Cheatsheet

Country Codes Reference

This reference lists ISO 3166-1 country codes for the countries developers meet most, in all three formats, with the exceptions that cause bugs. It is for anyone filling a country dropdown, storing an address, setting a locale or choosing between "US" and "USA". The confusion it clears up is that GB is the ISO code for the United Kingdom while UK is only an exceptional reservation, and that Kosovo has no official code at all.

Quick reference

The three code formats

Format Length Example for Germany Typical use
Alpha-2 2 letters `DE` Locales, ccTLD-style domains, address forms, payment APIs
Alpha-3 3 letters `DEU` Customs, sports, passports, some banking data
Numeric-3 3 digits `276` Script-independent systems. Keep the leading zeros

ISO 3166-1 has 249 officially assigned entries (via search summary). That is more than the number of sovereign states, because dependent territories are included.

Which format to store

Store alpha-2 unless a partner requires another format. It is the shortest, it is what locale tags, region subtags and flag emoji use, and most payment and address APIs expect it. Keep alpha-3 or numeric only as extra columns for systems that demand them, and map between them with one maintained lookup table rather than string tricks, since alpha-3 is not always the alpha-2 code plus a letter.

Common countries

Country Alpha-2 Alpha-3 Numeric
Argentina AR ARG 032
Australia AU AUS 036
Brazil BR BRA 076
Canada CA CAN 124
China CN CHN 156
Egypt EG EGY 818
France FR FRA 250
Germany DE DEU 276
India IN IND 356
Indonesia ID IDN 360
Ireland IE IRL 372
Italy IT ITA 380
Japan JP JPN 392
Mexico MX MEX 484
Netherlands NL NLD 528
New Zealand NZ NZL 554
Nigeria NG NGA 566
Philippines PH PHL 608
Poland PL POL 616
Saudi Arabia SA SAU 682
Singapore SG SGP 702
South Africa ZA ZAF 710
South Korea KR KOR 410
Spain ES ESP 724
Sweden SE SWE 752
Switzerland CH CHE 756
Türkiye TR TUR 792
Ukraine UA UKR 804
United Arab Emirates AE ARE 784
United Kingdom GB GBR 826
United States US USA 840
Vietnam VN VNM 704

Codes that are not what they look like

Code Meaning Status
GB United Kingdom Official ISO 3166-1 code
UK United Kingdom Exceptionally reserved, not an assigned code. It is the ccTLD `.uk`
XK Kosovo User-assigned, used by the European Commission, IMF and SWIFT
EU European Union Exceptionally reserved. It is also a region subtag in the IANA language registry
XA to XZ Private use Never assigned by ISO

Common patterns

Look up a country name from a code

const dn = new Intl.DisplayNames('en', { type: 'region' });
console.log(dn.of('DE'), '|', dn.of('US'), '|', dn.of('TR'));
console.log(dn.of('XK'), '|', dn.of('UK'), '|', dn.of('EU'), '|', dn.of('ZZ'));
Germany | United States | Türkiye
Kosovo | United Kingdom | European Union | Unknown Region

Intl.DisplayNames uses CLDR data and needs no table in your code. It accepts UK and XK even though ISO does not assign them, so validate separately if you need strict ISO codes. Change the first argument to get names in another language.

Handle case and invalid input

const dn = new Intl.DisplayNames('en', { type: 'region' });
console.log(dn.of('us'));
try { console.log(dn.of('usa')); } catch (e) { console.log(e.name + ': ' + e.message); }
console.log(new Intl.Locale('en-us').region);
us
RangeError: invalid_argument
US

A lowercase code is echoed back unchanged instead of resolved, and a three-letter code throws. Uppercase alpha-2 codes before the lookup. Intl.Locale normalizes the region for you.

Convert alpha-2 to the two Unicode code points of a flag

const flag = c => [...c].map(ch => 'U+' + (0x1F1E6 + ch.charCodeAt(0) - 65).toString(16).toUpperCase()).join(' ');
console.log(flag('DE'), '|', flag('US'));
U+1F1E9 U+1F1EA | U+1F1FA U+1F1F8

A flag is two regional indicator symbols, one per letter, starting at U+1F1E6 for A. That works only with alpha-2 codes, which is one reason to store alpha-2.

Store a code in a database

CREATE TABLE address (
  id INTEGER PRIMARY KEY,
  country CHAR(2) NOT NULL CHECK (country = UPPER(country) AND LENGTH(country) = 2)
);

Keep the alpha-2 code as text, uppercase, with a length check. Never store the numeric code as an integer, because Brazil's 076 becomes 76.

de -> CHECK constraint failed: country = UPPER(country) AND LENGTH(country) = 2
DEU -> CHECK constraint failed: country = UPPER(country) AND LENGTH(country) = 2
[(1, 'DE')]

This is the SQLite result of inserting DE, de and DEU. Only the uppercase two-letter value is accepted, so bad data is rejected at the database instead of surfacing in a report.

Pitfalls

  • Using UK instead of GB: UK is not an assigned ISO 3166-1 code. Many libraries reject it. Store GB and show "UK" in the interface if your users expect it.
  • Treating XK as official: Kosovo has no ISO code. XK is a widely used private-use convention, so check that your payment, tax or shipping provider accepts it.
  • Storing the numeric code as a number: codes such as 076, 036 and 032 lose their leading zeros. Keep them as three-character strings.
  • Confusing country codes with language codes: en-GB is a language and region pair, where GB is the region. cs is a language, while CZ is a country. Language and country are separate lists.
  • Mixing alpha-2 and alpha-3 in one column: US and USA both mean the same place but never match in a join. Pick one format per column.
  • Assuming the top-level domain equals the country code: .uk is delegated to Nominet, while the ISO code is GB. A .gb delegation exists in the IANA root zone database but is marked reserved.
  • Relying on a lowercase lookup: as the run above shows, Intl.DisplayNames returned us for us. Normalize case at the boundary.
  • Hardcoding the count: 249 is the assigned count at the time of writing. ISO can change entries, so load a maintained list instead of a literal number.

Related ZipKit tools

Related cheatsheets