US ZIP Code Regex
Validates United States ZIP codes in both the standard 5-digit form and the extended ZIP+4 form (e.g. 12345-6789).
Regex Pattern
^\d{5}(?:-\d{4})?$Pattern Breakdown
Hover over a token to see what it does.
| Token | Meaning |
|---|---|
| ^ | Anchors the match to the start of the string |
| \d | Matches any single digit 0-9 |
| {5} | Requires exactly 5 digits for the base ZIP code |
| (?: | Start of a non-capturing group for the optional ZIP+4 extension |
| -\d{4} | A literal hyphen followed by exactly 4 digits (the +4 extension) |
| )? | Closes the group and makes the entire extension optional |
| $ | Anchors the match to the end of the string |
Detailed Explanation
What it does
This pattern matches strings that are valid US ZIP codes, either the plain 5-digit form (90210) or the extended ZIP+4 form (12345-6789). Anything with the wrong digit counts, missing hyphen, or extra characters is rejected.
Why it works
\d{5} requires exactly five digits up front, which is mandatory for every US ZIP code. The optional non-capturing group (?:-\d{4})? then allows, but does not require, a hyphen followed by exactly four more digits for the ZIP+4 extension. Because the group is wrapped with ? rather than being two separate alternatives, the pattern stays compact while still cleanly supporting both formats.
Common use cases
- Validating shipping or billing address forms for US-based e-commerce checkouts
- Cleaning and standardizing ZIP codes during CSV/spreadsheet address imports
- Client-side input masking that accepts both 5-digit and ZIP+4 formats
- Filtering or extracting ZIP codes from free-text address strings
Edge cases
- ZIP codes with leading zeros, like 00501 (a real ZIP code for the IRS in Holtsville, NY), are matched correctly since \d doesn't strip leading zeros
- A trailing hyphen with no digits after it, like 12345-, is correctly rejected because -\d{4} requires exactly four digits
- A ZIP+4 with only 3 extension digits, like 12345-678, is rejected because {4} requires exactly four
- Codes with extra leading or trailing whitespace will fail unless trimmed first, since ^ and $ anchor to the exact string boundaries
Limitations
- Does not verify that the ZIP code actually exists or corresponds to a real US location
- Only validates US ZIP codes — other countries' postal code formats need separate patterns
- Does not normalize formatting differences like missing hyphens in ZIP+4 (e.g. 123456789 without a dash)
Interactive Tester
Edit the pattern or text below — matching runs live in your browser.
Test Cases
Editable — add your own inputs to see if they pass.
| Input | Expected | Result | |
|---|---|---|---|
| Pass | |||
| Pass | |||
| Pass | |||
| Pass | |||
| Pass | |||
| Pass | |||
| Pass | |||
| Pass |
Language Variants
Production-ready examples in 12 languages.
const zipRegex = /^\d{5}(?:-\d{4})?$/;
console.log(zipRegex.test('90210')); // trueCommon Mistakes
Requiring the ZIP+4 hyphenated segment as mandatory, rejecting valid plain 5-digit ZIP codes
Fix: Wrap the -\d{4} extension in an optional non-capturing group (?:-\d{4})? so both formats are accepted
Using [0-9]{5} exactly but forgetting to anchor with ^ and $, letting a 5-digit substring inside a longer invalid string pass
Fix: Always anchor the pattern so the entire input string is required to be a valid ZIP code
Assuming this pattern validates postal codes for any country
Fix: Use a country-specific postal code pattern (or a locale-aware library) since formats vary widely outside the US
Performance Notes
- Fixed-count quantifiers like {5} and {4} are the cheapest form of repetition and carry no backtracking risk
- The optional non-capturing group adds negligible overhead since it either matches once or is skipped entirely
- Anchoring with ^ and $ allows the engine to reject malformed input in a single linear pass
Browser Compatibility
| Engine | Supported | Notes |
|---|---|---|
| Chrome | Yes | — |
| Firefox | Yes | — |
| Safari | Yes | — |
| Edge | Yes | — |
| Node.js | Yes | — |