Part of a Data Solution
- Explore →
Postal Codes Solution
Every worldwide postal-code dataset in one bundle — the ultimate global reference for precise postal codes.
Premium
You're viewing a free sample
Get the complete dataset — all rows and files — delivered instantly after checkout, with lifetime access to the latest version.
- Secure checkout via Stripe
- Instant download after payment
- Lifetime access to the latest version
- Creative Commons Attribution 4.0 International license
API Access
Access dataset files directly from scripts, code, or AI agents.
Browse dataset files
API Access
Access dataset files directly from scripts, code, or AI agents.
Each file has a stable URL (r-link) that you can use directly in scripts, apps, or AI agents. These URLs are permanent and safe to hardcode.
Start with these files — they give you everything you need to understand and access the dataset.
- 1. Fetch datapackage.yaml to inspect schema and resources
- 2. Download data resources listed in datapackage.yaml
- 3. Read README.md for full context
Data Files
postal-codes-mx-sample
| Field | Type | Description | Constraints | Title |
|---|---|---|---|---|
| country_code | string | ISO 3166-1 alpha-2 -- always MX | Country Code | |
| postal_code | string | Mexican postal code (5 digits) | { "pattern": "^\\d{5}$" } | Postal Code |
| place_name | string | Colonia (neighbourhood) name from GeoNames -- empty on rows recovered only from SEPOMEX's official code list (no name in that source) | Place Name | |
| admin_name1 | string | State (32 federal entities) | Administrative Name 1 | |
| admin_code1 | string | ISO 3166-2:MX code | Administrative Code 1 | |
| admin_name2 | string | Municipio, from GeoNames | Administrative Name 2 | |
| admin_code2 | string | GeoNames municipio code | Administrative Code 2 | |
| admin_name3 | string | From GeoNames -- equals admin_name2 on roughly a fifth of rows, a distinct sub-municipal value on the rest, per the source | Administrative Name 3 | |
| admin_code3 | string | From GeoNames | Administrative Code 3 | |
| latitude | number | SEPOMEX official polygon centroid where available, else GeoNames-estimated | Latitude | |
| longitude | number | See latitude | Longitude | |
| accuracy | string | POSTAL_CODE where sourced from a SEPOMEX official polygon centroid; otherwise GeoNames' own code (1=estimated, 4=gazetteer match, 6=centroid of addresses/shape) | Accuracy | |
| alternative_city_name | string | Not populated in this release | Alternative City Name |
Download
Download sample CSVAbout
- Last updated
- 12 October 2026
- Total rows
- 100
- Format
- CSV
- File size
- 11.5 kB
About this dataset
Mexico (MX): migration notes
Internal record of the P5 migration. This is a dated record (2026-10-12) and is not shipped in the zip.
- Issue: datopian/postal-codes#41 (pc-28e.7.36)
- Producer:
scripts/produce.py(+test_produce.py),pipeline: producer: custom, refresh disabled - Parity: the content is identical to the live zip: 150,472 rows both sides, 0 rows only in one, 0 changed cells (0.000%). The repo's parity tool reports
unexplained: row order differs, and it finds 5 duplicate keys in both files (see below)
What the producer does
It re-implements the old build_postal_codes_product.py (GeoNames base + SEPOMEX polygon centroids and extra codes) and the serial, verified download of fetch_sepomex.py. GeoNames MX.zip is fetched live. The SEPOMEX shapefiles (32 states, CC BY 4.0 per the datos.gob.mx dataset page) are discovered through the CKAN API and downloaded serially, each archive tested.
The SEPOMEX host is blocked from our network. www.datos.gob.mx, repodatos.atdt.gob.mx and the Correos site return an Akamai 403 (or time out) from this network since about 2026-10; third-party probes from US, German, Dutch, French and Brazilian datacentres were refused too, and the download URLs did not move (Wayback). So the producer tries the official site, then our private R2 mirror of the 2026-08-28 snapshot, then (development only) the files already in sources/sepomex_shp/. Every fallback is printed and recorded as served_from in data/mx.inputs.json.
The mirror (mx/_sources/sepomex/2026-08-28/ in the premium bucket, private): sepomex_shp.zip (64 files, the .shp and .dbf of the 32 states, byte for byte as downloaded; the .shx index and .prj are not read, and all 32 .prj were identical anyway) and manifest.json (sha256 per file, source URL, licence statement, snapshot date). The zip is deterministic and its sha256 is pinned in produce.py, so a changed or corrupt mirror is refused. Snapshots are immutable: a new one gets a new dated prefix, never an overwrite. A projection change would put centroids outside Mexico, which load_sepomex rejects.
Taking a new SEPOMEX snapshot (when the site is reachable from some network)
- Download the 32 state archives into
sources/sepomex_shp/(the producer does this itself when the official site answers; copy the.shpand.dbffiles out ofsources/). produce.load_custom(...).build_package("sources/sepomex_shp")returns the deterministic zip and its manifest (sha256 per file). Build it twice and compare to be sure it is reproducible.- Upload both under a new dated prefix
mx/_sources/sepomex/<date>/in the premium bucket with any S3 client (never overwrite an old snapshot). - In
produce.pysetSNAPSHOT_DATEandMIRROR_SHA256, run a build, compare it with the live file, and note the differences here.
The upload tool used for the first snapshot (scripts/publish_mirror.py, dry run by default, refused to overwrite) was removed once the snapshot was uploaded; it is in the git history of this branch.
Measurements (2026-10-12, live GeoNames + the 2026-08-28 shapefiles)
| Check | Result |
|---|---|
| Rows | 150,472 live, 150,472 new; 38,265 distinct codes both |
| Only in one side / changed cells | 0 / 0 |
| accuracy tiers | POSTAL_CODE 146,977, "4" 1,627, "1" 1,436, "3" 432: identical |
Why unexplained | row order differs (same multiset of rows), and the tool's case-insensitive key sees 4-5 name pairs that differ only in case (e.g. "Rancho Las Conchitas" / "Rancho las Conchitas"), in both files: an inherited GeoNames trait, not a change |
| Producer run through the REAL R2 mirror, empty cache, official site blocked | 150,472 rows in 329 s (130 MB download at about 0.4 MB/s); output byte-identical to the run from the local shapefiles; 0 differences from live |
| Tests | 20 new (synthetic shapefiles, blocked-host fallbacks, corrupt archive retry, mirror hash, outside-Mexico check) |
GeoNames has not changed the Mexico rows since the live build, so there is no drift to explain.
Decisions
| Decision | By | Basis |
|---|---|---|
| Build the producer from the saved shapefiles, not a GeoNames-only file | Owner, 2026-10-12 | GeoNames-only would drop 5,817 codes (15%) and the POSTAL_CODE coordinates |
| Ship under CC BY 4.0 | Owner, 2026-10-12 | see .licensing-notes.md |
Open
- The mirror was uploaded 2026-10-12 (
mx/_sources/sepomex/2026-08-28/, zip 129,200,910 B, manifest 9,103 B). A real run through it (official site blocked, empty local cache, zip downloaded from R2 and checked against the pinned sha256) gave 150,472 rows in 329 s on this slow link, identical to the live file and to the local-shapefile run. - Owner confirmed 2026-10-12 that the premium bucket is private (so the mirror under
mx/_sources/is not public). - The snapshot is dated; the official dataset page lists the data as updated 2025-07-29 and its metadata 2026-01-29, so refreshes appear rare.