Postal Codes Dataset for Poland, PL

429
Updated:
Files:1
Size:11.1 kB
Formats:csv
License:CC-BY-4.0

Postal Codes Dataset for Poland, PL 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-pl/
https://datahub.io/logistics/postal-codes-pl/_r/-/.licensing-notes.md
https://datahub.io/logistics/postal-codes-pl/_r/-/README.md
https://datahub.io/logistics/postal-codes-pl/_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-pl/_r/-/datapackage.yml
README.mddocumentation
https://datahub.io/logistics/postal-codes-pl/_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 Poland, PL


About this dataset

Poland (PL) — internal licensing notes

Source research, 2026-08-27 — sellability + reproducibility audit

The national postal authority's product is explicitly non-resellable. GeoNames is the sellable base, and it already carries official TERYT codes, so the practical gap is smaller than it looks.

Source 1 — GeoNames PL (the sellable base)

https://download.geonames.org/export/zip/PL.zip       # 988 KB, 72,899 rows

Licence CC-BY-4.0, verified against export/zip/readme.txt on 2026-08-27 — Poland carries no per-country caveat (the readme flags only GB, CL, CN, IE, MT, AR, BR).

Important: GeoNames PL already embeds official GUS TERYT codes. Verified on the first record:

fieldvaluemeaning
admin_code172GeoNames' own voivodeship code (not TERYT, not ISO 3166-2:PL)
admin_code20201TERYT powiat code (4-digit)
admin_code3020102TERYT gmina code (6-digit)

So the admin2/admin3 tiers are already officially coded. What is not official is admin_code1 — it should be derived to ISO 3166-2:PL (PL-DS, PL-MZ, …), and admin_name1 is an English exonym (Lower Silesia) rather than the Polish dolnośląskie.

Tier mapping: admin1 = województwo (voivodeship), admin2 = powiat (county), admin3 = gmina (municipality).

❌ Poczta Polska "Oficjalny Spis PNA" — NOT usable, do not revisit

The official register of Polish postal codes is a commercial product with an explicit prohibition on resale. Per Poczta Polska's own terms, the list "can only be used for the customer's own purposes, namely for addressing correspondence and verifying data, without the right to resale to third parties."

  • Sold as a book edition at post offices (quarterly updates) and as PDF/XLS/TXT with a search mechanism through the Poczta Polska online shop.
  • A free PDF edition circulates at poczta-polska.pl/wp-content/uploads/2024/05/spispna.pdf, but it is the same product under the same terms — being free to download does not make it free to resell. Do not treat the PDF as an open source.
  • Reference pages: bip.poczta-polska.pl/bez-kategorii/system-pocztowych-numerow-adresowych-pna/ and poczta-polska.pl/spis-pna/ (lookup form only).

This is the single most important finding for PL: the authoritative postal source is closed for our use case, and no amount of reformatting changes that. Any future proposal to "just use the official PNA list" must be refused on these terms.

Source 2 (optional) — GUS TERYT (admin authority, commercially reusable)

https://eteryt.stat.gov.pl/eTeryt/rejestr_teryt/udostepnianie_danych/baza_teryt/
  uzytkownicy_indywidualni/pobieranie/pliki_pelne.aspx

Files: TERC (territorial division), SIMC (localities), ULIC (streets), WMRODZ (locality types). NTS was discontinued 2018-01-01.

Licence: commercially reusable. Polish public sector information law (the open data / re-use act implementing the EU Open Data Directive) states that reuse covers "commercial or non-commercial purposes other than the original public purpose", that public sector information is provided for reuse free of charge, and that it is provided unconditionally as a rule, except where the law says otherwise. Attribution of the source is the norm and should be given regardless.

Reproducibility caveat: fetch_tier: dynamic. The download page is ASP.NET with JavaScript post-back buttons — there are no direct file URLs. A build script needs DynamicFetcher, not a plain GET.

TERYT is optional, not required: GeoNames already supplies the TERYT powiat and gmina codes. Use TERYT only to validate those codes, to obtain proper Polish-language voivodeship/powiat/gmina names, or if a future build needs the locality (SIMC) tier.

Cross-check against what is currently sold (2026-08-27)

count
GeoNames PL.zip data rows72,899
R2 pl/pl.csv rows72,900
R2 distinct postal codes20,299

Row counts differ by exactly 1 — close enough to confirm the R2 file is a GeoNames re-export, but the extra row should be identified before a rebuild so it isn't silently dropped or duplicated.

No independent authoritative code list is available to measure real coverage against, because Poczta Polska's PNA is closed (above). Poland's true postal code count cannot be verified from a sellable source — state this honestly in the README rather than implying completeness.

Defects in the currently-published file

