Validate a UK postcode
Validate the common shape of a UK postcode — outward code, optional space, inward code — case-insensitively.
Last updated
Matches
- SW1A 1AA
- M1 1AE
- EC1A 1BB
Doesn’t match
- 12345
- SW1A 1AA
- not a postcode
Why it’s written this way
UK postcodes split into an outward code and an inward code. [A-Z]{1,2}\d[A-Z\d]? covers the outward part — one or two letters, a digit, then an optional letter or digit — which spans formats from 'M1' to 'SW1A'. The inward part, \d[A-Z]{2}, is always a digit followed by exactly two letters.
\s? makes the space between the two halves optional, since forms and copy-pasted addresses are inconsistent about including it, and the 'i' flag means the pattern doesn't care whether letters arrive as 'sw1a' or 'SW1A'.
Edge cases to know
- →A handful of real postcodes (parts of London's 'W1' series, plus some Girobank and overseas-territory codes) don't fit this general shape — the full Royal Mail specification needs a longer, more irregular pattern.
- →It accepts some letter-and-digit combinations that aren't currently allocated to any real postcode district — matching the shape isn't the same as the postcode existing.
- →Two consecutive spaces, or none where one belongs, both need normalizing first — \s? only tolerates zero or one space, not several.
Part by part
- ^[A-Z]{1,2}
- The area: one or two letters identifying a postal town, such as M for Manchester or SW for south-west London.
- \d[A-Z\d]?
- The district, which is a digit optionally followed by another digit or a letter. That optional character is what makes both W1 and W1A possible.
- \s?
- An optional space before the second half. Real postcodes are written with it and pasted data often is not, so accepting both is practical.
- \d[A-Z]{2}$
- The inward code: always a digit followed by two letters, with no exceptions. This half is the strictly regular part of the format.
Common mistakes
^[A-Z]{1,2}\d{1,2}\s?\d[A-Z]{2}$Requiring digits in the district rejects the London codes with a trailing letter, such as W1A and EC1V — which covers a large number of central London addresses.
^[A-Z]{1,2}\d[A-Z\d]?\s?\d[A-Z]{2}$^[A-Z]{1,2}\d[A-Z\d]?\s\d[A-Z]{2}$Requiring the space rejects the unspaced form that arrives from most databases and CSV exports, so valid data fails on import rather than at entry.
^[A-Z0-9\s]{5,8}$Matching by length and alphabet abandons the structure entirely, so any five-to-eight-character alphanumeric string passes — which on an address form is barely a check at all.
Questions
Why is the second half so much stricter than the first?
Because it is genuinely uniform: the inward code is always a digit followed by two letters, everywhere in the country. The outward code varies because it grew historically, town by town, rather than being designed as a system.
Does this cover every valid postcode?
Not quite. A handful of special cases exist, including the non-geographic GIR 0AA and codes for British Overseas Territories, which do not follow the standard shape. Add them explicitly if your data might contain them.
Should I store the space?
Store it normalised — one space before the final three characters — because that is the form Royal Mail publishes and the form users recognise. Accept anything on input and normalise before saving.
Does a match mean the postcode exists?
No. Only a lookup against the Post Office address file can confirm that, and it also gives you the address, which is usually why you wanted the postcode in the first place.