Technical Documentation: dr5hn/countries-states-cities-database
βΉοΈ Provenance: Multi-Tier Ingestion Β· CodeWiki Reference
Overview (README.md)
Total Regions : 6
Total Sub Regions : 22
Total Countries : 250
Total States/Regions/Municipalities : 5,299
Total Cities/Towns/Districts : 153,765
Total Postcodes : 725993 (116 countries)
Total Timezones : 427 (100% IANA coverage)
Last Updated On: October 19, 2026
Recommended for production
The two managed products below are the fastest path to shipping. They're actively maintained, billed for sustainability, and back the rest of the ecosystem.
REST API β `api.countrystatecity.in`
Query countries, states, cities, and postcodes from any language. Free tier for prototyping; paid tiers for production.
curl https://api.countrystatecity.in/v1/countries/IN/states/MH/cities \
-H "X-CSCAPI-KEY: $YOUR_API_KEY"Python applications can use the official sync and async client:
pip install countrystatecity-api
export CSC_API_KEY="YOUR_API_KEY"from countrystatecity import CountryStateCity
with CountryStateCity() as client:
states = client.get_states_of_country("IN")
print([state["name"] for state in states[:3]])Get a free API key β Β·
Compare plans Β·
Documentation Β·
Interactive playground Β·
OpenAPI spec Β·
Status
Export Tool β `export.countrystatecity.in`
Build tailored datasets in your browser β pick country, region, format, and field selection, then download.
Other ways to use the data
NPM (JavaScript / TypeScript)
| Package | GitHub | NPM |
|---|---|---|
@countrystatecity/countries |
GitHub | npmjs.com |
@countrystatecity/countries-browser |
GitHub | npmjs.com |
@countrystatecity/currencies |
GitHub | npmjs.com |
@countrystatecity/timezones |
GitHub | npmjs.com |
@countrystatecity/translations |
GitHub | npmjs.com |
@countrystatecity/cli |
GitHub | npmjs.com |
PyPI (Python)
Use countrystatecity-api for live, managed data. The suffixed packages are versioned offline snapshots.
| Package | Use | GitHub | PyPI |
|---|---|---|---|
countrystatecity-api |
Live REST API client | GitHub | pypi.org |
countrystatecity-countries |
Offline snapshot | GitHub | pypi.org |
countrystatecity-timezones |
Offline snapshot | GitHub | pypi.org |
countrystatecity-currencies |
Offline snapshot | GitHub | pypi.org |
countrystatecity-translations |
Offline snapshot | GitHub | pypi.org |
countrystatecity-phonecodes |
Offline snapshot | GitHub | pypi.org |
countrystatecity-regions |
Offline snapshot | GitHub | pypi.org |
countrystatecity-postal-codes |
Offline snapshot | GitHub | pypi.org |
Direct download (gzipped exports)
Countries, states, counties, cities, and postcodes are separate datasets. Counties contain official intermediate
administrative units; cities can link to them through a nullable county_id. See
the county field shape and link rules.
Every format ships as a .gz asset on each GitHub Release.
curl -LO https://github.com/dr5hn/countries-states-cities-database/releases/latest/download/json-cities.json.gz
gunzip json-cities.json.gz
curl -LO https://github.com/dr5hn/countries-states-cities-database/releases/latest/download/json-counties.json.gz
gunzip json-counties.json.gzSmaller reference files (countries, states, counties, schema) live in the repo. Use git clone --depth 1 for a fast clone.
Other packages and platforms
- Database browser β query and explore live data
- Encyclopedia β country profiles and insights
- Community Manager β submit corrections via web UI
- CLI β terminal access
- Kaggle Β· Data.world
What's in the data
- 250 countries Β· 5,329 states / regions Β· 14,058 counties Β· 153,513 cities Β· 840k+ postcodes across 125 countries
- 19 languages of country and state names plus native script
- 100% IANA timezone coverage for cities
- Validated foreign keys on every contribution
- Formats: JSON, MySQL, PostgreSQL, SQLite, SQL Server, MongoDB, XML, YAML, CSV, GeoJSON, TOON (LLM-optimised, ~40% fewer tokens than JSON), Parquet (columnar, analytics-ready)
| Format | Export time | Size | Compressed |
|---|---|---|---|
| CSV | 1s | 40 MB | 9 MB |
| MongoDB dump | 1s | 30 MB | 20 MB |
| MySQL SQL | 3s | 86 MB | 22 MB |
| JSON | 4s | 271 MB | 18 MB |
| TOON | 5s | 23 MB | 20 MB |
| Parquet | 7s | 31 MB | 27 MB |
| GeoJSON | 8s | 208 MB | 24 MB |
| XML | 9s | 91 MB | 15 MB |
| YAML | 17s | 68 MB | β |
| SQLite | 45s | 89 MB | β |
Contributing
The easiest way is the Community Manager β submit corrections through a web UI with end-to-end tracking.
To edit JSON directly:
- Fork and clone (
git clone --depth 1). - Edit files under
contributions/cities/,contributions/states/,contributions/countries/,contributions/counties/, orcontributions/postcodes/. - Required for new cities:
name,state_id,state_code,country_id,country_code,latitude,longitude. Optional:timezone,wikiDataId,native. - Omit
id,created_at,updated_at,flagβ auto-managed on import. - Open a pull request with a clear data source. If it removes, repurposes or restores ids, include its reviewed
ledger events keyed byevent_prin that same PR.
TheLedger migrationscheck validates the merge preview; all ids must be final at that preview.
{
"name": "San Francisco",
"state_id": 1416,
"state_code": "CA",
"country_id": 233,
"country_code": "US",
"latitude": "37.77493",
"longitude": "-122.41942",
"timezone": "America/Los_Angeles",
"wikiDataId": "Q62"
}Contributions guide Β·
Contribution guidelines Β·
Multi-level territories policy Β·
Data versioning Β·
Disputed and special territories Β·
Administrative structure policy Β·
The cities.type field
Don't edit the auto-generated directories (
json/,csv/,xml/,yml/,sql/, etc.). They're rebuilt from MySQL on every release.
License and attribution
Licensed under the Open Database License (ODbL v1.0). Commercial use, modification, and redistribution all permitted. Attribution is required, and derivatives must be shared under the same license.
Data by Countries States Cities Database
https://github.com/dr5hn/countries-states-cities-database | ODbL v1.0Some records also carry names or points copied from open sources that ask for credit: GeoNames
(CC BY 4.0), Β© OpenStreetMap contributors
(ODbL 1.0) and Wikidata (CC0). Points are selected per record and
rounded to eight decimals; the per-record source ledgers are in .github/fixes-docs/ledgers/.
Official registers matched to records (categories, codes and unit names) also ask for credit:
- Statistical Office of the Slovak Republic, register of spatial units REGPJ (CC BY 4.0)
- Geodetska uprava Republike Slovenije (GURS), register of spatial units RPE, 13 October 2026 (CC BY 4.0)
- Maa- ja Ruumiamet, administrative and settlement division, 2 September 2026 (public data terms)
- Central Statistics Office and Tailte Γireann, Census 2022 built-up areas (CC BY 4.0)
- Stats NZ, territorial authorities and urban-rural areas 2026 (CC BY 4.0): this work is based on Stats NZ data licensed for reuse under CC BY 4.0
- Ville de Luxembourg, quartiers on data.public.lu (CC BY 4.0)
- Ministry for Development of Communities and Territories of Ukraine, Codifier of administrative-territorial units and territories of territorial communities (KATOTTG), 7 July 2026 (CC BY 4.0): names and codes matched to records; CSC romanised the names under Cabinet of Ministers Resolution 55 (2010)
- Statistics South Africa, Census 2011 main places, distributed by UCT Libraries: main-place codes and classes matched to records; the mapping to
typeis CSC's
Country names in some languages follow Unicode CLDR 48.2: Copyright Β© 2015-2024 Unicode, Inc., under the Unicode License v3, whose notice must travel with copies.
Source credits and notices for 63 sources are in .github/licenses/SOURCES.txt; export releases attach it with the other notices. The register also identifies 233 sources whose redistribution basis remains under review. Keep the applicable credits and notices when redistributing the data.
Support
If this project saves you time, please consider supporting its continued maintenance.
You can also plant a tree on behalf of the project.
Reach out: gadadarshan [at] gmail [dot] com
Sponsors
Disclaimer
Community-maintained data may contain errors or lag behind geopolitical changes. Verify critical data with official sources. Report issues.
Releases V5.0.0 (`docs/releases/v5.0.0.md`)
Countries States Cities Database v5.0.0
Counts describe source commitd8a54626622012ee9f520108fddfdd8d11f29ae8,
compared with the v4.0 snapshot.
What this release changes
v5 is the corrective major after v4. It repairs ids that disappeared during the v4 export series,
separates administrative territories from the places that serve as their seats, and replaces
postcode values whose source support was missing. It also introduces cities without a state and
counties that belong to several regions.
This is a major because it removes keys, repairs ids that had come to denote another entity,
and changes the schema and documented settlement filters. From v5 onward, an id identifies one
geographic entity within its table. Regular releases can correct its facts and add records;
removals and incompatible contract changes wait for a major. Retired ids cannot be assigned to
another entity. A reviewed restoration of the same entity is allowed.
See the data versioning contract.
Breaking changes
Removed and repaired ids
Keys present in v4.0 but absent from this candidate:
| Table | Removed ids | Main reasons |
|---|---|---|
| Countries | 0 | No country id retired in this comparison. |
| States | 8 | Achaea moved to counties; seven states retired by the four reforms below. |
| Counties | 9 | Connecticut's 8 historical counties, with no successor; Alaska's Valdez-Cordova, split in two. |
| Cities | 3,485 | Administrative units moved to other tables, unit/seat distinctions, reviewed duplicates, no proved successors, and identity repairs. |
| Postcodes | 133,243 | Unsupported source or locality scope, replaced code namespaces, and reviewed duplicate removal. |
These are endpoint counts, not a count of all historical removal events. The migration manifest
also reports events and restorations. Use the individual reviewed reason, rather than assuming
that a retired row represents a place or postal code that disappeared in the real world.
1,353 city ids that had come to denote a different entity are retired, with fresh ids for
the later entity. An administrative district and its seat town are distinct entities even when
their names match. Do not replace every retired unit id with its seat's id. The migration files
separately describe the original entity and the later entity.
Cities without a state
state_id and state_code may both be null for a city in a country with no states. Accept the
null pair in storage, response models and filters. A mandatory join through states would lose
these cities. In nested country exports, read the country-level cities array as well as cities
inside states; MongoDB omits a state reference for such a city.
Western Sahara has 3 such cities in contributions/cities/EH.json: Gueltat Zemmour, Imlili
and Smara. Their city ids stay the same when they move from MA to EH. They do not acquire a
Moroccan state or a fabricated EH state.
See the nullable-state change
and the territory data changes.
Counties in several regions
7 New Zealand councils now have 16 county-region links. A county either has its
usual state pair, or has both fields null and a states list of {state_id, state_code} pairs.
A linked city still has its own state, which must be one of the county's regions.
Relational exports use county_states (county_id, state_id). CSV and PLIST supply a separate
county-state relation file; Parquet and TOON encode the list as JSON text. Update consumers
that assume a county always has one state. See the format and schema changes.
Schema and SQL imports
Apply the nullable city-state and county-region schema upgrades before loading into an existing
database, or rebuild using the schema supplied with this snapshot. SQL INSERT statements now
name their columns. Importers that parse positional INSERTs must accept column lists; a custom
schema must still provide the named columns and compatible types.
See the database upgrade instructions
and the dump change.
Migrating ids you have stored
Pin the exact data snapshot you use. An API protocol version or npm/PyPI package version alone
is not a data snapshot. The owner will confirm API and package rollout dates separately; this
page does not mean those products have already switched.
The first v5 export's builder supplies migrations-from-v4.0.tar.gz, withMIGRATIONS_SHA256SUMS and MIGRATIONS_SOURCE. Verify the archive checksum and source commit.
Inside, release_manifest.json identifies from.sha, to.sha, release versions, per-table
counts and file checksums. The candidate uses migration format 3.
Use removed_ids.jsonl (or its CSV view) to look up (old_table, old_id), not an id alone.
Check present_at_from, present_at_to and restored_at: the file is a history of removals,
and a key that was later restored and is present at the target is not currently retired.current_targets follows relations to the end of the interval. Multiple targets need a choice;
empty targets or a terminal no-successor outcome supply no replacement.
Read identity_changes.jsonl too. For a repaired id, current_targets refers to what the id
originally denoted; later_entity_targets refers to what it later came to denote. Match the
meaning in your stored record. A prior entity marked ended or unrecorded can have no target.
Neither identity repair nor territorial succession, split, dataset move or seat relationship
permits an automatic redirect.
Only a current_targets entry whose automatic_redirect is true can be applied automatically:
every step must be a reviewed merge of the same entity. For example, the reviewed duplicate
postcode 85289 β 85290 keeps the existing Larnaka record; the
postcode change records that merge.
A guarded lookup looks like this:
import json
for line in open('removed_ids.jsonl', encoding='utf-8'):
event = json.loads(line)
if (event['old_table'], event['old_id']) != ('postcodes', 85289):
continue
if event['present_at_to']:
continue # not retired at the target snapshot
for target in event['current_targets']:
if target['automatic_redirect']:
print(target['table'], target['id']) # postcodes 85290Back up your mappings, apply reviewed choices to your own references, and check that every
resulting (table, id) exists in the pinned v5 snapshot. Keep unresolved cases for manual review.added_ids.jsonl lists additions; changed_fields.jsonl gives typed before/after values and
presence flags for retained keys.
If you use a later v4 export, load v5 data fresh and use the cumulative history to map the ids
you stored. Do not patch that export with the cumulative added/changed files: those are relative
to v4.0, and some ids in later exports did not exist at that baseline. The current builder does
not supply an export.51 delta. Subsequent v5 exports supply a step from the previous published
v5 snapshot; apply matching steps in order.
See the migration files and archive rules.
Unresolved records and strict use
This candidate retains 12,140 keys whose latest identity decision is unresolved.
The data does not yet prove whether each legacy row originally denoted a settlement or a
territory. Independently proved facts can remain, while unproved category, hierarchy or item
changes are withheld. An unresolved row never redirects automatically.
Start with the cumulative identity_changes.jsonl, including its baseline: true entries.
Keep the latest decision for each (table, id) in file order; apply later releases' decisions
and reviewed removals. Strict territorial users exclude retained keys whose latest outcome isunresolved. Absence from a later file does not resolve a key. A settlement type filter alone
is not a substitute for this exclusion. Disclosure of an unresolved key does not approve
a pending name or territorial change; outstanding publication holds still need a decision.
Data changes to check before switching
Postcode coverage
Removed postcode ids since v4.0 include Malta 25,813, China 19,255, Myanmar 17,331,
Paraguay 8,644, Tunisia 4,860, Nigeria 3,728, Tanzania 3,684,
Argentina 10,628, South Africa 4,953, Ukraine 4,422, and Spain 8,124.
The full country/outcome breakdown is in appendix_postcode_removals_by_country.csv.
A replacement product must support the entity the id denoted: sometimes a code alone,
sometimes a code plus locality, district or delivery kind. Malta's locality prefixes and China's
general codes cannot silently replace finer delivery codes. Some rows retire even though their
code occurs in the replacement product. A removal for missing source support is not a finding
that mail cannot be delivered there. Supported values were re-derived; unsupported points,
localities and links may be null. Spanish municipality codes used as postal ids were replaced
with actual postal-code coverage rather than redirected by number.
After those removals, 4,137 postcodes were added for 24 countries left with little or no coverage, from
OpenStreetMap (ODbL, only codes with an explicit street address basis) and GeoNames (CC BY), each with a fresh id: for
example Iran 2,632, China 402, Vietnam 246, Greece 139, Nigeria 101 and Paraguay 100. Their state and city links are
empty until proved. See the additions.
United States counties and towns
US counties now match the US Census Bureau's 2024 Gazetteer: 3,144 counties, all its entries reconciled. Connecticut's
8 historical counties retire with no redirect, because the 9 planning regions that replaced them in 2022 are a
different geography; the regions are added as counties, and 179 of Connecticut's 182 cities link to one. 63 missing
county-equivalents are added, including Virginia's 38 independent cities, and Alaska's Valdez-Cordova splits into
Chugach and Copper River. Puerto Rico's municipios stay under the PR country. 610 New England towns that had no city
row are added with fresh ids, and 44 city populations that were wrong are corrected or cleared. See
the counties and
the towns.
Country names
Two display names follow Unicode CLDR 48.2.0's short forms, as the naming rule in
DISPUTED_AND_SPECIAL_TERRITORIES.md sets out:
Palestine's English name is now "Palestine" (was "Palestinian Territory Occupied"), and all its translations use the
short form (for example ru ΠΠ°Π»Π΅ΡΡΠΈΠ½Π°, ar ΩΩΨ³Ψ·ΩΩ, ko νλ μ€νμΈ, nl Palestina); Taiwan's Japanese and Chinese translations
are now ε°ζΉΎ. Codes and ids are unchanged; the former values are the before values in changed_fields.jsonl.
See the name change and
its follow-up.
Territories, names and moves
The CN-TW and CN-HK unit rows in the city table retire, with mappings to the TW and HK state
tables. TW and HK remain separate country lookups; CN-TW and CN-HK remain catalogue entries.
These cross-table mappings are not automatic city redirects. Western Sahara's province rows
in the city table retire to their existing MA state records.
For the owner's check: Crimean names follow Ukraine's official romanisation, with
283 name changes in the earlier territory update,
including legal renames such as Krasnoperekopsk β Yany Kapu and Kalinino β Umiut.
Har Adar and Modiin Ilit move from IL to PS; their local names and Israeli clock remain.
East Jerusalem's clock changes from Asia/Gaza to Asia/Jerusalem.appendix_renames_moves_for_review.csv lists endpoint name, country, state, county, parent and
point changes on retained keys, plus the earlier territory update separately, including its
later-retired rows. These comparison groups overlap and must not be summed. Identity decisions
are included where available; a changed label or point alone does not prove continuity.
Γ
land is restored under its original states 1509 key as FI-01, the same catalogue entity.
This is a reviewed same-entity restoration, not reuse for a new place.
See the restoration.
Settlement queries
Update to the documented settlement query:
exclude administrative-only and defunct types; additionally exclude municipality in MX, GR
and VN, and names beginning Gemeente in NL. Require non-null coordinates. Keep null types
only if your use case accepts unclassified records. The Vietnam rule distinguishes new
commune/ward territories from former cities and towns retained as urban places.
SELECT * FROM cities
WHERE (type IS NULL OR type NOT IN (
'county', 'regency', 'prefecture', 'parish', 'banner', 'province',
'area', 'oblast', 'administrative zone', 'region', 'abandoned',
'historical', 'destroyed', 'religious', 'historical_capital'
))
AND (country_code NOT IN ('MX', 'GR', 'VN') OR type IS NULL OR type <> 'municipality')
AND NOT (country_code = 'NL' AND name LIKE 'Gemeente %')
AND latitude IS NOT NULL AND longitude IS NOT NULL;The earlier type-only review documented 247 membership changes: 216 leaving
and 31 entering, across AU 1, CA 1, CN 1,
GR 22, KR 29, MX 142 and ZA 51.
This historical list is preserved in appendix_settlement_query_changes.csv, with each row's
current presence, type and query membership. After the subsequent identity corrections, that
same cohort has 10 leaving and 0 entering relative to v4.0.
The historical total is not the final release's total query difference.
State reforms
- South Korea: South Jeolla (states 3856) retires as territorial_successor; current targets: states 5854; Gwangju (states 3858) retires as territorial_successor; current targets: states 5854. The new state codes are project-assigned, not ISO issuances.
- Estonia: JΓ΅hvi (states 5746) retires as territorial_successor; current targets: states 5855; Toila (states 5788) retires as territorial_successor; current targets: states 5855. The new state codes are project-assigned, not ISO issuances.
- Angola: Cuando Cubango (states 226) retires as split_into; current targets: states 5856, states 5857. The new state codes are project-assigned, not ISO issuances.
- Latvia: VarakΔΌΔni (states 4431) retires as territorial_successor; current targets: states 5858; Madona (states 4433) retires as territorial_successor; current targets: states 5858. The new state codes are project-assigned, not ISO issuances.
Sources and reuse
CSC's own ODbL licence is unchanged. The source products and required credits have changed.
Much postcode data is now re-derived from named GeoNames products under CC BY, alongside
national open products. Malta and China also use OpenStreetMap under ODbL; Taiwan uses
Chunghwa Post under Taiwan's Open Government Data License. Other replacements include
Kadaster's public-domain postcode data and Ordnance Survey Code-Point Open. US counties and
New England towns come from US Census Bureau files, which are public domain.
Keep the supplied SOURCES.txt and accompanying licence notices with redistributed data,
including the specified attribution, source editions, licence links and modification notices.
Do not assume CSC's licence removes a source's attribution requirements. Some former sources
are excluded; others support only the narrower facts identified in their notices.
See the source credits and conditions.
v4 support
The API keeps serving v4 data for six months after v5.0.0 is published, until 19 April 2027. v4
downloads and the migration files stay available. Switch your clients and stored ids within that window.
--- METRICS ---
- Files Extracted: 2
- Estimated Token Budget: ~8083 tokens
- Canonical Reference: https://codewiki.google/github.com/dr5hn/countries-states-cities-database