Postal Codes Dataset for France, FR

303
Updated:
Files:1
Size:4.55 MB
Formats:csv
License:CC-BY-4.0

Postal Codes Dataset for France, FR 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 (GeoNames) license
20% off
$49.90$39.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-fr/
https://datahub.io/logistics/postal-codes-fr/_r/-/.licensing-notes.md
https://datahub.io/logistics/postal-codes-fr/_r/-/README.md
https://datahub.io/logistics/postal-codes-fr/_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-fr/_r/-/datapackage.yml
README.mddocumentation
https://datahub.io/logistics/postal-codes-fr/_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 France, FR


About this dataset

France (FR) — internal licensing notes

Status: RESOLVED AND REPUBLISHED (2026-08-24). Provenance identified, licence clean and now attributed, and the severe data-quality defect that was found alongside it has been fixed and republished to R2. See "Corrected republish — executed" at the foot of this file for what shipped.

Two separate findings below; don't conflate them.

The problem as filed (datahub-next#941 §3, opened 2026-08-08)

"France — a single raw CSV with no research.json, qa_log, validation report
or README. Provenance is unknowable; cannot be sold at any price until
re-sourced."

The "no provenance record" half is accurate and confirmed. The "unknowable" half is not — the data fingerprints cleanly against a known source.

Provenance — identified with HIGH confidence as GeoNames FR

Investigated 2026-08-24 by forensic fingerprinting (the same method used for Isle of Man), because no documentary trace survives anywhere:

  • countries/FRA/ in fedex-agents-prototype holds exactly one file and no research.json, script, qa_log or README. Git shows it was added wholesale in a single commit (bcd0fcb, 2026-05-11, 51,661 lines, no accompanying code).
  • The postal-codes repo has no France parserscripts/custom_parsing_scripts/ contains Brazil and Canada only, and git log --all shows no France script ever existed.

Finding 1 — the file actually ON SALE is GeoNames, and the match is exact. R2 fr/fr.csv has 51,611 data rows; GeoNames FR.txt has 51,611 lines. Every row was traced:

BucketRows
Direct match on (postal code, place name)47,677
Match once the zero-padding bug is undone3,281
CEDEX / SP special codes653
Genuinely unexplained0

Coordinates, admin_code1/2/3 and accuracy all carry through identically (e.g. Paris 75000 → 48.8534, 2.3488, accuracy 5).

Correction (2026-08-24, verified during the rebuild): an earlier draft of this note said admin_code1 uses GeoNames' "pre-2016 numeric region codes … not an INSEE or ISO scheme". That is wrong on both counts. The current GeoNames FR export carries the post-2016 13-region structure with official INSEE region codes84 Auvergne-Rhône-Alpes, 27 Bourgogne-Franche-Comté, 44 Grand Est, 32 Hauts-de-France, 75 Nouvelle-Aquitaine, 76 Occitanie are all post-2016 merged regions, and the export contains exactly 13 distinct region codes, not the pre-2016 22. 11 Île-de-France and 94 Corse merely happen to be unchanged across the reform, which is what made the older reading look plausible. No region remapping is needed or wanted for France — unlike Italy, where GeoNames' admin_code1 genuinely is a non-official internal numbering that had to be replaced.

Finding 2 — the local FedEx-schema file is also GeoNames-derived, not a second independent source. countries/FRA/data/France_2026_updated.csv (51,660 rows) matches GeoNames at 92.65% on (full postal code + normalised place name); the residual is explained by the corruption documented below. It is a reprocessed variant: 9-column FedEx schema, accents stripped, hyphens title-cased, and regions remapped to the post-2016 13-region names with official INSEE codes (ARA, BFC, BRE, COR, CVL, GES, HDF, IDF, NAQ, NOR, OCC, PAC, PDL).

Ruled out — La Poste's official base is NOT the source. Its "Base officielle des codes postaux" has 39,192 rows and matches our non-CEDEX rows at only 80.55%, against GeoNames' 99.53% on the same subset.

On the "49-row discrepancy" in the original brief: it is a false premise. The two files are different artifacts, not two copies of one thing — R2 has 51,611 (= GeoNames exactly) and the local FedEx file has 51,660 (a reprocessed variant). The near-coincidence of both sitting around 51.6k is what made them look like the same file with rows missing.

Licence — CC BY 4.0, commercial resale permitted

GeoNames' own readme.txt, shipped inside FR.zip:

"This work is licensed under a Creative Commons Attribution 4.0 License.
This means you can use the dump as long as you give credit to geonames
(a link on your website to www.geonames.org is ok)"

France is not on GeoNames' restricted list. That readme names Chile, Ireland and Malta as truncated "for copyright reasons", and China, Argentina and Brazil as truncated without stated reason. France appears in none of them — full codes, no caveat. Contrast Saudi Arabia, Guinea and Maldives, where GeoNames has no export at all.

So France is cleanly resolvable with attribution — it is NOT a withdrawal case. Attribution is a licence condition and is currently not being shipped: neither the R2 objects nor datasets/fr/datapackage.yml credited GeoNames before this pass.

Worth noting for completeness: La Poste's official base is also cleanly licensed — data.gouv.fr publishes it under the Licence Ouverte / Open Licence version 2.0, which permits commercial reuse. It is a legitimate re-source option (see below) if the quality problems argue for a rebuild rather than a patch.

The real problem: the file on sale is severely malformed

Licensing is clean; the data is not. Found in R2 fr/fr.csv — the file customers actually receive:

  • Every postal code is destroyed. All 51,611 are zero-padded to a fixed 15 characters — 75000 ships as 000000000075000. 73.2% carry five or more leading zeros. There is no French postal code format this matches; the primary field of a postal-code product is unusable as-is.
  • admin_code1 float-coerced on 51,610 of 51,611 rows11 ships as 11.0.
  • 361 rows carry the literal string nan in an admin name field.
  • Hyphens stripped from place namesLe Bellay-en-Vexin ships as Le Bellay en Vexin.
  • Bare CSV only — no datapackage.json, no README.md, no .zip, unlike a complete publish.

These are the same signature as the float-coercion and punctuation-stripping defects found in PT and DE earlier in this review, all traceable to scripts/geonames/geonames_parse_to_R2.py (pandas, no dtype=str). France is the worst instance found so far because the corruption reaches the postal code itself rather than an admin column.

The local FedEx-schema variant has a different and independent set of defects, recorded here so they are not lost:

  • 315 rows carry an English-translated region name in cityName — e.g. postal code 75000 (Paris) ships with cityName = "Upper France" (Hauts-de-France) and alternativeCityName = "Hauts de France". Wrong field, wrong language, wrong region.
  • Mojibake where accents were deleted rather than transliterated: Crteil (Créteil), Paris La Dfense (La Défense), IvrysurSeine (Ivry-sur-Seine) — inconsistent with the clean Ardeche/Correze transliteration elsewhere in the same file, suggesting two processing paths.
  • Cities sitting in the département field: Bobigny, Nanterre, Pantin, Montreuil, Paris 02, Paris 09 — inflating the département count to 108 against France's real 101.
  • Duplicate casing: Val-D'oise and Val-d'Oise both present.
  • No overseas départements (Guadeloupe, Martinique, Guyane, La Réunion, Mayotte are absent) while uninhabited Clipperton Island is present with empty region, department and city.

Recommendation

Licensing: resolvable now — outcome (a). Add GeoNames attribution and the CC BY 4.0 licenses: block to datasets/fr/datapackage.yml (done in this pass, locally) and to the R2 objects when they are next republished.

Quality: this should not stay on sale in its current state, and that is a separate decision from the licensing one. is_premium: true is set on a file whose every postal code is malformed. Options, in order of preference:

  1. Republish from GeoNames FR with a corrected parser (dtype=str, no punctuation stripping) — restores real postal codes, keeps the licence clean, and fixes PT/DE-class defects at the same time.
  2. Rebuild from La Poste's official base (Licence Ouverte 2.0, commercial reuse permitted) if authoritative provenance is preferred over GeoNames' coverage — but note it has 39,192 rows against GeoNames' 51,611 and omits the CEDEX layer.
  3. Gate with data_available: false until either is done.

Deliberately not done here: no is_premium/data_available flag was changed, no R2 object was written, nothing was committed. Those are human decisions.

Investigated 2026-08-24. Sources verified directly: GeoNames FR.zip + bundled readme.txt; La Poste "Base officielle des codes postaux" via data.gouv.fr; R2 fr/fr.csv; both repos' git history.


Corrected republish — EXECUTED 2026-08-24

Option 1 from the recommendation above was carried out: rebuilt from GeoNames FR with a corrected parser and republished to R2. Reproducible scripts live in datasets/fr/scripts/ (fetch_source.pybuild_base.pyintegrity_checker.pypackage.pypublish_r2.py); see that folder's README for run order and full verification.

Licence position, now shipping. GeoNames CC BY 4.0 attribution is carried in the published README.md and datapackage.json, and in datasets/fr/datapackage.yml. Before this pass it appeared nowhere — that was live non-compliance with the licence that makes the dataset sellable, and it is now closed.

All four defects fixed and asserted against.

DefectBeforeAfter
Postal codes zero-padded to 15 chars00000000007500075000
admin_code1 float-coerced11.011
Literal nan string cells4610
Punctuation stripped from place namesLe Bellay en VexinLe Bellay-en-Vexin

integrity_checker.py now fails the build on any of the four, so a regression cannot reach R2 silently. datapackage.json additionally declares postal_code as a string with an explicit France pattern (^\d{5}( (CEDEX( \d{1,2})?|SP \d{1,2}|AIR|CITYSSIMO))?$), so a schema-aware reader cannot re-coerce it.

Root cause of the padding, for the record. France's postal column is mixed width — the CEDEX/SP/AIR/CITYSSIMO business-delivery layer runs up to 15 characters (78078 CITYSSIMO). A max-width zero-fill over that column padded every short code to 15. This is why the bug hit the primary field here and only admin columns in PT/DE.

Row count: 51,611 source → 51,585 published. The 26-row difference is 24 groups of coordinate-only duplicates — same postal code, place name and full administrative hierarchy, differing only by roughly 100–200 m (two gazetteer entries for one commune centroid, e.g. 70230 Roche-sur-Linotte-et-Sorans-les-Cordiers). Dropped so (postal_code, place_name) holds as a primary key; counted in data/build_stats.json, not silently discarded.

Published and verified. Four objects now live under the fr/ prefix where previously only a bare CSV existed:

ObjectBytes
fr/fr.csv4,545,018 (was 5,215,242)
fr/datapackage.json3,754 (was absent)
fr/README.md3,828 (was absent)
fr/fr.zip648,556 (was absent)

Round-trip verified: the objects were downloaded back from R2 and the downloaded copy re-validated with Frictionless from inside its own directory — valid, 51,585 rows, zero padded/nan/float-suffixed cells, Paris 75000 present.

Still outstanding after this republish

  • The public 100-row sample is still corrupt. https://postal.datahub.io/fr/fr.csv returns 000000000075000, 11.0 and Île de France — it is the old broken extract. That object lives in the postal-codes-samples bucket, which the postal-codes token cannot write to (see docs/R2_ACCESS.md §3), so it could not be fixed here. This is the copy prospective buyers see. It needs regenerating by whoever holds access to that bucket.
  • _meta/catalog.json was not touched by this work — its fr entry still reflects the old byte count and lacks the three new files. Deliberate: that file is shared state and was being updated serially elsewhere.
  • The shared parser was not fixed. scripts/geonames/geonames_parse_to_R2.py is the root cause and is used by many countries; correcting it is a separate, wider job. PT and DE are already known to carry the same defect class.
  • is_premium / data_available flags were not changed — human decision.