Regex for ZIP Codes

ZIP codes are postal codes used in the United States, and are used with an address to describe the region that the address is located in. How do we write a regular expression that will match or validate a ZIP code?

A regular expression for ZIP codes needs to match 5 digits at the start, followed by 4 optional digits that further refine the region. The last 4 digits can be separated from the first 5 by a dash or space, or they can be written without any separator.

/^\d{5}(?:[- ]?\d{4})?$/Edit with Regexity

So let’s discuss how this expression is put together.

General Format of a Zip Code

A ZIP code is generally formatted in the following way:

  • Starts with 5 numbers (12345)
  • Optionally followed by 4 more numbers for further refinement, which is separated from the first 5 by either:
    • a dash (12345-6789),
    • a space (12345 6789), or
    • nothing (123456789)

Regular Expression for ZIP Codes

The first 5 digits are easy to write an expression for:

/\d{5}/Edit with Regexity

The \d matches any digit (0-9), and the {5} behind hit says that we’d like to match exactly 5 digits – no more and no less.

The optional set of 4 additional numbers are written in a similar manner behind that of the first:

/\d{5}\d{4}/Edit with Regexity

The expression above will match a 9-digit ZIP code (i.e. 123456789). In fact, we could just as well have written it as /\d{9}/, but you’ll see why the code above makes sense in a minute.

The 4 digits at the can be written directly following the 5 initial digits, but they can also be separated out using a dash (-) or a space. We can specify this by adding a dash and a space between the two digit expression, enclosed in square brackets:

/\d{5}[- ]\d{4}/Edit with Regexity

The square brackets indicate that we can match either of the two characters within it. Note that the space can also be indicated by a space character (\s), which is sometimes more visible to the eye of the programmer.

To indicate the the dash and space is optional, we can add a zero-or-more quantifier (?) behind it:

/\d{5}[- ]?\d{4}/Edit with Regexity

This should now match all variations of the 9-digit ZIP code, including:

  • 12345-6789 (dash separator)
  • 12345 6789 (space separator)
  • 123456789 (no separator)

However, note that the expression will no longer match a simple 5-digit only code.

To fix this, we need to indicate that the part of the expression after the initial 5 digits is optional. We do this by first enclosing the latter part in parentheses to indicate a group:

/\d{5}(?:[- ]?\d{4})/Edit with Regexity

The ?: at the start of the parenthesis indicate that this is a non-capture group, meaning that we have no intention of extracting the information in this group for later use.

To indicate that the group is optional, we can place a zero-or-more quantifier (?) behind the group, like so:

/\d{5}(?:[- ]?\d{4})?/Edit with Regexity

This quantifier will ensure that our expression will match all variations the 9-digit ZIP code, but also the simple 5-digit code.

Finally, to ensure that we match only the ZIP code and nothing before or after it, place a start-of-string character (^) at the beginning and an end-of-string character ($) at the end of the expression:

/^\d{5}(?:[- ]?\d{4})?$/Edit with Regexity

Which Flag Should I Use?

ZIP codes are numeric in nature, and may contain a dash of a space. Therefore, the case insensitive flag (i) would not be of any use here.

If you’d like to extract all ZIP codes from a body of text, instead of validating user input as a ZIP code, you should add the global flag (g) at the end. In this case, however, you should also remove the start-of-string and end-of-string characters:

/\d{5}(?:[- ]?\d{4})?/gEdit with Regexity

Sources

The regular expressions on this page were adapted from solutions posted on Stack Overflow by kennytm and Emma on this question. In addition, this article proved useful in understanding the general format of a ZIP code.

Benjamin

Founder, owner, and sole content creator on RegexLand. Enjoys programming, blogging, and teaching others how to do the same. Read more...

6 thoughts on “Regex for ZIP Codes”

  1. Having difficulty creating a regex for a 5 digit US zip code. This will be utilized in a Google Form. I want to limit the the entry to 5 digits only and the numbers must be between 00501 – 99950. That range presumably includes current active zip codes. So if someone types in 00500 I would like the entry rejected. What does that code look like? Many thanks.

    Reply
    • Hi Scotty. This is quite a tedious thing as it requires hardcoding the numbers that are allowed to appear within your range.

      It becomes much more easier to just use regex to validate that there are indeed 5 digits, and then to use additional logic in your native programming language to parse an integer from that and then check if that integer falls between 00501 and 99950, inclusive.

      Reply
  2. Hi is there a REGEX you can point to that would take an address without the zipcode. Extract everything besides the zip.

    TIA

    -Meir

    Reply
    • Hi Meir, addresses are mostly text based and can vary widely from place to place. Some street names could have only letters, other might have space, hyphens, or even initials of the person the street was named after. You would also need to look for things like Dr, Drive, Ave, Avenue, Rd, Road, Crescent… The list is endless and open ended. The same options for street names also goes for suburb names, town names, and country names. Add to that the fact that you’ll need to account for units inside a flat, for street numbers that might also include letters, etc., and it quickly becomes nearly impossible.

      I can’t think of an elegant way to ensure that the entered text is an address.

      If, on the other hand, you are sure that the text is a valid address and would just like to exclude the zip code, the easiest would be to use regex to look for the zip code in the text and then simply replace it with an empty string (i.e. “”) to completely remove it from the address.

      Reply

Leave a Reply to Benjamin Cancel reply