Postal Codes Dataset for South Africa, ZA

359
Updated:
Files:1
Size:388 kB
Formats:csv
License:CC-BY-4.0

Postal Codes Dataset for South Africa, ZA including name of the city, town, or place, various administrative divisions and alternative city names.

Part of a Data Solution

  • Postal Codes Solution

    Every worldwide postal-code dataset in one bundle — the ultimate global reference for precise postal codes.

    Explore →

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
10% off
$49.90$44.91
one-time payment

API Access

Access dataset files directly from scripts, code, or AI agents.

Browse dataset files
Dataset Files

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.

/logistics/postal-codes-za/
https://datahub.io/logistics/postal-codes-za/_r/-/.licensing-notes.md
https://datahub.io/logistics/postal-codes-za/_r/-/README.md
https://datahub.io/logistics/postal-codes-za/_r/-/datapackage.yml
Key Files

Start with these files — they give you everything you need to understand and access the dataset.

datapackage.ymlmetadata & schema
https://datahub.io/logistics/postal-codes-za/_r/-/datapackage.yml
README.mddocumentation
https://datahub.io/logistics/postal-codes-za/_r/-/README.md
Typical Usage
  1. 1. Fetch datapackage.yml to inspect schema and resources
  2. 2. Download data resources listed in datapackage.yml
  3. 3. Read README.md for full context

Data Files

Postal Codes Data Resource for South Africa, ZA


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

CandidateVerdictWhy
SAPO official listincompatibleOwn 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 sellablePrivately owned commercial dataset; no open licence.
opendb.co.za❌ unresolved, and smallerDownloadable 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 riskRepo 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 trapMIT-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 listDespite 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 furtherPublishes 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 patternPage 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:

  1. admin_name1/admin_name2/admin_name3 are the literal string nan on every row. As established above, GeoNames' own source has these genuinely empty — the nan string is the round-trip artifact, but the underlying emptiness itself is real and does not resolve with any licensable source found.
  2. Integer accuracy written as float (44.0); many rows blank.
  3. 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 rows3,920 (unchanged from source)
Distinct postal codes3,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 unresolved0
Provinces covered9/9
Districts/metro municipalities covered52/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.