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.
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
Explore with AIpostal-codes-ug
| Field | Type | Description | Title |
|---|---|---|---|
| country_code | string | ISO 3166-1 alpha-2 -- always UG | Country Code |
| postal_code | string | Always empty -- Uganda has no bulk-fetchable national postal code system (a real 5-digit code is rolling out via a government-app concession, but no bulk export or API exists). Not a data gap; see ATTRIBUTION.txt. | Postal Code |
| place_name | string | Locality/place name (GeoNames populated place) | Place Name |
| admin_name1 | string | Region -- all 4 covered; blank where GeoNames assigns a place to no region | Administrative Name 1 |
| admin_code1 | string | ISO 3166-2:UG region code (GeoNames' own code already matches exactly) | Administrative Code 1 |
| admin_name2 | string | Not populated in this release -- ISO 3166-2:UG also defines district-level codes, not attempted here | Administrative Name 2 |
| admin_code2 | string | Not populated | Administrative Code 2 |
| admin_name3 | string | Not populated | Administrative Name 3 |
| admin_code3 | string | Not populated | Administrative Code 3 |
| latitude | number | GeoNames latitude (WGS84) | Latitude |
| longitude | number | GeoNames longitude (WGS84) | Longitude |
| accuracy | string | Not populated -- the GeoNames gazetteer dump carries no accuracy field | Accuracy |
| alternative_city_name | string | Not populated in this release | Alternative City Name |
Download
Download CSVAbout
- Last updated
- 6 October 2026
- Total rows
- 11,455
- Format
- CSV
- File size
- 626 kB
About this dataset
Uganda (UG): migration notes
Internal record of the P6 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.8.24
- Commit: see
git log -- datasets/ug/(P6 ug commit on feat/single-source-of-truth, basee797eb1) - Parity verdict:
format-only(gate: pass, exit 0); CRLF→LF only - Producer:
custom, refresh disabled
Sources
| Input | URL | Notes |
|---|---|---|
| GeoNames gazetteer dump | https://download.geonames.org/export/dump/UG.zip | UG.txt, filtered to feature class P. The old builder read a local sources/UG_dump.txt snapshot of this file |
- Stable, unversioned GeoNames URL. The fetch date and sha256 are recorded in
ug.inputs.json;--no-fetchreuses the cache. - Uganda has no bulk-fetchable postal-code system and GeoNames has no postal export for UG (
export/zip/UG.zipis a 404), sopostal_codeis empty on every row.pipeline.postal_code_required: falsetells build.py this is intended. - The old builder used no admin1 table: its region names are a fixed table in the script, kept as-is in the producer.
Parity against the live public CSV (2026-10-05)
Rows: 11,455 live and 11,455 fresh, none only on one side, 0 changed cells, no cell classes. Once CRLF is normalised to LF the fresh ug.csv is byte-identical to the live CSV, including row order. Live sha256 aa7147c8…, fresh bf9a613d… (the only difference is line endings).
No discrepancies to explain. The dump at migration time has 2 populated places on the reserved admin1 code 00 (Kabende, Kagera), shipped with blank region as before; no populated place has a blank admin1 cell.
Decisions
| Decision | By | Basis |
|---|---|---|
| Accept the CRLF→LF difference | Standing rule (P5 sign-off: row_order/CRLF-only pre-approved) | Equal rows, 0 changed cells |
| Drop the minimum-count assert (>= 9,000 places) | P6 brief | Replaced by structural checks: all 4 regions present, primary key unique, only known admin1 codes |
A blank admin1 cell is treated like 00 (blank region) | Agent: port choice | The old builder's assert would have refused it; same handling as bj. Does not occur in the current dump |
latitude/longitude typed number; accuracy stays string | Agent, per the brief | accuracy is empty on every row (the gazetteer dump has no accuracy field), so it gets no GeoNames accuracy description |
primaryKey: [place_name, admin_name1, latitude, longitude] | Agent, from the produced CSV | Unique in the produced CSV; it is the old builder's own PK. (place_name, latitude, longitude) is also unique today, but the old key was kept |
pipeline.postal_code_required: false | Agent, per the brief | postal_code is empty on every row |
| Field descriptions taken from the old builder's datapackage.json (minus counts) | Agent | The P3 generic descriptions said "Postal code for the location", which is wrong for ug. The "134 district codes" count was dropped from the admin_name2 description |
| README: "11,455 places" → "populated places" | P6 brief (count rule) | Otherwise unchanged; it was not a stale stub and had no licence_status line |
Transforms carried over
From build_postal_codes_product.py:
- Feature class
Ponly;place_nameis the dump'snamecolumn; latitude/longitude copied verbatim. admin_code1=UG-+ GeoNames admin1 code (C/E/N/W, identical to ISO 3166-2:UG);admin_name1from the fixed region table.- Reserved admin1
00→ blank admin_name1/admin_code1; any other unknown code stops the build. postal_code,accuracy,alternative_city_nameand admin tiers 2–3 empty.- Sorted by (admin_code1, place_name), ties in dump order.
- Not ported: the old builder's own datapackage.json, README, ATTRIBUTION and zip writing (build.py / committed docs handle those) and
publish_r2.py.
Open questions
- None needing the user.
.licensing-notes.mdstill carries dated counts and an outdated "0-row placeholder" description; left for pc-hfz.