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
- Open Government Licence v3.0 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-gb-sample
| Field | Type | Description | Constraints | Title |
|---|---|---|---|---|
| country_code | string | ISO country code — always GB | { "pattern": "^GB$", "required": true } | Country Code |
| postal_code | string | Unit postcode, e.g. AL1 1AG | { "pattern": "^[A-Z]{1,2}[0-9][A-Z0-9]? [0-9][A-Z]{2}$", "required": true } | Postal Code |
| place_name | string | Nearest GeoNames populated place (town/locality) | Place Name | |
| admin_name1 | string | Country: England / Scotland / Wales | Administrative Name 1 | |
| admin_code1 | string | Country GSS code (E92/S92/W92) | Administrative Code 1 | |
| admin_name2 | string | District / unitary authority / borough / council area | Administrative Name 2 | |
| admin_code2 | string | District GSS code (E06/E07/E08/E09/S12/W06) | Administrative Code 2 | |
| admin_name3 | string | Electoral ward | Administrative Name 3 | |
| admin_code3 | string | Ward GSS code (E05/S13/W05) | Administrative Code 3 | |
| latitude | number | WGS84 latitude (converted from BNG) | Latitude | |
| longitude | number | WGS84 longitude (converted from BNG) | Longitude | |
| accuracy | string | OS positional quality indicator (10 = highest; 90 = no coordinate) | Accuracy | |
| alternative_city_name | string | Not available in source — empty | Alternative City Name | |
| admin_county_code | string | Extra: two-tier England county GSS code (E10); blank for single-tier areas | ||
| admin_county_name | string | Extra: two-tier England county name | ||
| easting | integer | Extra: British National Grid easting (EPSG:27700) | ||
| northing | integer | Extra: British National Grid northing (EPSG:27700) |
Download
Download sample CSVAbout
- Last updated
- 3 October 2026
- Total rows
- 100
- Format
- CSV
- File size
- 13.7 kB
- Sources
- Ordnance Survey Code-Point Open (OGL) — postcodes, grid coordinates, GSS codes
- ONS Open Geography Portal (OGL) — LAD, Ward, County name-code lookups
- GeoNames GB (CC-BY) — nearest populated-place names
- License
- Open Government Licence v3.0
About this dataset
Great Britain (GB): migration notes
Internal record of the P5 migration from the old scripts to the producer: the discrepancies found, their causes, and who decided what. This is a dated record, so the numbers are as of the migration and not kept current. It is not shipped in the zip.
- Issue: pc-28e.7.23 (closed 2026-10-03)
- Commit:
20284af(worktree commit4c32157), landed in batch 5 - Parity verdict:
unexplained(the gate blocks on any unclassified cell); accepted as upstream drift plus two user decisions - Producer:
custom, refresh disabled
Sources
| Input | URL | Notes |
|---|---|---|
| OS Code-Point Open (CSV) | https://api.os.uk/downloads/v1/products/CodePointOpen/downloads?area=GB&format=CSV&redirect | OS Downloads API's stable latest-release URL, no account or key. 2026-08 release at migration time |
| ONS Local Authority Districts (April 2025) Names and Codes, V2 | https://open-geography-portalx-ons.hub.arcgis.com/api/download/v1/items/5779a9578f0e48ccacef6af41546b56b/csv?layers=0 | |
| ONS Counties (December 2025) Names and Codes in EN | same pattern, item 646a11ad90574e949fd0e9b12199f35f | |
| ONS Wards Names and Codes: May 2024, Dec 2022, Dec 2023, May 2025, May 2026 | same pattern, items 8b712468c9d1491e9d3d023c8408e1ea, 6d3a1a1cf24d4543965a9fef1dcf9c9d, 8e206a9475a9426491b68f096568cb8b, db1e8af0f59f4aaf8ec5d21afe8f26b0, 06bf0a5d7bc14148a347aa8517b2a945 | May 2026 is new (see Decisions) |
| GeoNames GB gazetteer dump | https://download.geonames.org/export/dump/GB.zip | Nearest populated place (feature class P) |
- The old scripts read hand-fetched files from
sources/; no download URL was recorded. The agent found the OS Downloads API URL and the ONS item ids through the ArcGIS search API. - The ONS lookups are fixed vintages, so their URLs don't move. A future Code-Point release on newer ward codes makes the producer stop with "ward code … isn't in the ONS lookups" until someone adds that vintage to
WARD_URLS.
Parity against the live zip (2026-10-03)
Rows: 1,747,841 live and 1,749,109 fresh. 2,237 only in live, 3,505 only in fresh. 157,082 rows changed, 332,536 cells, all unclassified. Line endings change from CRLF to LF.
Changed cells by column: admin_code3 120,103; admin_name3 59,577; latitude 37,802; longitude 38,087; easting 36,833; northing 36,726; place_name 2,874; accuracy 362; admin_code2 / admin_name2 68 each; admin_county_code / admin_county_name 16 each; admin_code1 / admin_name1 2 each.
How the agent showed the logic reproduces the old build:
- On every row whose easting/northing is unchanged, latitude/longitude match exactly (the pyproj BNG→WGS84 conversion matches).
- On every row whose GSS codes are unchanged, the district, ward and county names match (lookups and ward load order match).
| Rows / cells | Change | Cause |
|---|---|---|
| 2,237 only in live, 3,505 only in fresh (e.g. live-only AB10 1WS, AB11 8TU; fresh-only AB12 9HJ, AB15 8RG) | Postcodes terminated / added | Code-Point Open drift: live was built from an older release than 2026-08 (the live datapackage says created 2026-08-25) |
| 120,103 admin_code3, 59,577 admin_name3 | New ward codes | Code-Point drift. 119,895 rows carry May 2026 ward codes that live has none of, e.g. B14 4LJ: live E05001298 "Shirley West" → fresh E05016430 |
| ~36.8k easting/northing, ~38k lat/lon | Coordinates moved | Code-Point drift, e.g. AB10 1JR 393970,806184 → 393977,806177 (lat 57.146503 → 57.146440) |
| 362 accuracy | Positional quality changed | Code-Point drift, e.g. 325 × 50→10, 17 × 20→10, 12 × 50→20, 5 × 10→50 |
| 68 admin_code2/name2, 16 county, 2 admin_code1/name1 | Code changes | Code-Point drift (covered by the "names match where codes unchanged" check; the individual rows were not examined) |
| 1,659 place_name | Follows moved coordinates | Code-Point drift |
| 562 place_name on unchanged coordinates | e.g. BA15 1AA "Bradford-on-Avon" → "Bradford on Avon" (GeoNames renamed it 2026-09-14); B30 1JT Selly Oak → Bournville (Bournville entry modified 2026-09-21) | GeoNames dump drift. The agent ran the old SciPy cKDTree algorithm on today's dump; it also disagrees with live on these rows |
| 653 place_name on unchanged coordinates | e.g. AB37 9ES "Delnabo" → "Easter Gaulrig" (both at 57.21667, -3.38333); AB39 3AG Newtonhill → Skateraw | Tie-break between GeoNames places with identical coordinates (55 groups). The new code takes the first in file order; cKDTree's pick had no pattern (35 last, 17 first, 3 middle) |
1,659 + 562 + 653 = 2,874 place_name cells.
Decisions
| Decision | By | Basis |
|---|---|---|
| Accept the Code-Point Open and GeoNames drift | Standing rule (upstream drift traced to source, user, 2026-10-03) | Evidence above; recorded in the batch 5 sign-off in docs/parity/p5.md |
| Add the ONS Wards (May 2026) lookup | User, 2026-10-03 (session d33e1b7e, "Add May 2026 wards") | Without it, 119,895 rows (6.9%) fail the new unresolved-code check; the old builder would have left those ward names blank |
| Deterministic first-in-file tie-break for co-located GeoNames places, instead of matching SciPy's cKDTree | User, 2026-10-03 (session d33e1b7e, "Deterministic first-in-file") | SciPy isn't in the venv or requirements; cKDTree's tie pick is arbitrary and can shift with each dump. Changes 653 cells |
| Exact nearest-place grid search in NumPy (chord distance) rather than SciPy | Agent | Avoids adding scipy to requirements-producers.txt; agrees with cKDTree except on exact ties |
| Ward vintages unioned in the old build's actual load order (May 2024, Dec 2022, Dec 2023, May 2025, then May 2026; later wins) | Agent: a faithful port | The old code comment claimed a different order; the sorted-file-name order is what actually ran |
| Unresolved district/ward/county codes and a missing country now stop the build | Agent | New ProducerError checks |
Drop scripts/README.md and publish_r2.py; remove counts and the DATA_DICTIONARY.md / gb.zip entries from the README contents table | Agent | Counts rule; the built zip doesn't contain those files |
Transforms carried over
Folded from parse_codepoint.py → enrich_uk.py → fill_place_name.py → data_integrity_checker.py (restored 2026-08-25):
- Rows from every
Data/CSV/*.csvin the Code-Point zip, in sorted file order; cells stripped. - admin_code1 = CY, mapped to England / Scotland / Wales; admin_code2 = DC; admin_code3 = WC; admin_county_code = CC; accuracy = PQ; easting/northing verbatim.
- BNG (EPSG:27700) → WGS84 with pyproj, 6 decimals. Positional-quality 90 rows (0,0) get blank coordinates.
- Names joined on GSS code from the ONS lookups; the ONS UTF-8 BOM is stripped.
- place_name = nearest GeoNames populated place from the 6-decimal coordinate; rows without a coordinate have none. alternative_city_name is always empty.
- Old checker gates are
ProducerErrors: postcode pattern, unique postcode, known country code, GB bounding box. New: all three countries present, every district/ward/county code resolves.
Open questions
- None recorded from the agent beyond the two answered above.
ATTRIBUTION.txtstill has counts ("1,747,841 unit postcodes", "865 of 1,747,841", "31.9% of rows"), and.licensing-notes.mdhas historical counts. Left alone; they belong to the pc-hfz sweep.
Provenance
Reconstructed 2026-10-05 from the agent transcript d33e1b7e-5027-498a-a97f-ba914ee2524e/subagents/agent-ada3531935232a997.jsonl, the orchestrator session d33e1b7e-… (AskUserQuestion answers and close), the commit message, the bd close reason and the batch 5 sign-off in docs/parity/p5.md.