pl/pl.csv on R2 was round-tripped through pandas and corrupted:

  • TERYT codes destroyed by leading-zero stripping plus float suffix — the worst instance across all countries audited, because these are real official codes, not GeoNames internal ids:
    • admin_code2: GeoNames 0201 → published 201.0
    • admin_code3: GeoNames 020102 → published 20102.0 A consumer cannot join 201.0 to TERYT. The official coding is functionally destroyed in the sold file.
  • 2 cells contain the literal string nan.
  • admin_code1 is GeoNames' 72-style code, not ISO 3166-2:PL.
  • admin_name1 uses English exonyms (Lower Silesia) rather than Polish.
  • accuracy is 6 on all 72,900 rows (GeoNames: centroid of addresses or shape) — uniform, so nothing lost here.

Attribution is absent from the sold product. R2 carries only pl/pl.csv — no README.md, datapackage.json, ATTRIBUTION.txt or pl.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": "all fields",
      "source_url": "https://download.geonames.org/export/zip/PL.zip",
      "licence_id": "CC-BY-4.0",
      "collected_at": "2026-08-27",
      "decision": "compatible",
      "decided_by": "claude-opus-5 (source research)",
      "decided_at": "2026-08-27"
    },
    {
      "field_group": "NOT USED — optional admin name/code validation tier",
      "source_url": "https://eteryt.stat.gov.pl/eTeryt/rejestr_teryt/",
      "licence_id": "custom:pl-psi-reuse-act",
      "collected_at": "2026-08-27",
      "decision": "unresolved",
      "decided_by": null,
      "decided_at": null,
      "note": "Polish PSI re-use act permits commercial reuse free of charge and unconditionally as a rule. Not a named SPDX licence, so flagged for human sign-off. Only needed if the build adds TERYT beyond what GeoNames already carries."
    }
  ],
  "excluded_sources": [
    {
      "source_url": "https://www.poczta-polska.pl/spis-pna/",
      "licence_id": "custom:poczta-polska-pna-tou",
      "decision": "incompatible",
      "reason": "Terms permit use for the customer's own purposes only, expressly without the right to resale to third parties. Applies equally to the freely-downloadable PDF edition."
    }
  ]
}

Proposed tier

B ($49) as a GeoNames single-source normalisation — which is what it realistically is, since the TERYT codes arrive inside GeoNames rather than from a second source. It rises to A only if a build genuinely consolidates TERYT (or SIMC localities) as a second dataset, which would also mean solving the dynamic fetch.

BUILT — 2026-08-27 (not published)

Pipeline written and run. Scripts committed under datasets/pl/scripts/; sources/ and data/ are gitignored and regenerable.

fetch_source.py -> build_base.py -> recover_alt_names.py -> integrity_checker.py -> package.py -> publish_r2.py

Result: 72,899 rows, 20,299 distinct postal codes, 16/16 voivodeships, 380 powiats, 2,476 gminas, zero duplicate primary keys, Frictionless validation passed, integrity status PASS. Cold rebuild is byte-identical (md5 1f4765f5f3f5e3d60915a14889eae9dc) after deleting sources/ entirely and re-fetching.

Fixed against the old R2 file: TERYT powiat/gmina codes restored as strings (201.0 -> 0201, 20102.0 -> 020102), admin_code1 replaced with the official ISO 3166-2:PL code derived from the TERYT voivodeship prefix, nan string literals removed, hyphens restored to voivodeship names.

Load-bearing new assertion: the TERYT gmina code must extend the powiat code. This is what catches a stripped leading zero — the old pipeline's row-count and column-name checks could not, which is why the corruption shipped.

alternative_city_name was recovered from the existing R2 copy rather than re-derived. Re-deriving from the GeoNames PL gazetteer by name + nearest coordinate was tried and rejected: it reproduces only ~76% of the published values (~62% as the first alternate name), so it would have silently changed a column customers already hold. 10,268 aliases carried over; 14,752 legacy values that merely echoed place_name were dropped.

One upstream conflict, kept and disclosed: Pilow / 78-650 exists under two gminas (Walcz 321705, Miroslawiec 321703), 90 m apart. Both are genuine source rows, so admin_code3 is part of the primary key rather than one row being dropped.

datapackage.yml updated: premium_tier: B, premium_source_key: pl/pl.zip, real sources[] naming GeoNames, and a licenses[] array — closing the CC BY 4.0 attribution breach.

Still to do — requires a human decision

publish_r2.py --apply has not been run. R2 still holds the old single-file pl/pl.csv and _meta/catalog.json still lists one file for PL. Publishing overwrites the live customer-facing product, so it is left for explicit approval. The dry run is clean:

pl/pl.csv             7,412,771 ->  7,108,193
pl/datapackage.json     (absent) ->      3,765
pl/README.md            (absent) ->      4,502
pl/ATTRIBUTION.txt      (absent) ->        688
pl/pl.zip               (absent) ->  1,024,612
_meta/catalog.json    PL entry: 1 file -> 5 files

Note the CSV gets smaller (7.41 MB -> 7.11 MB) despite gaining correct leading zeros — the old file's .0 float suffixes and nan literals cost more bytes than the zeros save.