Engineering guide
Global Address and Phone Number Standards
Implement global address and phone data with UPU S42, ITU-T E.164, adaptive forms, E.164 storage, regional display, parsing, and validation.
Reviewed 19 July 2026 · Editorial owner: localization.guide
Do not model either field as “just a string”
An address is a structured set of country-dependent components rendered through a regional template. A phone number combines a calling-code plan, national numbering metadata, and a display context. Keep the user’s original input for correction, store normalized values where appropriate, and render for the selected destination or audience rather than forcing one global layout.
Address order changes by country and script
| Region | Illustrative local order | Implementation implication |
|---|---|---|
| United States | Recipient 123 Main St Boston, MA 02110 | City, state abbreviation, and ZIP commonly share a line. |
| United Kingdom | Recipient 10 High Street LONDON SW1A 1AA | Post town and postcode are distinct concepts; a state field is usually inappropriate. |
| Germany | Recipient Musterstraße 42 10115 Berlin | House number follows the road name; postcode precedes city. |
| Japan | 〒100-0001 東京都千代田区千代田1-1 受取人 | Native-script order proceeds from larger to smaller geographic units; Latin-script mail may use another template. |
| India | Recipient 12 MG Road Mumbai, Maharashtra 400001 | State and six-digit PIN matter; locality details can be essential in delivery workflows. |
UPU S42 separates a generic vocabulary of postal components from country-specific templates. Follow that model: store named components, then render with a maintained template for the destination country and script.
Build an adaptive, forgiving address form
Change labels and order
Load the country first, then show relevant fields with regional labels such as state, province, prefecture, county, postcode, ZIP, or PIN. Do not mark a field required merely because another country requires it.
Preserve what the user typed
Normalize cautiously. Allow diacritics and local scripts, retain apartment/building detail, and offer a correction instead of silently rewriting a valid unfamiliar format.
Use browser semantics
Apply autocomplete tokens such as `name`, `street-address`, `address-line1`, `address-level1`, `address-level2`, `postal-code`, and `country`. Pair every input with a visible label and useful error text.
Validate deliverability separately
Field completeness, syntactic plausibility, geocoding, and postal deliverability are different checks. A regex cannot prove that a destination receives mail.
Phone storage and display serve different jobs
| Country | E.164 storage | International display | National display |
|---|---|---|---|
| United States | +14155552671 | +1 415 555 2671 | (415) 555-2671 |
| United Kingdom | +442079460018 | +44 20 7946 0018 | 020 7946 0018 |
| Germany | +4930901820 | +49 30 901820 | 030 901820 |
| India | +912266613000 | +91 22 6661 3000 | 022 6661 3000 |
| Japan | +81312345678 | +81 3 1234 5678 | 03-1234-5678 |
Examples illustrate format differences and are not contact numbers or deliverability claims.
Formatting, parsing, validation, and verification are different
- Parsing
- Interprets digits using an explicit default country when no international calling code is present.
- Formatting
- Renders a parsed number as E.164, international, national, or RFC3966 output.
- Validation
- Checks the number against current length and numbering-plan patterns in the selected metadata bundle.
- Verification
- Confirms control or reachability through an SMS, voice, or another out-of-band challenge. Syntax alone cannot do this.
Parse with an explicit regional context
import { parsePhoneNumberFromString } from "libphonenumber-js";
const local = parsePhoneNumberFromString("020 7946 0018", "GB");
if (!local?.isValid()) {
throw new Error("Check the number and selected country");
}
const record = {
originalInput: "020 7946 0018",
country: local.country,
e164: local.number,
};
const nationalDisplay = local.formatNational();
const internationalDisplay = local.formatInternational();An input such as `020 7946 0018` is ambiguous without a country. Do not guess from language, IP address, or the user’s current location when a wrong interpretation would matter; ask for or preserve the selected country.
Treat metadata as versioned operational data
- Record the source, package/data version, generation date, and covered territories.
- Schedule updates because numbering plans, postal codes, administrative divisions, and currency use change.
- When a country template is missing, collect flexible address lines instead of forcing another country’s form.
- Keep test fixtures for shared calling codes, non-geographic numbers, extensions, zero-prefix rules, territories, and script variants.
- Revalidate stored phone numbers only when required; a metadata update should not silently destroy previously accepted input.
Representative fixture matrix
const fixtures = [
{ input: "(415) 555-2671", country: "US", valid: true },
{ input: "020 7946 0018", country: "GB", valid: true },
{ input: "+81 3 1234 5678", country: undefined, valid: true },
{ input: "123", country: "US", valid: false },
];
for (const fixture of fixtures) {
const parsed = parsePhoneNumberFromString(fixture.input, fixture.country);
assert.equal(Boolean(parsed?.isValid()), fixture.valid);
}Primary and official sources
- Addressing Solutions and S42 — Universal Postal Union
- ITU-T E.164 international numbering plan — International Telecommunication Union
- libphonenumber-js documentation and metadata — libphonenumber-js project
- HTML autofill field names — WHATWG