Postal Codes Dataset for Switzerland, CH

385
Updated:
Files:1
Size:728 kB
Rows:5,972
Formats:csv

Postal Codes Dataset for Switzerland, CH 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
  • opendata.swiss terms of use, open tier (commercial use permitted, attribution recommended) license
20% off
$99.90$79.92
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-ch/
https://datahub.io/logistics/postal-codes-ch/_r/-/.licensing-notes.md
https://datahub.io/logistics/postal-codes-ch/_r/-/.migration-notes.md
https://datahub.io/logistics/postal-codes-ch/_r/-/ATTRIBUTION.txt
https://datahub.io/logistics/postal-codes-ch/_r/-/README.md
https://datahub.io/logistics/postal-codes-ch/_r/-/datapackage.yaml
Key Files

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

datapackage.yaml— metadata & schema
https://datahub.io/logistics/postal-codes-ch/_r/-/datapackage.yaml
README.md— documentation
https://datahub.io/logistics/postal-codes-ch/_r/-/README.md
Typical Usage
  1. 1. Fetch datapackage.yaml to inspect schema and resources
  2. 2. Download data resources listed in datapackage.yaml
  3. 3. Read README.md for full context

Data Files

postal-codes-ch-sample


About this dataset

Switzerland (CH): 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.10 (closed 2026-10-03)
  • Commit: 8947b96 (worktree commit 1f2124d, same content), landed in batch 3 after the user's sign-off (6c221ca)
  • Parity verdict: unexplained (the gate blocks on any unclassified cell); accepted by the user as upstream drift
  • Producer: custom, refresh disabled

Sources

InputURLNotes
swisstopo Amtliches Ortschaftenverzeichnis (WGS84 CSV)https://data.geo.admin.ch/ch.swisstopo-vd.ortschaftenverzeichnis_plz/ortschaftenverzeichnis_plz/ortschaftenverzeichnis_plz_4326.csv.zipBackbone. Stable "current release" URL, refreshed monthly; the file fetched was dated 2026-09-30. opendata.swiss terms_open
GeoNames postal exporthttps://download.geonames.org/export/zip/CH.zipOnly for the Bezirk (district) tier and for postal codes swisstopo doesn't list

Both are the inputs the old builder used.

Parity against the live zip (2026-10-02)

Rows: 5,974 live and 5,972 fresh. 2 rows only in live, 0 only in fresh. 1,377 rows changed, 2,535 cells, all unclassified: latitude 933, longitude 933, address_share_pct 669. No other column changed. PO-box/large-account rows: 276 on both sides.

Cause: swisstopo's monthly release has moved on since the live build (upstream drift).

RowsChangeCause
1149 Berolle / Bière (admin_code3 5425)only in liveThe current swisstopo file has no Bière slice of 1149 Berolle; Berolle's share went 99.574 → 100
9104 Waldstatt / Schwellbrunn (admin_code3 3004)only in liveThe current file has no Schwellbrunn slice; Waldstatt 99.496 → 99.697, Urnäsch 0.302 → 0.303
669 cellsaddress_share_pct re-normalisedSame: shares recomputed in the new release
933 rows (e.g. 1008 Prilly, 1012 Lausanne, 1020 Renens VD)coordinates shifted, e.g. Prilly latitude 46.5367525803778 → 46.536752484570144, longitude 6.604545982129699 → 6.604532947343865New swisstopo release. The examples move by about 1 m; the full distribution wasn't measured

The live CSV matches the old swisstopo values (e.g. Bière 0.426 %), so this is the source changing, not a missing transform. The agent did not tune the producer to hide it.

Decisions

DecisionByBasis
Accept the drift and land chUser (session 2479b1c9-…, 2026-10-03, AskUserQuestion "ch/fi drift" → "Accept both")Recorded in the sign-off section of docs/parity/p5.md
Fetch swisstopo's stable "current release" URL rather than a dated oneAgentswisstopo publishes no dated URL; the docstring says so
Remove row, distinct-PLZ, split-locality, district-fill and PO-box row counts from README and descriptor; "duplicates 0" → "the producer checks it is unique"Orchestrator instruction (the README counts rule, user 2026-10-02)Kept the 26 cantons and 2,112 municipalities
Replace the README's licence_status.decision sentence with "both licences permit commercial use"AgentNo such field in the descriptor (same fix as batch 1)

Transforms carried over

Folded from build_postal_codes_product.py (2026-09-16 rebuild):

  • swisstopo locality rows are the backbone. Locality rows split across municipalities stay as one row per municipality, with their address share ("84.138 %" → "84.138").
  • admin_code1 = CH- + swisstopo's Kantonskürzel (the ISO 3166-2:CH suffix); admin_name1 is the ISO canton name.
  • Liechtenstein rows (blank Kantonskürzel, PLZ 9485–9499) are dropped.
  • The district comes from GeoNames, joined on the BFS municipality number (never on names). It is left empty where GeoNames gives a municipality more than one district (leftovers from mergers).
  • Postal codes in GeoNames but not in swisstopo (e.g. "Zofingen PF") are added with code_type = po_box_or_large_account.
  • accuracy and alternative_city_name are empty.
  • The old asserts are now ProducerErrors: 4-digit postal code, non-empty place name, no literal nan, known canton, unique (postal_code, place_name, admin_code3), all 26 cantons present. No row-count asserts.

Open questions

  • Resolved (user, 2026-10-05, pc-28e.7.59): gating of recurring swisstopo drift is left to the P8 refresh.yml design (comment on pc-28e.11). Refresh stays disabled until then.
  • ATTRIBUTION.txt still has "5,974 rows", the 276 PO-box rows and "93 rows carry no district value"; .licensing-notes.md has historical counts. Both are for pc-3d2 / pc-hfz.

Provenance

Reconstructed 2026-10-05 from the agent transcript 2479b1c9-c4dd-47e5-be82-34ccf8d49a80/subagents/agent-a88bf7f3ca81e1172.jsonl, the orchestrator session 2479b1c9-… (also checked d33e1b7e-…, 7df0c5be-…, 068ca403-…: no further ch decisions), the commit messages (8947b96, 6c221ca), the bd close reason and docs/parity/p5.md.