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-ua-sample
| Field | Type | Description | Constraints | Title |
|---|---|---|---|---|
| country_code | string | ISO 3166-1 alpha-2 -- always UA | Country Code | |
| postal_code | string | Ukrainian postal code (5 digits) | { "pattern": "^\\d{5}$" } | Postal Code |
| place_name | string | Locality/place name (Cyrillic), as GeoNames' postal export records it | Place Name | |
| admin_name1 | string | Oblast / city-with-special-status -- 26/27 covered, resolved via a coordinate-based join against GeoNames' own gazetteer, see ATTRIBUTION.txt | Administrative Name 1 | |
| admin_code1 | string | ISO 3166-2:UA code | Administrative Code 1 | |
| admin_name2 | string | Raion (district) -- 130/136 covered; empty for Kyiv City and Sevastopol City, which are not subdivided into national raions | Administrative Name 2 | |
| admin_code2 | string | GeoNames' own raion code (not an independently verified official code) | Administrative Code 2 | |
| admin_name3 | string | Not populated -- no source reaches a third tier nationally | Administrative Name 3 | |
| admin_code3 | string | Not populated | Administrative Code 3 | |
| latitude | number | GeoNames postal-export latitude (WGS84) | Latitude | |
| longitude | number | GeoNames postal-export longitude (WGS84) | Longitude | |
| accuracy | string | AREA throughout -- coarse city/town-level point, shared across all codes in that place | Accuracy | |
| alternative_city_name | string | Not populated in this release | Alternative City Name |
Download
Download sample CSVAbout
- Last updated
- 2 October 2026
- Total rows
- 100
- Format
- CSV
- File size
- 5.72 kB
About this dataset
Ukraine (UA): 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.55 (closed 2026-10-02)
- Commit:
e4ba518(worktree commit92b4f3a, same content), landed in batch 3 - Parity verdict:
explained(row_orderonly); signed off under the standing rule - Producer:
custom, refresh disabled
Sources
| Input | URL | Notes |
|---|---|---|
| GeoNames postal export | https://download.geonames.org/export/zip/UA.zip | |
| GeoNames gazetteer dump | https://download.geonames.org/export/dump/UA.zip | Populated places (class P) with admin1/admin2 |
| GeoNames admin2 codes | https://download.geonames.org/export/dump/admin2Codes.txt | Raion names. Added to the descriptor's sources in this commit |
The old builder read all three from local files; the producer now fetches them. Ukrposhta has no bulk download, only a single-address lookup (.licensing-notes.md, 2026-08-31).
Parity against the live zip (2026-10-02)
Rows: 29,571 live and 29,571 fresh, none only on one side. 0 changed cells. The only class is row_order: places sharing a postal code come out in a different order (e.g. 10421 Субине / Горбачі, and Батьківщина / Булахівка, swapped). A line-by-line diff showed 1,912 positions differing; keyed on (postal_code, place_name) the rows are identical. The live CSV is already LF.
The informational sample check against https://postal.datahub.io/ua/ua.csv came back unexplained. It is outside the gate and was not traced.
Decisions
| Decision | By | Basis |
|---|---|---|
Accept the row_order verdict and land | Standing rule (row_order/CRLF-only, user, 2026-10-02) | Equal rows, 0 changed cells |
| Replace the old brute-force nearest-place scan with a grid search | Agent | Exact distance bound, ties to the first dump entry, so the same place is picked; ~5 s instead of minutes. Parity shows 0 changed cells |
| "Every region present" check exempts Sevastopol | Agent | GeoNames has no Sevastopol postal codes |
Keep the existing accuracy description, not the standard GeoNames wording | Agent | The column is the constant AREA, not a GeoNames code. Not put to the user |
| Remove the row and distinct-code counts; keep 26/27 regions and 130/136 raions | Orchestrator instruction (the user's README counts rule) | |
Drop the README sentence "licence_status.decision is compatible" | Orchestrator instruction | Brief: no such field |
| No row-count assert | Orchestrator instruction | Brief: structural checks only |
Transforms carried over
From build_postal_codes_product.py (2026-08-31):
- Each postal row is joined to a gazetteer populated place by name against the dump's name, asciiname and each alternatename (postal names are Cyrillic, name/asciiname Latin; matching only those matched nothing). Nearest same-named place within 50 km, else the nearest place of all within 100 km; otherwise an error.
- GeoNames admin1
01–27→ English name and ISO 3166-2:UA via the 27-region crosswalk (e.g.05Donetsk → UA-14). admin_name2from admin2Codes.txt,admin_code2is GeoNames' own raion code; both empty for Kyiv City and Sevastopol City.admin_name3/admin_code3andalternative_city_nameempty; accuracyAREA; latitude/longitude rounded to 5 dp; stable sort by postal_code.- The old asserts are now
ProducerErrors: 12-column UA rows, 5-digit codes, no literal "nan", every row resolved within the fallback, every region but Sevastopol present, unique (postal_code, place_name).
Open questions
ATTRIBUTION.txtstill carries the old join counts (e.g. 20304 exact-name rows, 9267 fallback rows); it belongs to the pc-hfz sweep.
Provenance
Reconstructed 2026-10-05 from the agent transcript 2479b1c9-c4dd-47e5-be82-34ccf8d49a80/subagents/agent-a4c7e115fb7db5133.jsonl, the orchestrator session 2479b1c9-… (also checked 068ca403-… and 803a95aa-…: no ua decisions), the commit message, the bd close reason and docs/parity/p5.md.