Skip to content

Brazil Territorial Crosswalk

Brazil's IBGE, TSE and Receita Federal codes reconciled — plus CEP-to-municipality, resolved from observed addresses.

5,571

current municipalities

931,499

CEPs resolved to a municipality

Numbers as of September 2026, checked against the listing documentation.

1. The problem

Brazil has at least four territorial code systems that don't talk to each other: the 7-digit IBGE code (the statistical standard), the 6-digit IBGE code (used by DATASUS, the health system, and legacy systems), the TSE code (all electoral data), and the Receita Federal code — the bridge to the CNPJ business registry, the same code the Treasury republishes as the "SIAFI code".

Cross-referencing electoral data with economic data, or health data with a business registry, means translating between them. Every data team in Brazil has already lost a week to this.

And there's a second, quieter problem: a CEP is not a municipality. Most of the market resolves CEP by numeric range, which works almost always and fails without warning when it doesn't.

2. What's published, and what isn't

Every agency publishes its own table, and they're all correct. IBGE publishes the territorial division, TSE publishes its own codes, Receita maintains the table of agencies and municipalities.

What isn't published is the table linking one to another — nor the historical series of what happened to a municipality that changed code, name or state.

3. How the data is built

Every match is by official code, never by name. There's no fuzzy matching anywhere in the logic. Municipality names diverge between agencies in dozens of cases — accents, abbreviations, articles — and matching by name produces errors that don't show up in a row-count test.

The IBGE ↔ Receita bridge is validated against an independent publication. The Treasury publishes the same code through a different channel, and the two agree on 5,570 of 5,570. The check runs on every publication: two agencies publishing the same data through independent paths, and it's real validation, not an internal double-check.

CEP resolution is observed, not inferred. Each CEP is assigned to the municipality where its addresses actually fall, counted from the national address registry. That makes it possible to state two things a range table can't:

  • what share of addresses falls in the assigned municipality
  • which CEPs cross a municipal boundary — which happens in practice

The historical series preserves the name and state of the time, and distinguishes "the source wrote it without an accent" from "we normalized it" — two things that, without a column to separate them, become indistinguishable.

4. What this data does NOT do

  • Doesn't convert between two historical editions. It covers any year to the current one.
  • Doesn't resolve street address, only CEP to municipality.
  • Has no population by year. It carries the 2022 Census figures — and one municipality doesn't have one: Boa Esperança do Norte, in Mato Grosso, was created after the census. The dataset states this instead of letting the total silently fail to add up.
  • It's 5,571 municipalities, not 5,570. The number that circulates has been out of date since January 1st, 2025.

5. How we know it's correct

Besides the cross-validation between Receita and the Treasury:

Conversion weights sum to exactly 1 per origin, which guarantees that converting a summable quantity preserves the total.

There's a versioned quality statement, checked against the data on every publication. When the dataset claims a number about itself, a test measures and compares.

Every partial coverage is declared in its own column. If a municipality has no Treasury code, there's a boolean that says so — not a null for the consumer to interpret.

6. Access

Published on the Snowflake Marketplace, free of charge.

Sources: IBGE, the Superior Electoral Court (TSE), Receita Federal and the National Treasury Secretariat — federal open data, free to use. The attribution each requires travels with the data.

7. Found a problem, or want to know when the data changes?

A reported error is more useful than one nobody found: hi@insigne.tech.

The newsletter. Every change to the data raises the dataset version and enters a changelog, which goes out through it. But it isn't only that: it's also where the making-of these datasets comes out, and what we learn working with public data — which almost never arrives ready to use.

An occasional email, no noise.

No spam. Unsubscribe anytime. Privacy policy

Public data rarely arrives in the shape you need it. This crosswalk exists because a project needed it and it didn't exist.

If your case sounds similar, that's what we do.