Compare

@koshmoney/countries vs country-state-city

country-state-city is a comprehensive geographical data library that includes countries, states, and cities worldwide. It is the go-to package when you need city-level data. Here is how it compares to @koshmoney/countries.

Feature Comparison

Feature@koshmoney/countriescountry-state-city
Countries249 (ISO 3166-1)249
Subdivisions/States5,000+ (ISO 3166-2)5,000+ states
CitiesNot included150,000+ cities
Postal Code Validation150+ countriesNot included
Currency DataISO 4217Basic currency info
Phone Dial CodesVia libphonenumber-jsPhone codes
CoordinatesNot includedLat/lng for countries, states, cities
TimezonesNot includedTimezone data
EU/SEPA/EEA MembershipBuilt-inNot included
Geography (Continent/Region)UN M49Not included
Code ValidationFull validation suiteNot included
Alpha-3/Numeric CodesYesLimited
TypeScript SupportBuilt-inBuilt-in
Tree-ShakingSubpath exportsPartial
Full Bundle Size~60KB gzipped~2MB+ gzipped
Dependencies0 (core)0

Where country-state-city Wins

City Data

The defining feature. country-state-city includes 150,000+ cities with coordinates. If your application needs city-level data (autocomplete, location pickers, geographic searches), this is what you need:

// country-state-city
import { City } from 'country-state-city';
 
City.getCitiesOfState('US', 'CA');
// [{ name: 'Los Angeles', latitude: '34.05223', longitude: '-118.24368' }, ...]
 
City.getCitiesOfCountry('JP');
// [{ name: 'Tokyo', ... }, { name: 'Osaka', ... }, ...]

@koshmoney/countries does not include city data. If cities are a core requirement, country-state-city is the right choice.

Coordinates and Timezones

country-state-city includes geographic coordinates and timezone information for countries and states. This is useful for map-based UIs and timezone detection.

Where @koshmoney/countries Wins

Bundle Size

This is the most significant difference for frontend applications:

Import@koshmoney/countriescountry-state-city
Full library~60KB gzipped~2MB+ gzipped
Country only~8KB gzippedNot separable
Country + 1 state set~10KB gzippedNot separable

country-state-city includes all cities in the bundle even if you only need countries and states. The city JSON alone is ~8MB raw (~2MB gzipped after minification). For frontend applications where bundle size matters, this is a significant cost.

Granular Tree-Shaking

@koshmoney/countries lets you import data at the individual country level:

// Load only US and Canada subdivisions: ~10KB total
import '@koshmoney/countries/subdivision/US';
import '@koshmoney/countries/subdivision/CA';
import { forCountry } from '@koshmoney/countries/subdivision';
 
forCountry('US');  // Works
forCountry('CA');  // Works
forCountry('GB');  // Returns [] (not loaded)

Postal Code Validation

import { postalCode } from '@koshmoney/countries';
 
postalCode.isValid('US', '90210');       // true
postalCode.isValid('GB', 'SW1A 1AA');    // true
postalCode.isValid('JP', '100-0001');    // true
postalCode.getFormat('CA');              // 'A1A 1A1'
postalCode.getName('DE');                // 'PLZ'

EU/SEPA Membership

import { membership } from '@koshmoney/countries/membership';
 
membership.isEU('FR');          // true
membership.isSEPA('GB');        // true
membership.isEurozone('DE');    // true
membership.getMembers('EEA');   // 30 EEA countries

Code Conversion and Validation

import { country } from '@koshmoney/countries';
 
country.alpha2ToAlpha3('US');      // 'USA'
country.alpha3ToAlpha2('GBR');     // 'GB'
country.alpha2ToNumeric('DE');     // '276'
country.isValid('US');             // true
country.detectFormat('USA');       // 'alpha3'

ISO 3166-2 Compliance

@koshmoney/countries uses official ISO 3166-2 codes (e.g., US-CA, GB-ENG). country-state-city uses its own code format that may not match the ISO standard exactly.

API Comparison

Getting States/Subdivisions

// country-state-city
import { State } from 'country-state-city';
State.getStatesOfCountry('US');
// [{ name: 'Alabama', isoCode: 'AL', countryCode: 'US', ... }]
// @koshmoney/countries
import { subdivision } from '@koshmoney/countries';
subdivision.forCountry('US');
// [{ code: 'US-AL', name: 'Alabama', type: 'State', regionCode: 'AL', ... }]

Looking Up a Country

// country-state-city
import { Country } from 'country-state-city';
Country.getCountryByCode('US');
// { name: 'United States', isoCode: 'US', phonecode: '1', currency: 'USD', ... }
// @koshmoney/countries
import { country } from '@koshmoney/countries';
country.whereAlpha2('US');
// { name: 'United States', alpha2: 'US', alpha3: 'USA', numeric: '840' }

Migration Guide

States/Subdivisions

// Before (country-state-city)
import { State } from 'country-state-city';
const states = State.getStatesOfCountry('US');
const california = states.find(s => s.isoCode === 'CA');
// After (@koshmoney/countries)
import { subdivision } from '@koshmoney/countries';
const states = subdivision.forCountry('US');
const california = subdivision.where('US', 'CA');

Country Lookup

// Before
import { Country } from 'country-state-city';
const us = Country.getCountryByCode('US');
 
// After
import { country } from '@koshmoney/countries';
const us = country.whereAlpha2('US');

When to Choose Which

Choose country-state-city if:

  • You need city-level data (autocomplete, location pickers)
  • You need geographic coordinates for mapping
  • You need timezone data
  • Bundle size is not a primary concern (backend or SSR)

Choose @koshmoney/countries if:

  • You do not need city data
  • Bundle size matters (frontend applications)
  • You need postal code validation
  • You need EU/SEPA/Eurozone membership checks
  • You want ISO 3166-2 compliant subdivision codes
  • You need code conversion between alpha-2, alpha-3, and numeric formats
  • You want tree-shakeable imports

Use both together if: You need cities for some features and small bundles for others. Use @koshmoney/countries on the frontend for dropdowns and validation, and country-state-city on the backend for city-level queries.