International Postal Code Formats: A Quick Reference
Postal codes look deceptively simple until you try to validate them across borders. A field that accepts 90210 without complaint will reject SW1A 1AA or M5V 2T6 if the validation logic only knows about US ZIP codes. This guide covers the formats used in the most common countries, the regex patterns that match them, and the handful of places that don't use postal codes at all.
At a Glance
- Postal code formats range from 2 to 10 characters, mix digits with letters in some countries, and place the code either before or after the city name depending on the region.
- Modern postal codes date back to the 1932 Soviet Ukraine system, with Germany (1941), Singapore (1950), and the United States (1963) adopting their own versions later.
- Canadian postal codes deliberately exclude the letters D, F, I, O, Q, and U, confirmed by Wikipedia's breakdown of the format, which also caps the first character to 18 possible letters.
- UK postcodes split into an outward code (area plus district) and an inward code (sector plus unit), a structure documented in detail on Wikipedia.
- Not every country has a postal code system at all: Panama, Hong Kong, and the UAE are notable examples that route mail by district or address alone.
- Regex confirms shape, never existence. A code can match a pattern perfectly and still not correspond to any real delivery area.
Why Postal Code Formats Differ So Much

Postal systems evolved independently before any international standard existed. The result is a patchwork: some countries use pure digits, others mix letters and numbers, and a few use entirely different separators or positional rules. The Universal Postal Union publishes guidance, but each national postal authority sets its own spec.
The history explains a lot of the variation. According to Wikipedia's history of postal codes, the earliest postal district systems predate the modern postal code by decades: London was subdivided into 10 numbered districts in 1857, with Liverpool following in 1864 and Manchester and Salford in 1867-68. The postal code as we know it, a code appended to every address rather than just naming a city district, arrived much later: Soviet Ukraine introduced one in 1932, Germany in 1941, Singapore in 1950, and the United States rolled out ZIP codes in 1963. Each system was designed around the sorting technology and delivery volume of its own era, which is a large part of why they never converged on a shared format.
Length alone varies from two digits (parts of Iceland) to ten characters (Brazil's extended format). Case matters in some systems but not others. Several countries share a format but use completely different assignment logic underneath.
Understanding the structure helps you write validation that's strict enough to catch typos but loose enough to accept legitimate codes from anywhere on your user's signup form.
Common Country Formats at a Glance
The table below covers countries that appear most frequently in international shipping and testing datasets. The regex patterns are written to match the postal code in isolation, so strip whitespace before applying them.
| Country | Example | Format description | Regex pattern |
|---|---|---|---|
| United States | 90210 / 90210-4321 | 5 digits, optional +4 extension | ^\d\d\d\d\d(-\d\d\d\d)?$ |
| United Kingdom | SW1A 1AA | AN NAA or AAN NAA etc. | ^[A-Z][A-Z]?\d[A-Z\d]?\s?\d[A-Z][A-Z]$ |
| Canada | M5V 2T6 | ANA NAN (letter-digit alternating) | ^[A-Z]\d[A-Z]\s?\d[A-Z]\d$ |
| Germany | 80331 | 5 digits | ^\d\d\d\d\d$ |
| France | 75008 | 5 digits | ^\d\d\d\d\d$ |
| Japan | 150-0001 | 7 digits with hyphen after first 3 | ^\d\d\d-\d\d\d\d$ |
| Australia | 2000 | 4 digits | ^\d\d\d\d$ |
| Netherlands | 1234 AB | 4 digits + 2 letters | ^\d\d\d\d\s?[A-Z][A-Z]$ |
| Brazil | 01310-100 | 8 digits with hyphen after first 5 | ^\d\d\d\d\d-\d\d\d$ |
| India | 110001 | 6 digits | ^\d\d\d\d\d\d$ |
| Mexico | 06600 | 5 digits | ^\d\d\d\d\d$ |
| Sweden | 113 21 | 5 digits, sometimes written with a space | ^\d\d\d\s?\d\d$ |
For a deeper look at how these fit into full address strings, see how address formats vary by country.
Where Postal Code Data Comes From: A Timeline
Format alone doesn't tell you when a country's system stabilized, which matters if you're deciding how much edge-case handling to build. The table below traces a few landmark dates.
| Year | Milestone |
|---|---|
| 1857 | London divided into 10 numbered postal districts, the earliest precursor to a modern postal code |
| 1932 | Soviet Ukraine introduces one of the first true postal code systems |
| 1941 | Germany adopts a national postal code system |
| 1950 | Singapore introduces postal codes |
| 1959-1974 | United Kingdom rolls out its national postcode system in stages, starting with a Norwich pilot |
| 1963 | United States rolls out ZIP codes |
| 1971 | Canada begins testing its alphanumeric postal code system in Ottawa, expanding nationwide through 1974 |
| 2015 | Ireland introduces Eircode, one of the most recent national systems |
Systems adopted more recently, like Eircode, tend to be more granular from the start (Eircode identifies individual buildings) because the technology to assign and process that level of detail already existed by the time they launched. Older systems like the five-digit US ZIP code were designed for the sorting technology of 1963 and have had ZIP+4 bolted on since to add precision without a full renumbering.
Writing Regex Patterns for Postal Code Validation
A few principles make postal code regex more reliable in practice.
Case normalization first. UK, Canadian, and Dutch codes use uppercase letters by convention, but users type them in lowercase all the time. Normalize to uppercase before running validation rather than writing case-insensitive patterns. sw1a 1aa becomes SW1A 1AA, which your regex can match cleanly.
Treat the space as optional. UK, Canadian, Dutch, and Swedish codes traditionally include a space, but many databases and form fields strip it. Write your pattern to accept both M5V2T6 and M5V 2T6. The \s? placeholder handles this without needing two separate patterns.
The UK format is genuinely tricky. UK postcodes split into two parts: the outward code, made up of the postcode area and district, and the inward code, made up of the sector and unit. For the example LA1 1EX, LA is the area, 1 is the district, 1 is the sector, and EX is the unit. The outward code alone can be one or two letters, one or two digits, and optionally a trailing letter. Valid outward codes include W1, W1A, SW1, SW1A, EC1A, and EC1. A simplified pattern like ^[A-Z][A-Z]?\d[A-Z\d]?\s?\d[A-Z][A-Z]$ covers most real addresses but doesn't rule out every impossible combination. For thorough UK validation, a lookup against the Royal Mail's postcode database is more reliable than regex alone.
US extended ZIP codes. The ZIP+4 format (12345-6789) is optional and often omitted by users. Your validation should accept both the 5-digit and the hyphenated 9-digit form rather than requiring one or the other.
Don't conflate format with existence. A code can match the regex perfectly and still not exist. Regex confirms shape, not validity. For generating realistic test data that passes deeper checks, see how to generate realistic test addresses for forms.
Countries That Don't Use Postal Codes
Not every country has a postal code system. Some rely on city and street addressing alone; others have codes only for major cities or P.O. boxes.
Countries with no national postal code system (as of this writing) include:
- Ireland (introduced Eircode in 2015, but it's not universally required)
- Panama
- Hong Kong (addresses use district names instead)
- United Arab Emirates (no universal system; free zones have their own)
- Yemen
- Parts of sub-Saharan Africa, including Angola, Cameroon, and Niger
When you're building address forms for a global audience, the postal code field should never be marked as globally required. A sensible approach: require it only when the selected country has a well-established system, and leave it optional otherwise.
Validation Edge Cases Worth Knowing
Standard patterns handle the common case. The edge cases are where things break quietly.
UK Crown dependencies. Jersey, Guernsey, and the Isle of Man use UK-style postcodes but are not administratively part of the UK postcode system. Wikipedia notes that these territories "adopted the UK-format postcodes in 1993-94," with Guernsey using the GY prefix, the Isle of Man using IM, and Jersey using JE, each administered consistently with Royal Mail practice but issued under separate arrangements. A form that accepts UK addresses but blocks JE2 3AB will confuse a lot of users.
Canadian codes exclude certain letters. The letters D, F, I, O, Q, and U never appear in Canadian postal codes, and the first character of the code is further restricted to 18 possible letters (W and Z are also excluded from the first position). A regex that allows all letters will accept D0D 0D0 even though it can't be a real code. The strict pattern is ^[ABCEGHJ-NPRSTVXY]\d[ABCEGHJ-NPRSTV]\s?\d[ABCEGHJ-NPRSTV]\d$.
Numeric-only codes with leading zeros. French department 01 (Ain) produces codes like 01000. Database columns typed as integers silently drop that leading zero. Store postal codes as strings, always.
Alphanumeric confusion in OCR and manual entry. The letter O and digit 0 are common mix-ups, as are I/1 and S/5. For test data intended to exercise OCR pipelines, generating codes that include these ambiguous characters deliberately is worth doing. More on testing edge cases like these at address edge cases that break forms.
Building a Country-Aware Validator
A single global regex is the wrong tool. The practical approach is a lookup object keyed by ISO 3166-1 alpha-2 country code, where each entry holds the pattern and any normalization steps needed.
const postalPatterns = {
US: { pattern: /^\d\d\d\d\d(-\d\d\d\d)?$/, normalize: (v) => v.trim() },
GB: { pattern: /^[A-Z][A-Z]?\d[A-Z\d]?\s?\d[A-Z][A-Z]$/, normalize: (v) => v.trim().toUpperCase() },
CA: { pattern: /^[ABCEGHJ-NPRSTVXY]\d[ABCEGHJ-NPRSTV]\s?\d[ABCEGHJ-NPRSTV]\d$/, normalize: (v) => v.trim().toUpperCase() },
DE: { pattern: /^\d\d\d\d\d$/, normalize: (v) => v.trim() },
JP: { pattern: /^\d\d\d-\d\d\d\d$/, normalize: (v) => v.trim() },
// add more as needed
};
function validatePostalCode(country, value) {
const entry = postalPatterns[country];
if (!entry) return true; // unknown country, skip validation
const normalized = entry.normalize(value);
return entry.pattern.test(normalized);
}
Countries absent from the lookup pass through without an error, which handles the no-postal-code case gracefully. For more background on what a technically valid address looks like beyond the postal code, see what makes an address valid.
Frequently Asked Questions
Do postal codes and ZIP codes mean the same thing?
ZIP code is the US-specific term, originally standing for Zone Improvement Plan. "Postal code" is the generic international term. Most countries use postal code or postcode, though the underlying systems work differently everywhere.
Can two countries share the same postal code format?
Yes, and it causes real problems. Germany and France both use 5-digit numeric codes, so 75008 is a valid French code and could theoretically collide with a German one if you're not filtering by country first. Always validate in the context of the country field, not the postal code field alone.
Why do some UK postcodes have letters at the end?
The inward code (second half of a UK postcode) always ends in two letters representing the postcode unit, which narrows the location to a specific street segment or a handful of buildings. The Royal Mail assigns them; they're not derived from place names or alphabetical logic.
Is it safe to use synthetic postal codes in automated tests?
Synthetic codes in the right format are appropriate for most testing purposes: form validation, UI rendering, and integration tests that don't hit live geocoding APIs. If your test pipeline calls a shipping rate calculator or address verification service, use known sandbox codes from the provider's documentation instead, since real-looking fake codes may resolve unexpectedly.
Which countries changed their postal code system most recently?
Ireland is the most recent major example, introducing Eircode in 2015. Unlike most postal codes, which identify a shared area, each Eircode identifies a single building, which makes it closer to a delivery point code than a traditional postal code. Countries planning new systems today tend to follow that more granular model rather than the area-based approach older systems like the US ZIP code use.