US ZIP Code Regex (5-Digit and ZIP+4)
Accept a five-digit US ZIP code, with or without the four-digit ZIP+4 add-on after a hyphen.
One case per line; the m flag makes ^ and the end anchor work line by line.
Link optionspattern only
The address bar holds the pattern, flags and replacement, so Copy link shares them. Your test text stays out of it unless you include it (up to 2,000 characters), because it may be private. Nothing is sent to a server.
Matches
6matches
The first is “90210”, at position 0.
- Groups
- none
- Characters matched
- 40 of 103
What the pattern meansHover or tap a part to see it in the pattern and what it matched
How this works: Method, 4 sources, Checked against 1 worked example,
How this works
Method
Your pattern runs in your own browser’s JavaScript engine, in a background worker that is stopped after 1.5 seconds, so a pattern that backtracks catastrophically can’t freeze the page. The explanation comes from our own parser of the ECMAScript pattern grammar, checked against the engine; what each part matched is found by wrapping that part in one more group and running the pattern again. Conversions to other flavours only rewrite the syntax and list what their documentation says works differently.
Sources
How it’s tested
One worked example for this page is checked by automated tests before every release: given the inputs, the tool must show the expected answer.
Changes
- First published, with a library of 19 common patterns and their test cases.
Worked example
Take 90210, the first case in the tester. Reading the pattern left to right, each part takes its share of the text:
^The start of the text (matches a position, no characters)\d{5}Exactly five digits (0–9) matches 90210(?:-\d{4})?A group (not captured), optional (zero or one time): (matches a position, no characters)$The end of the text (matches a position, no characters)
How the ZIP code regex works
\\d{5}\ asks for exactly five digits, the ZIP code the US Postal Service introduced in 1963. The group \(?:-\d{4})?\ adds the ZIP+4 extension: a hyphen and four more digits, and the question mark after the group makes the whole extension optional. Because the hyphen sits inside the group, "90210-" fails: either the full add-on is there or none of it is.
The anchors matter more here than in most patterns. Without the caret and the dollar sign, "1234567" would contain a five-digit run and pass a search. With them, the string must be exactly a ZIP code and nothing else.
The most common ZIP bug isn't in the regex at all: storing the code as a number. ZIP codes in New England and parts of New Jersey and New York start with 0, and a numeric column or \parseInt\ turns 02134 into 2134. Keep ZIP codes as text, and if you receive four-digit values from an old spreadsheet, pad them back with \padStart(5, '0')\ before testing.
- ZIP Codes (Zone Improvement Plan) were introduced on 1 July 1963 as five digits, the first naming a region of the country. Source: ZIP Code (Wikipedia).
- ZIP+4, added in 1983, is the five-digit code followed by a hyphen and four digits that narrow the location further. Source: ZIP Code (Wikipedia).
- The lowest ZIP Code is 00501 in Holtsville, New York, used only by an IRS centre, which is why leading zeros must be kept. Source: ZIP Code (Wikipedia).
Test cases
Every case runs as an automated test of this page’s pattern, so the table can’t drift from what the pattern really does.
| Text | Result | Why |
|---|---|---|
| 90210 | Passes | five digits |
| 00501 | Passes | the lowest ZIP code, Holtsville, New York: the zeros matter |
| 02134 | Passes | a Boston ZIP code starting with 0 |
| 10001-1234 | Passes | ZIP+4 with its hyphen |
| 20500-0003 | Passes | ZIP+4 whose add-on starts with zeros |
| 99950 | Passes | one of the highest, in Alaska |
| 9021 | Fails | four digits, perhaps a lost leading zero |
| 902101 | Fails | six digits |
| 90210-12 | Fails | the add-on needs four digits |
| 90210 1234 | Fails | a space instead of the hyphen |
| 90210- | Fails | a hyphen with nothing after it |
| 902101234 | Fails | nine digits with no hyphen |
| SW1A 1AA | Fails | a UK postcode, a different format |
What it doesn’t check
- A matching code may not exist; only the USPS address data can say whether 12345 is in use.
- It doesn’t accept a space or no separator before the +4 part; normalise those inputs first if your form allows them.
- It is US-only: Canadian, UK and other postcodes use letters and different layouts, so use a country-specific pattern for each.
- Military APO and FPO addresses use ordinary-looking five-digit codes, so the pattern can’t tell them apart and doesn’t need to.
The same pattern in other languages
Converted automatically from the JavaScript version; the tester above always runs JavaScript.
| Flavour | Pattern | Notes |
|---|---|---|
| Python | (?a)^\d{5}(?:-\d{4})?\Z | |
| PCRE | ^\d{5}(?:-\d{4})?\z | |
| Go | ^\d{5}(?:-\d{4})?$ | |
| Java | ^\d{5}(?:-\d{4})?\z | |
| .NET | ^\d{5}(?:-\d{4})?\z | In .NET, \d and \w match any Unicode digit or letter. Pass RegexOptions.ECMAScript, or write [0-9] and [A-Za-z0-9_], for JavaScript’s ASCII-only meaning. |
Sources
Frequently Asked Questions
What regex matches a US ZIP code?
Five digits, optionally followed by a hyphen and four more digits, anchored at both ends. That covers both the basic ZIP code and ZIP+4.
Why did my ZIP code lose its first digit?
It was stored or parsed as a number, which drops leading zeros. Treat ZIP codes as text everywhere, from the form field to the database column.
Does a matching ZIP code mean the address is real?
No. The pattern checks only the shape. Use an address verification service built on USPS data if you need to know a code is in use or matches the city.