npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

countrycitystatejson

v26.9.2802

Published

A JSON Object containing Countries and their associated States/Provinces and cities.

Readme

countrycitystatejson

JSON data for the world's countries, states/provinces, and cities.

npm

Recent changes

2026-09-26 Fixed Bangladesh state names.
2026-08-16 Switched the package license to MIT.
2026-08-16 Dual CJS/ESM: `import` and `require` both work. `npm run release` date-bumps, commits, pushes, and publishes.
2026-04-04 Merged fixes to Tucuman province, Argentina.  (Thanks to gerohelguera)
2025-08-01 Fixed errnoneous states for India, South Africa, and Mexico.  Added correct cities for Ciudad de Mexico
2025-05-29 Added typescript definitions
2024-12-29 Fixes to Turkey (Had extra states that don't belong - Thanks Sinan997)
2023-03-27 Fixes to Maldives
2023-02-15 More fixes to Australian cities. (Thanks again andrewjdavidson)
2022-10-21 Fixed some Australian city and state information.  (Thanks andrewjdavidson)
2021-10-14 Some optimizations
2021-10-13 Added getCitiesByName method.
More accurate Nigerian states and cities.  (Thanks TheoOkafor)

Usage

ESM import and CJS require expose the same API (named exports and a default object). Native Node import needs Node 20.10+; require works on Node 18+.

import geo, { getCities } from 'countrycitystatejson'
// or: import geo from 'countrycitystatejson/server'
getCities('US', 'California')

const geoCjs = require('countrycitystatejson')
geoCjs.getCities('US', 'California')

// Client / bundlers — metadata is sync; cities lazy-load per country
import geoClient from 'countrycitystatejson/client'
await geoClient.getCities('US', 'California')
await geoClient.getCitiesByName('Los Angeles', 'US')

// Countries + states only, no city payloads (~300KB)
import countriesOnly from 'countrycitystatejson/countries'

The package has three entrypoints. The import path is which one you load (import … from '…' or require('…')):

| Import path | What it is | Best for | Cities | API | |---|---|---|---|---| | countrycitystatejson or countrycitystatejson/server | Default/full server build. Same API; loads the whole city database into memory. | Node, SSR, backends | Full in-memory DB (~2.5MB) | Sync | | countrycitystatejson/client | Browser/bundler build. Country/state metadata is small and sync; cities load one country at a time. | Browsers, bundle-sensitive apps | Lazy per-country chunks | Sync metadata + async cities (await getCities(…)) | | countrycitystatejson/countries | Metadata only: countries + state names, no city lists. | Dropdowns / forms without cities | None (~300KB) | Sync |

TypeScript types ship with both builds (dist/cjs, dist/esm).

getAll()

Full database (~2.5MB).

getCountries()

Every country plus shortName (no states/cities):

{ shortName: 'HK', name: 'Hong Kong', native: '香港', phone: '852',
  continent: 'AS', capital: 'City of Victoria', currency: 'HKD',
  languages: [ 'zh', 'en' ], emoji: '🇭🇰', emojiU: 'U+1F1ED U+1F1F0' }

getCountriesShort()

[ 'AD', 'AE', 'AF', 'AG', 'AI', 'AL', ... ]

getCountryByShort(shortName)

Country record with states keyed by state name; each value is an array of cities.

getCountryByShort('US')
// { name: 'United States', ..., states: { Alabama: [ [Object], ... ], ... } }

getCountryInfoByShort(shortName)

Same as above without states.

getStatesByShort(shortName)

State/province names for that country, or null if the code is unknown.

getCities(shortName, state)

City names for a country + state (state name from getStatesByShort). Unknown country → null; unknown state → [].

getCities('US', 'Kentucky')
// [ 'Albany', 'Ashland', 'Bardstown', ... ]

getCitiesByName(cityName)

Prefix search across the full dataset (not cheap on the server entry). Client API requires a country code: getCitiesByName(name, shortName).

getCitiesByName('lexington')
// [ { city: { id, name }, state, country }, ... ]

Developing

Do not add "type": "module" to the root package.json — that would break Jest, scripts/*.js, and root index.js. ESM is marked only in dist/esm/package.json.

In-repo tests import from src/ via Jest. That is not the same as a consumer import from 'countrycitystatejson'.

Data edits

Sources live under src/:

  • Country metadata: src/countries-list/dist/countries.json
  • Cities/states: src/country-state-city/lib/city.json and state.json (cities join states by id)

Then:

npm run compile   # writes src/lib/compiledCities.json (+ states-only + compat copy)
npm run build     # CJS + ESM entrypoints, client chunks, ESM rewrite for Node import
npm test

npm run build includes fix:modules, which rewrites dist/esm so Node can import it (.js extensions and JSON import attributes). Do not skip that step, run tsc alone, or hand-edit those ESM artifacts. dist/ is committed — include the rewritten files.

Some country fixes were applied directly to compiledCities.json. After compile, review the diff (especially AR, IN, MX, TR, ZA) before committing so curated corrections are not lost.

Convenience functions read from compiledCities.json. Please send fixes upstream so everyone gets them.

Checks

bash scripts/ci.sh          # install, build, test, import/require smoke
npm run smoke:modules       # CJS require + ESM import against package exports

Jenkins and other CI: docs/CI.md.

Publish

Working tree must be clean. Then:

npm run release

That bumps the version to YY.MM.DDnn (local date; nn is the same-day counter from npm plus the current package version), commits package.json and package-lock.json, pushes the current branch, and runs npm publish (which still runs build / test / smoke). You must already be logged in (npm login).

Why this package

Existing country and city datasets did not share a usable state/province link. country-state-city used integer IDs, which made corrections painful (the US list had seven bogus states). This package merges annexare/Countries with that city/state data and keys records by name so a recompile does not need reindexing.

License

MIT