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.
| 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.
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.
| 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 |
| 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 |
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.
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.
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.
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.
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.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.US and USA both mean the same place but never match in a join. Pick one format per column..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.Intl.DisplayNames returned us for us. Normalize case at the boundary.