Postal Codes Dataset for Morocco, MA

173
Updated:
Files:1
Size:106 kB
Formats:csv
License:CC-BY-4.0

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

About

Last updated
17 September 2026
Total rows
...
Format
CSV
File size
106 kB

About this dataset

Morocco (MA) — internal licensing notes

Source research, 2026-09-17 — first proper audit of this country

No .licensing-notes.md existed for MA before this pass. datapackage.yml carries the same old-style placeholder already flagged elsewhere in this project (sources: [{title: "Multiple sources", path: https://datahub.io/collections/postal-codes-datasets}], see feedback_datapackage_no_sources) and no licenses: array or licence_status block at all. README.md claims the data is "sourced from official and publicly available records" — a generic, unverified claim. The datapackage.yml resource metadata is also stale on basic facts: it declares bytes: 9268 and modified: '2024-11-07', but the file actually live on R2 is 107,941 bytes and was last written 2026-07-30 — the descriptor was never regenerated against the real object.

Audit scope note: research/audit only. No R2 write, no git commit, no datapackage.yml change, no .env value printed. Same ground rules as the CH/PR/CO audits this pass follows.

1. What the current R2 file (ma/ma.csv, 107,941 bytes, 2026-07-30) actually is — VERIFIED

Fetched directly from the main postal-codes R2 bucket (read-only, R2_ACCESS_KEY/R2_SECRET_KEY from this repo's own .env). 1,325 data rows + header.

Listing the ma/ prefix also shows the automated monthly GeoNames job is already running against this country and landing in the same bucket:

ma/ma.csv                        107941 bytes  2026-07-30  <- the shipped product
ma/geonames/latest/0.csv         107941 bytes  2026-09-01  <- monthly job output
ma/geonames/2026-09-01/0.csv     107941 bytes  2026-09-01  <- same, dated

Byte-identical sizes across the shipped file and the current monthly GeoNames pull confirm ma/ma.csv is (and continues to be) sourced from scripts/geonames/geonames_parse_to_R2.py, the same shared script that produces every other {cc}/geonames/latest/0.csv in this bucket.

Fetched https://download.geonames.org/export/zip/MA.zip (CC BY 4.0) directly for comparison: MA.txt also has exactly 1,325 rows, and a row-by-row diff confirms the R2 file is a straight tab-to-comma conversion of raw GeoNames MA.txt, run through geonames_parse_to_R2.py, with that script's own transforms visible:

GeoNames:  MA  32000  Al Hoceima  Tanger-Tetouan-Al Hoceima  01  Al-Hoceima  051          35.2516  -3.9372  4
R2 file:   MA,32000,Al Hoceima,Tanger Tetouan Al Hoceima,1,Al Hoceima,51,nan,,35.2516,-3.9372,4,Al Hoceima

Confirmed defects, all traced to scripts/geonames/geonames_parse_to_R2.py

  1. Literal string "nan" in admin_name3 on every single row (1,325/1,325). GeoNames' own MA.txt leaves admin name3/admin code3 blank for Morocco (no locality/community tier is supplied) — a genuinely empty tab field. pd.read_csv() reads that as NaN; the script's clean_and_normalize() then does df[column].astype(str) on admin_name3 before checking for null, which stringifies NaN to the literal four-character text "nan", and the following regex steps (which only strip parens and non-word characters) do not remove it because "nan" contains only word characters. This is the exact defect class already flagged in this project's postal_codes CSV typing reference note, just manifesting on a name field instead of a numeric one. Every downstream consumer sees admin_name3 as the 4-country town "Nan" rather than empty.

  2. admin_code1 and admin_code2 lose their leading zeros. GeoNames' raw values are zero-padded strings — 01..12 for admin_code1, 051/121/066 etc. for admin_code2. The script's add_leading_zero() re-pad step is applied only to postal_code (line 176-177 of geonames_parse_to_R2.py); admin_code1/admin_code2 pass through pd.read_csv() with no dtype=str, so pandas infers them as integers and the leading zero is silently dropped ("01"1, "051"51). This matters concretely here (see §2): 01 is the real ISO 3166-2:MA region suffix, so the shipped value fails to match the official code as published, even though the correct digits are present.

  3. admin_code2 values (e.g. 1, 51, 301, 311) are GeoNames- internal sequence numbers, not an official Moroccan province code. Morocco's ISO 3166-2 register defines codes only at the 12-region level (confirmed against Wikipedia's ISO 3166-2:MA table, see §2) — there is no ISO, HCP, or other official numeric code for the 82 provinces/prefectures, so there is no official replacement value to substitute; the honest fix is to stop presenting these numbers as if they were an administrative code (drop the column or clearly label it geonames_internal).

  4. admin_name2 carries inconsistent, unfiltered GeoNames gazetteer naming — e.g. Settat Province, Khouribga Province, Kelaa Des Sraghna (missing article/accents) alongside plain names like Fes, Nador with no suffix — i.e. some province names carry a literal "Province" suffix and most don't, an artefact of GeoNames' own admin2 name field rather than something introduced by this project's script.

  5. alternative_city_name is low-value GeoNames alternate-name noise, not a curated alias list: 455/1,325 rows have a value, and a large share of them either just repeat place_name verbatim (Al HoceimaAl Hoceima) or supply a French administrative-unit gloss rather than a real alternate spelling (IzemmourenCaidat d'Izemmouren, RouadiCaidat de Rouadi) — same failure mode already documented for CH's alternative_city_name, caused by the same get_non_numerical_name() / asciiname-keyed dict-merge logic in the shared script.

No float-formatted accuracy bug here (unlike CH) — accuracy values are clean 1 / 4 strings in both the raw GeoNames file and the R2 file, matching GeoNames' documented scale (1=estimated, 4=geonameid). No duplicate (postal_code, place_name) pairs; postal_code itself is not affected by the leading-zero bug (Morocco's postal codes are 5 digits with no leading zero to lose).

Verdict on the current file: a raw, unmodified-content GeoNames CC BY 4.0 extract from a stale underlying vintage (see §3), degraded further in packaging by the shared script's admin_name3"nan"-string bug and the admin_code1/admin_code2 zero-stripping bug. Not fabricated data, but materially worse than what Morocco's own postal authority currently publishes for free.

2. ISO 3166-2:MA region codes — VERIFIED against Wikipedia

Morocco has 12 regions, each with an official two-digit ISO 3166-2:MA code (region reorganisation per Decree No. 2.15.10, 20 Feb 2015):

CodeRegion
MA-01Tanger-Tétouan-Al Hoceïma
MA-02L'Oriental
MA-03Fès-Meknès
MA-04Rabat-Salé-Kénitra
MA-05Béni Mellal-Khénifra
MA-06Casablanca-Settat
MA-07Marrakech-Safi
MA-08Drâa-Tafilalet
MA-09Souss-Massa
MA-10Guelmim-Oued Noun
MA-11Laâyoune-Sakia El Hamra
MA-12Dakhla-Oued Ed-Dahab

GeoNames' admin_code1 for Morocco (01..12 in the raw file) is genuinely the real ISO 3166-2:MA numeric suffix — not a false-friend internal code, matching the CH finding that GeoNames sometimes gets admin1 right. The defect is entirely downstream: the R2 file strips the leading zero (1 instead of 01), so a consumer matching against the published ISO list byte-for-byte gets zero hits unless they re-pad it first. This should be fixed regardless of which postal source is used — it is a pure packaging bug on a field GeoNames already got right.

admin_code2 (province) has no ISO or other official numeric code to fall back on — see defect 3 above.

3. Official tier-1/2 sources checked FIRST, per the standing GeoNames-is-fallback rule

Barid Al-Maghrib / Poste Maroc, via Morocco's national open data portal (data.gov.ma) — CONFIRMED, and it is a real upgrade

Morocco's postal operator publishes its own postal-code reference data directly on data.gov.ma (organisation: poste-maroc), under the "Codes postaux des localités" dataset. Confirmed licence on the dataset page: Open Data Commons Open Database License (ODbL), data.gov.ma's stated "Open Definition"-compliant licence for this resource. (ODbL is share-alike, same family as OSM's licence — flag for a licence decision before shipping, per the OSM/ODbL gate philosophy in this project's standing rules, even though this is a different upstream than OSM.)

Fetched and inspected all four resources directly:

ResourceFormatRows (data)Notes
codes-postaux-des-localites-fev-2011-...csvCSV1,325This is what GeoNames' MA.txt — and therefore the current R2 file — is built from. Row count matches exactly; columns are REGION_POSTALE, PROVINCE, LOCALITE, NOUVEAU CODE POSTAL.
codes-postaux-des-localites-postemaroc-fev-2011.xlsXLS1,325Same 2011 vintage, alternate format.
codes-postaux-localites-2018.xlsxXLSX1,773The postal authority's own 2018 update — 448 more rows than 2011, 1,770 distinct postal codes vs. 1,325 today.
codes-postaux-des-villes-2018.xlsxXLSX34"Multi-code cities" index (large cities like Agadir, Casablanca, Fès with more than one postal code) — locality names only, cross-referenced against the main 2018 file rather than carrying codes itself.

This is a materially better, currently-unused, freely-licensed source:

  • The shipped product is running ~7 years stale. Comparing distinct postal codes: 463 codes exist in the 2018 official file that are absent from the 2011 file GeoNames (and therefore this project) currently serves; 18 codes present in 2011 were retired/renumbered by 2018 and no longer appear.
  • The 2018 file uses the real, current (post-2015-reform) region names directly from the postal authority (BENI MELLAL KHENIFRA, SOUSS MASSA, TANGER TETOUAN AL HOCEIMA, etc.) matching the 12 ISO regions in §2 — with one labelling defect in the source itself, noted honestly rather than silently fixed: 3 rows are tagged GRAND CASABLANCA SETTAT (a name that does not correspond to any of the 12 official regions) for provinces (Sidi Bennour, Benslimane, Berrechid) that appear correctly under plain CASABLANCA SETTAT elsewhere in the same file — an apparent data-entry inconsistency in Poste Maroc's own spreadsheet, not something introduced by this project. A rebuild would need to normalise those 3 rows.
  • Real province names, not a GeoNames-internal number — the 2018 file gives 82 named provinces/prefectures directly, which is the intended fix for defect 3 above (there is still no official numeric province code, but the name itself would be authoritative rather than GeoNames-derived).
  • Publisher-declared update history is transparent: dataset page shows "last modified 2021-12-13", data current to September 2018 — older than ideal, but still a full postal-authority refresh cycle ahead of what ships today.

Licence caveat to resolve before any rebuild, not resolved in this pass: ODbL is a share-alike licence. Whether that is compatible with this product's resale model (the postal-codes R2/datahub.io channel, where — per this project's own standing rule — attribution/licence disclosure is required and expected, unlike the FedEx delivery-folder product) needs a licence_status decision (decision: "unresolved" is the correct interim state) rather than silent adoption. This is a materially different situation from the GeoNames CC BY 4.0 baseline (attribution-only, no share-alike) currently implied by the unshipped licenses block.

HCP (Haut-Commissariat au Plan) — CONFIRMED as the tier-2 admin reference, not fetched row-by-row this pass

HCP publishes the official administrative structure and, most recently, population counts by region/province/prefecture/commune from the 2024 census (Decree No. 2.24.1009, adopted per HCP's own site, resources at hcp.ma). The 12-region structure itself traces to Decree No. 2.15.10 (20 February 2015) — the same regions independently confirmed via Wikipedia's ISO 3166-2:MA table in §2, so the two sources agree. HCP also publishes commune-level administrative boundary/reference files ("Découpage administratif", "Maroc des régions" downloads). Licensing terms for HCP's own downloads were not fetched/verified in this pass — would need checking before use, same as any new official source.

4. Disputed-territory disclosure — Western Sahara, factual only, no determination made

Both the currently shipped file and Poste Maroc's own 2018 update assign postal codes to localities inside Western Sahara, a territory whose sovereignty is internationally disputed (administered by Morocco over roughly 80% of the territory since 1975-76; also claimed by the Sahrawi Arab Democratic Republic / Polisario Front; the UN continues to list Western Sahara as a Non-Self-Governing Territory and MINURSO maintains an active mandate there).

In the currently shipped R2 file: 9 of 1,325 rows carry admin_code1 11 (Laâyoune Sakia El Hamra, 7 rows: Boujdour, Es-Semara, Foum El Oued, Dcheira Tafoudart, Tarfaya, Daoura, Akhfennir) or 12 (Dakhla Oued Ed Dahab, 2 rows: Aousserd, Dakhla) — all under country_code: MA, with no separate flag or EH (Western Sahara's own ISO 3166-1 code) anywhere in the file.

In Poste Maroc's own 2018 update, this grows to 31 of 1,773 rows (18 under LAAYOUNE SAKIA EL HAMRA, 13 under DAKHLA OUED EDDAHAB) — the postal authority's own current reference data assigns these localities Moroccan postal codes and Moroccan region/province names on exactly the same footing as undisputed Moroccan territory, with no distinguishing marker.

GeoNames itself has no separate EH.zip/EH.txt postal file — Western Saharan localities exist in GeoNames' data only via MA.txt, i.e. GeoNames also treats them as part of Morocco for postal-code purposes, not as a separate entity.

Note on Tarfaya specifically, for anyone relying on this note later: Tarfaya sits just north of the Western Sahara territory as usually defined (it reverted to Morocco in 1958, well before the 1975-76 Spanish withdrawal that created the modern dispute over the territory to its south), yet both sources file it under the Laâyoune-Sakia El Hamra region, which straddles undisputed Morocco and disputed Western Sahara — worth knowing if a future pass wants a locality-level rather than region-level disputed-territory flag.

No determination is made here about sovereignty. This section records, factually, what both the current file and its likely replacement contain, following the same neutral disclose-don't-decide treatment already used in this project for Crimea/Sevastopol (Russia) and Israel's disputed territories: if a rebuild happens, this fact should be disclosed in the delivered dataset's documentation (a factual note that these localities' Moroccan administrative assignment reflects Morocco's own postal/civil administration and is disputed internationally), not silently carried or silently stripped.

Verdict

A real official upgrade exists and is not currently used. This is not a "GeoNames is good enough" case: Barid Al-Maghrib publishes its own postal-code reference data on Morocco's national open data portal, it is directly fetchable, it is ~7 years newer than the vintage GeoNames (and therefore this project) currently serves, it carries 448 more distinct postal codes, and it uses the real post-2015-reform region names instead of a GeoNames-internal numbering scheme for at least the region tier.

Concrete defects in what ships today, independent of which source is used going forward:

  1. admin_name3 is the literal string "nan" on 100% of rows — a pd.read_csv()/astype(str) ordering bug in the shared geonames_parse_to_R2.py script.
  2. admin_code1 (1-12) is missing its leading zero relative to the real ISO 3166-2:MA code (01-12) — same script, add_leading_zero() applied only to postal_code, not to the admin code columns.
  3. admin_code2 is a GeoNames-internal sequence number mislabeled as an administrative code column; no official province-level numeric code exists to replace it with (only province names are official).
  4. datapackage.yml resource metadata (bytes: 9268, modified: '2024-11-07') does not match the live R2 object (107,941 bytes, 2026-07-30) — stale even on basic file facts, independent of any licensing question.
  5. No licence_status, no licenses array, no sourcing disclosure anywhere in the shipped metadata — the same gap already found and fixed for other countries in this project's 2026-09 audit pass.

Recommended next step (not executed in this pass — research/audit only):

  1. Rebuild from Barid Al-Maghrib's codes-postaux-localites-2018.xlsx as the postal_code/place_name/region/province backbone, normalising the 3 GRAND CASABLANCA SETTAT rows to CASABLANCA SETTAT.
  2. Re-pad admin_code1 to the real ISO 3166-2:MA two-digit form (01- 12) if a GeoNames-derived region tier is kept at all, or map directly from the 12 official region names in §2.
  3. Drop or clearly relabel admin_code2 — there is no official numeric code at province level to ship in its place.
  4. Fix the admin_name3/"nan"-string bug at the source (the shared geonames_parse_to_R2.py script), or, if the postal authority's own file is adopted instead, note that it has no locality/community tier either (2018 file stops at province+locality, same as GeoNames) — so admin_name3 should ship empty, never "nan".
  5. Resolve the ODbL licence question explicitly (custom:data-gov-ma-odbl or similar, decision: "unresolved" until a human signs off, channel: "postal-codes-r2") before any republish — do not silently carry forward the GeoNames CC BY 4.0 assumption implied by the current unshipped sources placeholder, since the better source has a different, share-alike licence.
  6. Disclose the Western Sahara postal-code inclusion factually in any rebuild's documentation, per §4 — do not silently drop or silently ship those rows without a note either way.

Not done in this pass, by design: no script written, no datapackage.yml change, no R2 write, no git commit. This file is the audit record only.


Build, 2026-09-17 — packaging fix, GeoNames only, local only

Per explicit instruction: this is a packaging fix on GeoNames (CC BY 4.0), NOT a source upgrade. Poste Maroc's richer 2018 dataset (codes-postaux-localites-2018.xlsx, 1,773 rows, ODbL) was deliberately not used — that licence question stays unresolved pending an explicit human decision, out of scope here. Local build only: no R2 upload, no git commit/push, _meta/catalog.json and datapackage.yml left untouched.

Fetched https://download.geonames.org/export/zip/MA.zip fresh — 1,325 rows, matching the expected count and the audit above exactly.

Wrote datasets/ma/scripts/build_postal_codes_product.py (csv module only, no pandas — modelled on datasets/ke/ and datasets/lk/'s build scripts). Confirmed against the raw tab-delimited source before any transform:

  • admin_code1 in the raw file is already zero-padded (^\d{2}$, 01–12) and already the genuine ISO 3166-2:MA region code (§2 above) — no crosswalk needed, only re-padding + an MA- prefix (MA-01.. MA-12).
  • admin_code2 in the raw file is already zero-padded (^\d{3}$) — the only reason it lost its zero in the previously shipped file was pd.read_csv() with no dtype=str in the shared geonames_parse_to_R2.py. Reading with csv.reader avoids that entirely. Value is kept unprefixed (not given an MA-/ISO-style prefix) and is labelled in the schema (datapackage.json field description), README.md, and ATTRIBUTION.txt as a "GeoNames-internal identifier, NOT an official Moroccan province code" — Morocco's ISO 3166-2:MA register only defines codes at region level, so there is no official value to substitute.
  • admin_name3/admin_code3 are genuinely blank in the raw source (asserted in the build script) — csv.reader preserves that as "", never the literal string "nan".
  • Disputed-territory rows (Western Sahara localities under MA-11 Laâyoune-Sakia El Hamra and MA-12 Dakhla-Oued Ed-Dahab) carried through completely unchanged — 9/1,325 rows, exactly matching the audit's count (7 under MA-11: Boujdour, Es-Semara, Foum El Oued, Dcheira Tafoudart, Tarfaya, Daoura, Akhfennir; 2 under MA-12: Aousserd, Dakhla). A neutral, factual disclosure paragraph was added to ATTRIBUTION.txt (same disclose-don't-decide treatment as this project's Crimea/Sevastopol note in the Russia build) — no row added, removed, or modified.

Result: datasets/ma/data/ma.csv — 1,325 rows, 12/12 ISO regions covered, 59 distinct admin_code2 values, 0 duplicate (postal_code, place_name) pairs, 0 literal "nan" strings, 0 float-formatted accuracy values. licence_status.decision: compatible (licence_id: CC-BY-4.0, channel: postal-codes-r2), with an explicit note recording that the ODbL 2018 source exists and was deliberately not adopted this pass.

Frictionless validation: run from inside datasets/ma/data/ against datapackage.json (the delivered artifact, not the working copy) — report.valid == True, 0 errors, 0 warnings.

Files written: datasets/ma/scripts/build_postal_codes_product.py, datasets/ma/data/ma.csv, datasets/ma/data/datapackage.json, datasets/ma/data/README.md, datasets/ma/data/ATTRIBUTION.txt, datasets/ma/data/ma.zip. datasets/ma/sources/postal_raw/MA.txt and readme.txt saved as the raw source snapshot. No other files touched.