15 minlesson

Postal Code Systems Around the World

Postal Code Systems Around the World

Postal codes are unique identifiers that help route mail and packages. Each country has its own system with different formats, lengths, and rules.

What Postal Codes Tell Us

A postal code is more than just a delivery identifier:

InformationUse Case
Geographic regionShipping zone calculation
City/StateAddress verification
Latitude/LongitudeDistance calculations
Urban vs RuralDelivery time estimates

US ZIP Codes

The US uses 5-digit ZIP codes, optionally extended to ZIP+4:

110001 - Basic ZIP (New York, NY)
210001-1234 - ZIP+4 (specific building/floor)

Structure:

  • First digit: Region (0-9)
  • First 3 digits: Sectional center facility
  • Last 2 digits: Post office or delivery area
  • +4 extension: Specific delivery point

Pattern: /^\d{5}(-\d{4})?$/

javascript
1const US_ZIP = /^\d{5}(-\d{4})?$/;
2
3US_ZIP.test('10001'); // true
4US_ZIP.test('10001-1234'); // true
5US_ZIP.test('1234'); // false (too short)
6US_ZIP.test('ABCDE'); // false (letters)

Regional distribution:

First DigitRegion
0Northeast (CT, MA, ME, NH, NJ, NY, PR, RI, VT, VI)
1Northeast (DE, NY, PA)
2-3Southeast (DC, MD, NC, SC, VA, WV)
4Midwest (IN, KY, MI, OH)
5Midwest (IA, MN, MT, ND, SD, WI)
6Midwest (IL, KS, MO, NE)
7South (AR, LA, OK, TX)
8West (AZ, CO, ID, NM, NV, UT, WY)
9West (AK, AS, CA, GU, HI, MH, OR, WA)

Canadian Postal Codes

Canada uses alternating letter-digit format:

1M5V 3A8 - Toronto, ON
2V6B 2W2 - Vancouver, BC

Structure:

  • First letter: Province/territory (18 letters used)
  • First 3 characters (FSA): Forward Sortation Area
  • Last 3 characters (LDU): Local Delivery Unit

Pattern: /^[A-Z]\d[A-Z]\s?\d[A-Z]\d$/i

Letters NOT used: D, F, I, O, Q, U (avoid confusion with numbers) W and Z: Only in certain positions

javascript
1const CA_POSTAL = /^[ABCEGHJ-NPRSTVXY]\d[ABCEGHJ-NPRSTV-Z]\s?\d[ABCEGHJ-NPRSTV-Z]\d$/i;

First letter by province:

LetterProvince
ANewfoundland
BNova Scotia
CPrince Edward Island
ENew Brunswick
G-HQuebec
J-KQuebec (Montreal area)
L-NOntario
POntario (Northern)
RManitoba
SSaskatchewan
TAlberta
VBritish Columbia
XNWT/Nunavut
YYukon

UK Postcodes

UK postcodes are complex with variable length:

1SW1A 2AA - Westminster, London
2M1 1AA - Manchester
3B1 1AA - Birmingham

Structure:

  • Outward code (before space): Area + district
  • Inward code (after space): Sector + unit

Valid formats:

FormatExample
AN NAAM1 1AA
ANN NAAM60 1NW
AAN NAACR2 6XH
AANN NAADN55 1PT
ANA NAAW1A 1HQ
AANA NAAEC1A 1BB

Pattern: /^[A-Z]{1,2}\d[A-Z\d]?\s?\d[A-Z]{2}$/i

javascript
1const UK_POSTCODE = /^([A-Z]{1,2}\d[A-Z\d]?)\s?(\d[A-Z]{2})$/i;
2
3function normalizeUKPostcode(code) {
4 // Remove spaces, then add space before last 3 chars
5 return code.replace(/\s/g, '').replace(/(.{3})$/, ' $1').toUpperCase();
6}
7
8normalizeUKPostcode('sw1a2aa'); // "SW1A 2AA"
9normalizeUKPostcode('M1 1AA'); // "M1 1AA"

German PLZ (Postleitzahl)

Germany uses simple 5-digit codes:

110117 - Berlin Mitte
280331 - München

Structure:

  • First 2 digits: Region
  • All 5 digits: Specific delivery area

Pattern: /^\d{5}$/

Regional distribution:

RangeRegion
01-04Saxony, Brandenburg
10-14Berlin
20-27Hamburg, Bremen
30-31Hannover
40-47Düsseldorf
50-53Köln
60-65Frankfurt
70-76Stuttgart
80-87München
90-96Nürnberg

French Code Postal

France uses 5-digit codes similar to Germany:

175001 - Paris 1st arrondissement
269001 - Lyon

Structure:

  • First 2 digits: Département (01-95, plus overseas)
  • Last 3 digits: Distribution office

Pattern: /^\d{5}$/

Paris arrondissements: 75001-75020

Japanese Postal Codes

Japan uses 7-digit codes with optional hyphen:

1150-0041 - Shibuya, Tokyo
2〒150-0041 - With postal mark

Structure:

  • First 3 digits: Region/prefecture
  • Last 4 digits: Local area

Pattern: /^\d{3}-?\d{4}$/

Validation Levels

There are two levels of postal code validation:

1. Format Validation (Regex)

Check if the code matches the expected pattern:

javascript
1function validateFormat(code, country) {
2 const patterns = {
3 US: /^\d{5}(-\d{4})?$/,
4 CA: /^[A-Z]\d[A-Z]\s?\d[A-Z]\d$/i,
5 GB: /^[A-Z]{1,2}\d[A-Z\d]?\s?\d[A-Z]{2}$/i,
6 DE: /^\d{5}$/,
7 FR: /^\d{5}$/
8 };
9
10 return patterns[country]?.test(code) || false;
11}

2. Existence Validation (Database/API)

Check if the code actually exists:

javascript
1async function validateExists(code, country) {
2 // Use GeoNames API to verify
3 const response = await fetch(
4 `http://api.geonames.org/postalCodeSearchJSON?postalcode=${code}&country=${country}&username=demo`
5 );
6 const data = await response.json();
7 return data.postalCodes?.length > 0;
8}

Why both?

  • 99999 passes US format validation but doesn't exist
  • Format validation is fast (no network)
  • Existence validation confirms deliverability

GeoNames: Free Postal Code Database

GeoNames provides free access to postal code data:

  • Coverage: 150+ countries
  • Data: City, state, coordinates for each code
  • API: Free tier with 2000 requests/hour
  • Download: Bulk data files available

We'll use GeoNames in the workshop to validate postal codes exist.

What's Next

In the workshop, you'll build a postal code validator that:

  1. Validates format by country
  2. Queries GeoNames to verify existence
  3. Returns city/region information
  4. Handles rate limiting gracefully