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 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.yml to inspect schema and resources
- 2. Download data resources listed in datapackage.yml
- 3. Read README.md for full context
Data Files
Postal Codes Data Resource for South Africa, ZA
| Field | Description | Title |
|---|---|---|
| country_code | ISO 3166-1 alpha-2 code for the country. | Country Code |
| postal_code | Postal code for the location. | Postal Code |
| place_name | Name of the city, town, or place. | Place Name |
| admin_name1 | Primary administrative division (e.g., state, region). | Administrative Name 1 |
| admin_code1 | Code for the primary administrative division. | Administrative Code 1 |
| admin_name2 | Secondary administrative division (e.g., county, district). | Administrative Name 2 |
| admin_code2 | Code for the secondary administrative division. | Administrative Code 2 |
| admin_name3 | Tertiary administrative division (e.g., municipality, borough). | Administrative Name 3 |
| admin_code3 | Code for the tertiary administrative division. | Administrative Code 3 |
| latitude | Latitude coordinate of the place. | Latitude |
| longitude | Longitude coordinate of the place. | Longitude |
| accuracy | Accuracy level of the latitude and longitude coordinates. | Accuracy |
| alternative_city_name | Alternative name(s) for the city or place. | Alternative City Name |
Download
Download sample CSVAbout
- Last updated
- 29 August 2026
- Total rows
- ...
- Format
- CSV
- File size
- 388 kB
About this dataset
South Africa (ZA) — internal licensing notes
Source research, 2026-08-28 — sellability + reproducibility audit
GeoNames is the only source that is both legally sellable and reproducible — same shape of finding as Albania — but here it carries a much larger gap: it has ZERO administrative-division data for South Africa, not a reduced amount.
The only usable source — GeoNames ZA
https://download.geonames.org/export/zip/ZA.zip # 26 KB, 3,920 rows
Licence CC-BY-4.0, verified against export/zip/readme.txt on
2026-08-28 — South Africa carries no per-country caveat.
Verified directly against the raw source file (not the corrupted R2
export): admin_name1, admin_name2, and admin_name3 are empty on
every single one of the 3,920 rows in GeoNames' own ZA.txt. This is
not a pandas-round-trip bug like TH/RO/AL — GeoNames genuinely carries no
province, district, or municipality data for South Africa at all. Only
postal_code, place_name, latitude, longitude, accuracy are ever
populated. 3,266 distinct postal codes across 952 distinct place names — the
coordinates are coarse city/town-level points (e.g. every Pretoria-area code
from 0002–0006 shares the exact point -25.7069, 28.2294), not per-code
locations.
The official source — SAPO — is explicitly closed, not merely unresolved
The South African Post Office (SAPO) maintains the authoritative postal code
list but its own website terms of use require prior written permission for
commercial use — this was checked directly (Open Knowledge's Global Open
Data Index review of SA postcodes, 2015, quotes SAPO's own ToU to this
effect) and is a clean decision: "incompatible", not "unresolved". Also
not machine-readable in bulk (XLS only, not a downloadable dataset). Do not
re-attempt scraping SAPO for a commercial product.
Ruled out — do not re-attempt without new evidence
| Candidate | Verdict | Why |
|---|---|---|
| SAPO official list | ❌ incompatible | Own ToU requires prior written permission for commercial use (verified via Open Knowledge Index citation of SAPO's terms). Not bulk-downloadable in any case. |
| AfriGIS | ❌ not sellable | Privately owned commercial dataset; no open licence. |
| opendb.co.za | ❌ unresolved, and smaller | Downloadable CSV (1,357 rows — fewer than GeoNames' 3,920) with province/municipality fields, but its own Terms and Conditions page states nothing about licensing data downloads and nowhere discloses where OpenDB itself sources the data. Same shape as Mauritius' youbianku.com case: a genuine absence of stated terms, not a confirmed grant — decision: "unresolved" at best, and the row-count regression makes it a poor trade even if accepted. |
| raramuridesign-cc/South-African-Postal-Codes (GitHub) | ❌ licence-laundering risk | Repo itself carries a GPL-3.0 LICENSE file, but nowhere states where postcodes-za.csv was originally sourced. A GPL licence on the repository cannot grant rights the uploader never held over the data, and GPL is also a poor fit for data redistribution generally (copyleft software licence, not a data licence). Same failure shape as the TH kongvut/Albania-HDX traps already documented in this catalog: an asserted permissive container licence over unverified data provenance. |
| DataWookie/saffeR (GitHub R package) | ❌ same trap | MIT-licensed package, but its postalcodes dataset (province, area, suburb, boxcode) has no cited source anywhere in the README or docs — the only postal-code link in the repo points to Wikipedia's postal-codes article as a suggested reference for readers, not as the dataset's actual provenance. |
| Wikipedia "List of postal codes in South Africa" | ❌ doesn't exist as a list | Despite the title, this page contains no per-code or per-range table — it redirects to the general "Postal codes in South Africa" article, which only explains the format with two or three illustrative examples. Nothing to extract. |
| Municipal Demarcation Board (MDB) | ⚠️ different geography, not evaluated further | Publishes real official municipal/ward boundary shapefiles, but these are administrative boundaries, not postal boundaries, and don't align with postal code areas. Using them would require a full point-in-polygon spatial join against postal-code coordinates — and GeoNames' own ZA coordinates are too coarse for that to be meaningful (952 distinct points shared across 3,920 codes). MDB's own redistribution licence was not confirmed (site's terms-of-use page did not resolve during this research pass — cert error). This is a large, separate geocoding-style build, not a quick fix; not attempted this pass. |
HDX — South Africa Subnational Administrative Boundaries (cod-ab-zaf) | ⚠️ not checked, flagged by pattern | Page returned HTTP 403 during this research pass, so its methodology/licence fields could not be verified directly. Given Albania's HDX entry in this same catalog traced back to GADM (non-commercial) despite a permissive package-level licence label, treat this with the same suspicion until actually read — do not assume it is clean. |
What this means for the product
A GeoNames-only rebuild is legally sellable (CC BY 4.0, unambiguous) and
would fix the current file's defects, but the result is a much thinner
product than usual: postal_code, place_name, latitude, longitude,
accuracy only — every admin_name*/admin_code* field ships empty, not
because of a build limitation but because no commercially licensable source
carries South African admin-tier data at all. This is a genuine product-
quality ceiling, not a licensing block.
Defects in the currently-published file
za/za.csv on R2 is a GeoNames re-export (row count matches ZA.zip
exactly: 3,920) round-tripped through pandas and corrupted:
admin_name1/admin_name2/admin_name3are the literal stringnanon every row. As established above, GeoNames' own source has these genuinely empty — thenanstring is the round-trip artifact, but the underlying emptiness itself is real and does not resolve with any licensable source found.- Integer
accuracywritten as float (4→4.0); many rows blank. - 3,920 rows but only 3,266 distinct postal codes — check duplicates
against the primary key rule before publishing (distinct on
(postal_code, place_name)is expected to be clean; verify at build time).
Attribution is absent from the sold product. R2 carries only
za/za.csv — no README.md, datapackage.json, ATTRIBUTION.txt or
za.zip. The repo datapackage.yml lists sources: [{title: "Multiple sources"}] with no licenses[]. CC BY 4.0 attribution is a licence
condition — live breach on a paid product.
datapackage.yml also sets is_premium: true with no premium_tier and
no premium_source_key, and no zip exists in R2 for a key to point at.
licence_status (proposed — needs human sign-off before shipping)
{
"channel": "postal-codes-r2",
"components": [
{
"field_group": "postal_code, place_name, latitude, longitude, accuracy",
"source_url": "https://download.geonames.org/export/zip/ZA.zip",
"licence_id": "CC-BY-4.0",
"collected_at": "2026-08-28",
"decision": "compatible",
"decided_by": "claude-session-2026-08-28",
"decided_at": "2026-08-28"
},
{
"field_group": "admin_name1/2/3, admin_code1/2/3",
"source_url": null,
"licence_id": null,
"collected_at": "2026-08-28",
"decision": "no_source_found",
"decided_by": "claude-session-2026-08-28",
"decided_at": "2026-08-28",
"note": "Not 'unresolved' in the usual sense of an unread ToU -- every candidate source was checked and individually ruled out (SAPO incompatible, others unresolved-provenance or wrong-geography). Ships empty, not guessed."
}
]
}
Proposed tier
B ($49) at most, and worth a deliberate human decision on whether B is even justified given how thin the product is (5 of 13 columns real content, 0 of 8 admin columns populated). This is a weaker product than AL (which at least carries qark+bashki), despite ZA usually being thought of as a bigger, more developed market. Do not price it as A — there is no second source consolidated onto it, only a single-source cleanup, and the admin gap is not something a human sign-off can wave through since no licensable source exists to fill it.
Verdict (superseded below — see Build, 2026-08-29)
Possible, but weak. GeoNames-only is buildable and legally sellable
today — same mechanical fix as TH/RO/AL (rebuild via csv, not pandas, fix
the nan literals and float accuracy). It should NOT be marketed as
carrying province/municipality data, because it doesn't and no licensable
source was found that provides it. If a real admin tier is wanted later, the
MDB spatial-join path is the only remaining lead, and it is a substantial
separate build (geocoding-shaped, not a normalisation), not a quick follow-up.
Build — 2026-08-29 (local only, not published)
Human asked to fill the admin-tier gap using AfriGIS. Checked first: AfriGIS
is a paid, API-key-gated commercial geocoding service
(developers.afrigis.co.za, 50M+ address records), not a downloadable
dataset — no API credentials exist anywhere in this environment (.env,
.env.template checked), and bulk-querying a commercial geocoding API to
build a cached, resold reference dataset is the same shape of ToS
violation this project already blocks for Nominatim (see CLAUDE.md's
OSM/Nominatim gate — "systematic queries… reselling of geocoding
results" is expressly prohibited by that class of provider). Presented
this to the human; instruction was to skip AfriGIS and look for other
sources instead.
Found one, and it was hiding in a source already in hand. GeoNames
publishes TWO separate exports: the postal export (export/zip/ZA.zip,
zero admin fields, already established above) and a general-purpose
gazetteer dump (export/dump/ZA.zip) — same publisher, same CC BY 4.0
licence, not a new source or a new licensing question. The dump DOES carry
full South African admin data: 9 provinces and 52 district/metro
municipalities, via admin1CodesASCII.txt / admin2Codes.txt, populated
on 12,875 of its own populated-place entries.
Built a same-source join: postal row's place name matched against the gazetteer (disambiguating common names that repeat across provinces by nearest coordinate), falling back to pure nearest-neighbour search where no name matches at all. Measured directly before shipping:
| value | |
|---|---|
| Final rows | 3,920 (unchanged from source) |
| Distinct postal codes | 3,266 |
| Exact-name-match rows (median 1.2 km, p90 5.9 km from matched point) | 2,879 |
| Coordinate-fallback rows, no name match (median 1.1 km, max 44.1 km) | 1,041 |
| Rows left unresolved | 0 |
| Provinces covered | 9/9 |
| Districts/metro municipalities covered | 52/52 |
Verified the join on a spot check (postal code 0002/0003/0004/0005, Pretoria → Gauteng → City of Tshwane Metropolitan Municipality) before trusting it at scale.
This is disclosed as a coordinate-based join against GeoNames' own
gazetteer, not an official South African administrative register — high
confidence, not authoritative in the register sense. Stated explicitly in
README.md/ATTRIBUTION.txt/datapackage.json, not silently upgraded to
look like government data. admin_code2 values are GeoNames' own internal
identifiers (e.g. "DC32", "ETH"), not an independently verified official
municipal code registry — also disclosed rather than presented as
authoritative.
admin_code1 derived to ISO 3166-2:ZA via a verified crosswalk (Wikipedia,
checked 2026-08-29) from GeoNames' internal admin1 numbering — GeoNames'
own admin1 codes (ZA.02, ZA.03, …) are not themselves ISO codes.
Frictionless validation: valid: True.
Verdict (final)
Ship it as tier B, with the join method disclosed. This is a meaningfully stronger product than the original GeoNames-only proposal — 9/9 provinces and 52/52 districts recovered, not zero — at no new licensing cost (same publisher, same CC BY 4.0). Still single-source in the tier sense (both exports are GeoNames), so B ($49), not A: real derivation work (the gazetteer join) but no second authoritative provider consolidated onto it.
Status: built and validated locally only. Nothing published to R2,
nothing committed to git. datasets/za/README.md and datapackage.yml
updated in place (tier B, premium_source_key: za/za.zip, real
sources/licenses, replacing the "Multiple sources" placeholder and the
broken is_premium: true with no tier/key that was live on R2 before this
build). The previously-flagged live breach (broken paid product, missing
attribution files) is fixed in this local build but the fix has not been
published — R2 still serves the old defective file until someone runs the
publish step.