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 Poland, PL
| 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
- 7 November 2024
- Total rows
- ...
- Format
- CSV
- File size
- 11.1 kB
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:
| field | value | meaning |
|---|---|---|
admin_code1 | 72 | GeoNames' own voivodeship code (not TERYT, not ISO 3166-2:PL) |
admin_code2 | 0201 | TERYT powiat code (4-digit) |
admin_code3 | 020102 | TERYT 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/andpoczta-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 rows | 72,899 |
R2 pl/pl.csv rows | 72,900 |
| R2 distinct postal codes | 20,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: GeoNames0201→ published201.0admin_code3: GeoNames020102→ published20102.0A consumer cannot join201.0to TERYT. The official coding is functionally destroyed in the sold file.
- 2 cells contain the literal string
nan. admin_code1is GeoNames'72-style code, not ISO 3166-2:PL.admin_name1uses English exonyms (Lower Silesia) rather than Polish.accuracyis6on 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.