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.
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.yaml to inspect schema and resources
- 2. Download data resources listed in datapackage.yaml
- 3. Read README.md for full context
Data Files
Explore with AIpostal-codes-ly
| Field | Type | Description | Title |
|---|---|---|---|
| country_code | string | ISO 3166-1 alpha-2 -- always LY | Country Code |
| postal_code | string | Always empty -- Libya has no operational postal code system. Not a data gap; see ATTRIBUTION.txt. | Postal Code |
| place_name | string | Locality/place name (GeoNames populated place) | Place Name |
| admin_name1 | string | District (shabiyah) -- all 22 covered; blank where GeoNames assigns a place to no current district | Administrative Name 1 |
| admin_code1 | string | ISO 3166-2:LY code | Administrative Code 1 |
| admin_name2 | string | Not populated in this release | Administrative Name 2 |
| admin_code2 | string | Not populated | Administrative Code 2 |
| admin_name3 | string | Not populated | Administrative Name 3 |
| admin_code3 | string | Not populated | Administrative Code 3 |
| latitude | number | GeoNames latitude (WGS84) | Latitude |
| longitude | number | GeoNames longitude (WGS84) | Longitude |
| accuracy | string | Not populated -- the GeoNames gazetteer dump carries no accuracy field | Accuracy |
| alternative_city_name | string | Not populated in this release | Alternative City Name |
Download
Download CSVAbout
- Last updated
- 6 October 2026
- Total rows
- 909
- Format
- CSV
- File size
- 55.2 kB
About this dataset
Libya (LY): migration notes
Internal record of the P6 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.8.14
- Commit: see
git log -- datasets/ly/(P6 ly commit on feat/single-source-of-truth, basee797eb1) - Parity verdict:
format-only(gate: pass, exit 0); CRLF→LF only - Producer:
custom, refresh disabled
Sources
| Input | URL | Notes |
|---|---|---|
| GeoNames gazetteer dump | https://download.geonames.org/export/dump/LY.zip | LY.txt, filtered to feature class P. The old builder read a local sources/LY.txt snapshot of this file |
| GeoNames admin1 table | https://download.geonames.org/export/dump/admin1CodesASCII.txt | Defines the 22 current LY buckets and their labels, checked against the crosswalk. The old builder read a local sources/geonames_admin1CodesASCII.txt snapshot |
- Both URLs are stable, unversioned GeoNames URLs. The fetch date and sha256 are recorded in
ly.inputs.json;--no-fetchreuses the cache. - Libya has no postal-code system and GeoNames has no postal export for LY (
export/zip/LY.zipis a 404), sopostal_codeis empty on every row.pipeline.postal_code_required: falsetells build.py this is intended.
Parity against the live public CSV (2026-10-05)
Rows: 909 live and 909 fresh, none only on one side, 0 changed cells, no cell classes. Once CRLF is normalised to LF the fresh ly.csv is byte-identical to the live CSV, including row order. Live sha256 daf95602…, fresh 8709188d… (the only difference is line endings).
No discrepancies to explain. The GeoNames dump at migration time still has 909 populated places, 22 of them on admin1 codes outside the current table (blank, 00, and stale pre-reform codes 11, 19, 30, 36, 47, 49, 55, 56, 58, 61), as on 2026-09-15.
Decisions
| Decision | By | Basis |
|---|---|---|
| Accept the CRLF→LF difference | Standing rule (P5 sign-off: row_order/CRLF-only pre-approved) | Equal rows, 0 changed cells |
| Drop the count assert (at least 800 places) | P6 brief | Replaced by structural checks: all 22 districts present, primary key unique, GeoNames labels match the crosswalk |
| Key the crosswalk on the GeoNames bucket code (LY.63–LY.84) instead of the admin1 name, and check each label | Agent: port choice | Same output; an upstream rename or a new/removed bucket now stops the build instead of silently blanking rows |
| Any admin1 code not in the current admin1 table ships blank (not an error, unlike bj) | Agent: port choice | Faithful to the old builder. LY has many stale pre-reform codes in the dump, and a code outside the table can't be a new district (a new one would appear in admin1CodesASCII first and fail the bucket check) |
latitude/longitude typed number; accuracy stays string | Agent, per the brief | accuracy is empty on every row (the gazetteer dump has no accuracy field), so it doesn't get the GeoNames accuracy description |
primaryKey: [place_name, latitude, longitude] | Agent, from the produced CSV | Unique in the produced CSV, and the producer checks it. The old builder's PK added admin_name1, which is blank on some rows; the shorter key is stricter and implies the old one. (place_name, admin_code1) is not unique |
pipeline.postal_code_required: false | Agent, per the brief | postal_code is empty on every row (same as bj) |
Add admin1CodesASCII.txt to the descriptor sources | Agent | It is a fetched input |
| Field descriptions taken from the old builder's datapackage.json (minus counts) | Agent | The P3 generic descriptions said "Postal code for the location", which is wrong for ly |
| Drop "909 rows" from the descriptor description and "909 places" from README.md | P6 brief (count rule) | District count (22) kept |
Transforms carried over
From build_postal_codes_product.py:
- Feature class
Ponly;place_nameis the dump'snamecolumn; latitude/longitude copied verbatim. admin_code1→ ISO 3166-2:LY via the 22-district crosswalk;admin_name1uses the old builder's display names (Banghazi→Benghazi, Darnah→Derna, Misratah→Misrata, Surt→Sirte, Jabal al Gharbi→Al Jabal al Gharbi, "Murzuq District"→Murzuq, "Sabha District"→Sabha).- Admin1 codes outside the current table → blank admin_name1/admin_code1.
postal_code,accuracy,alternative_city_nameand admin tiers 2–3 empty.- Sorted by (admin_code1, place_name), ties in dump order.
- Not ported: the old builder's own datapackage.json, README, ATTRIBUTION and zip writing (build.py / committed docs handle those) and
publish_r2.py.
Open questions
- README.md was not the stale stub and had no
licence_statusline; only the count was removed. Nothing pending there. .licensing-notes.mdstill carries dated counts; left for pc-hfz.