How countries differ
Every ISO 3166-1 country has rules, and 91 of them have a layout of their own. The other 158 share the default layout, which is permissive by design. All countries lists the 91, each with a page showing its form and every rule.
Everything that is a decision about one country is in that country's file, src/rules/ and its code: its rows, its wording, its postcode pattern, its example and its written form. The reasons behind a country's choices are under Country notes.
What actually differs
| Country | Rows after the name | State | Postcode |
|---|---|---|---|
| US | line1 / line2 / city · state · postcode | State (select) | ZIP Code, 90210 |
| CA | line1 / line2 / city · state · postcode | Province (select) | Postal code, K1A 0B1 |
| GB | line1 / line2 / city · postcode | none | Postcode, SW1A 1AA |
| DE | line1 / line2 / postcode · city | none | Postleitzahl, 10115 |
| JP | postcode · state / city / line1 / line2 | Prefecture (select) | 100-0001 |
| BR | postcode / line1 / line2 / city · state | State (select) | 01310-100 |
| IN | line1 / line2 / city · state · postcode | State (select) | PIN code, 110001 |
| HK | line1 / line2 / city · state | Region (free text) | none |
| TH | line1 / line2 / city · state · postcode | Province (select) | 10200 |
| GI | line1 / line2 | none | fixed GX11 1AA |
| default | line1 / line2 / city · state · postcode | free text, optional | optional, never validated |
Every address layout starts with country, then the name, and ends with phone_number: the table leaves those out. The name is written given name first everywhere but Japan and Korea. The email is in every country's fields and in no layout.
A few countries have one city or one postcode for every address, and a form does not ask for it: address.fixed sends it. Vatican City fixes both (Vatican City, 00120), as do Gibraltar, the Falklands and Turks and Caicos their one postcode, Anguilla its postcode, Singapore and Monaco their city.
Thailand is worth reading closely, for what it does not collect. A Thai address has four administrative levels (จังหวัด → อำเภอ → ตำบล → postcode), but this form collects three: orders from some stores are forwarded to order systems with no field for a ตำบล, so one collected here would be dropped at that boundary. The customer writes it on the street line instead. The reasoning, and what to do if that constraint ever lifts, is under Thailand.
The differences are not cosmetic. Germany collects no state at all. Hong Kong collects a district but no postcode. Japan writes largest-unit-first, so its postcode and prefecture lead the form. Some countries collect no postcode or no city at all, and some fix one to its single value. A single "international" address form is wrong for most of this list.
Wording differs too, from the same field: Postal code vs Postcode vs ZIP Code vs PIN code; City vs District; State vs Province vs County vs Prefecture vs Emirate vs Governorate vs Region.
The two street lines are the deliberate exception. They read Address and Apartment, suite, etc. in every country, translated but never re-worded: what goes on them varies far less than what the administrative fields are called, and a visitor should not meet Address on one checkout and Street and house number on the next.
Which fields a country requires
A country names the layouts it wants, and they list the rows. That list is also what makes the administrative fields required: collected means required, absent means not collected at all. There is no second list of required fields to keep in step.
Required-ness follows a field's autocomplete token, not its name: anything carrying address-level1–4 or postal-code is required wherever a curated layout collects it. The default layout is the exception, below. Which is why a line3 declared as address-level3 would be required, while the same field name used as a third street line is not. No country declares one today.
country, first_name, last_name, email and line1 are required everywhere. line2, line3 and phone_number are never required by a country; a page can require them per form.
The default layout
A country with no layout of its own is not an error. It gets the default layout under its own code, with curated: false, a free-text state and a postcode, both optional, and no postcode pattern at all: whatever the visitor types is accepted. Dozens of countries have no postcode system (Ghana, Angola, most of the Caribbean) and many have no state level, so requiring either would make a shopper there invent one. The city stays required.
It is deliberately permissive, because a wrong rule is worse than a missing one. Nobody should be blocked from checking out because we guessed their address format. The same applies to the postcode, and more sharply: an odd-looking form is survivable, a rejected postcode is not. Validation is something a country earns by having a layout of its own, where its pattern sits beside an example that a test checks it against. The same goes for a code with no file at all: it gets the default layout, and no currency or region.
State values
state submits a string, and which string depends on the country:
| Country | Value | Example |
|---|---|---|
| US, CA, AU | ISO 3166-2 suffix | CA, ON, NSW |
| every other enumerated country | the subdivision name | Tokyo, Baden-Württemberg |
| countries with no list (HK, and any uncurated country) | whatever was typed | Hong Kong Island |
The split is interop, not taste: it matches what existing orders already store, so a form built with this package produces values comparable to the ones already in the database. Changing it would orphan every stored address, so it is fixed, and a change to it is a major version (see Versioning).
28 countries have an enumerated list, covering 1,050 subdivisions. Ireland offers counties only. Lists are sorted by name, and a country whose layout has no state has no list at all.
Postcodes by state
A postcode can be the right shape for its country and still not be the chosen state's: 10001 is a US ZIP code, and New York's, not California's. POST /v1/validate checks a postcode against the state sent beside it, by how that state's postcodes start, and answers not_in_state when they do not match. The prefixes are libaddressinput's, for 673 states in 15 countries: Argentina, Australia, Brazil, Canada, India, Italy, Japan, Malaysia, Mexico, the Philippines, Russia, South Korea, Spain, Thailand and the US. Each country's page lists its own, under Postcode.
A state libaddressinput has no prefix for is checked by pattern only, as is every state of the other countries. A few real addresses sit across a state line from their postcode (Texhoma, Texas has an Oklahoma ZIP code; some New South Wales towns near the border have Queensland postcodes), so a form that refuses not_in_state refuses those too. See POST /v1/validate.
Phone numbers
Every inhabited country carries its ITU calling code and a valid example number, from libphonenumber: 242 of them. The seven uninhabited territories carry neither, rather than a guess. The example is the national form (081 234 5678), and the submitted value is E.164 (+66812345678), from POST /v1/validate. A country on the default layout has no pattern, so its number is not checked. A country with a layout of its own also carries a loose phone rule, display masks and a digit-count pattern. The calling code, prefix and example are libphonenumber's; the masks and the pattern are ours, held to its example numbers by the tests. See Phone numbers.
Languages
Twelve: da de en es fi fr it nl no pt sv th. Labels and validation messages are written for this package, not lifted from a platform catalog. A test asserts every language holds the same keys as English, with the same placeholders, so a form is never half-translated. Every text is under Languages. Country names come from Intl.DisplayNames, so they are localized for every language the runtime knows.
Country notes
Why a country's file says what it says, where that is not obvious from the file.
Thailand
A Thai address has four administrative levels, not three: จังหวัด (province) → อำเภอ/เขต (district) → ตำบล/แขวง (sub-district) → postcode. This form collects only three of them on purpose.
The sub-district has no field because orders from some stores are forwarded to order systems whose Thai address has three levels: city, province and postcode. A sub-district collected into a fourth field would be dropped at that boundary, or folded back into the street line by whatever does the forwarding. Collecting three levels means the address that leaves here is the address that arrives there. So a Thai customer writes the ตำบล on the street line:
100 ม.12 ต.ผาขาว line1 (house number, moo, sub-district)
อ.ผาขาว city
เลย 42240 state, postcodeThis is an interop decision, not a claim about Thai addresses. Google's libaddressinput does give Thailand a sub-district (%N%n%O%n%A%n%D %C%n%S %Z, where %D is the dependent locality), and it is right that a Thai address has one. If that forwarding goes away, the field should come back on its own row before the district, with "fields": { "line3": { "autocomplete": "address-level3" } } so that autofill knows what it is.
Argentina
The phone rule has no calling_code. Argentine mobiles are dialled with a 15 inside the number, which dropping the national prefix does not undo, so the number is sent as typed and the order API converts it.
Adding a country
One file: see Adding a country.