Blog

28Nov
2003
RegEx Patterns to Match Zip Codes and Postal Codes

Need to match zip codes or postal codes? Of course, no two countries use the same format. But here are solutions for USA, Canada, and the United Kingdom.

The USA format is simple, five digits as 99999 or zip+4 as 99999-9999. A simple RegEx could be:

view plain print about
1\d{5}(-\d{4})?
If you want to omit zips with a trailing hyphen (as in 99999-) then you could use a lookahead condition:
view plain print about
1\d{5}(?(?=-)-\d{4})

Canada is a little trickier, the format looks like A1A 1A1 which can be easily matched with:

view plain print about
1[A-Z]\d[A-Z] \d[A-Z]\d

However, there is one rule that may be employed to improve validation, the opening character of the set of characters (technically called the "forward sortation area" or FSA) identifies the province, territory, or region (there are 18 characters that are valid in this position, A for Newfoundland and Labrador, B for Nova Scotia, K, L, N and P for Ontario excluding Toronto which uses M, and so on.), and so validation should ideally check to ensure that the first character is a valid one. And so, here is a better Canadian postal code regular expression:

view plain print about
1[ABCEGHJKLMNPRSTVXY]\d[A-Z] \d[A-Z]\d

Good old UK is the trickiest of the three. United Kingdom postcodes, as defined by the Royal Mail, are five, six, or seven characters and digits (that includes a single space). Postcodes are made up of two parts, the "outward postcode" (or outcode), and the "inward postcode" (or incode). The outcode is one or two alphabetical characters followed by one or two digits, or one or two characters followed by digit and a character. The incode is always a single digit followed by 2 characters (any characters excluding C, I, K, M, O, and V). The incode and outcode are separated by a space. Here's the regular expression:

view plain print about
1[A-Z]{1,2}\d[A-Z\d]? \d[ABD-HJLNP-UW-Z]{2}

If you have any other countries or formats to share, please do so.

Comments (20)



  • PaulH

    for all things postal i generally look here first:
    http://www.upu.int/post_code/en/addressing_formats...

    for specific in-country info (i'll bet some countries postal codes vary internally):
    http://www.upu.int/post_code/en/list_of_sites_by_c...

    #1Posted by PaulH | Nov 28, 2003, 01:35 PM
  • Iain

    The easiest place to get regex for assorted
    zips in various countries is to consult the perl module <a href="http://search.cpan.org/perldoc/Regexp::Common::zip...;.

    #2Posted by Iain | Nov 28, 2003, 09:51 PM
  • Mike

    Regular Expressions Rock! I've been using them for form validation for years. Here's a killer re that validates dates:

    ^(?:(?:(?:0[13578]|1[02])([\/|\-|\.]?)31)\1|(?:(?:0[1,3-9]|1[0-2])([\/|\-|\.]?)(?:29|30)\2))(?:(?:1[6-9]|[2-9]\d)\d{2})$|^(?:02([\/|\-|\.]?)29\3(?:(?:(?:1[6-9]|[2-9]\d)(?:0[48]|[2468][048]|[13579][26])|(?:(?:16|[2468][048]|[3579][26])00))))$|^(?:(?:0[1-9])|(?:1[0-2]))([\/|\-|\.]?)(?:0[1-9]|1\d|2[0-8])\4(?:(?:1[6-9]|[2-9]\d)\d{2})$

    It's probably the most complicated one I have, but it works really well and can be tweaked for different formats.

    #3Posted by Mike | Dec 1, 2003, 09:19 AM
  • Mike

    Here are some other good ones:

    Phone numbers:
    (^[0-9]{10}$)|(^\([0-9]{3}\) ?[0-9]{3}\-[0-9]{4}$)|(^[0-9]{3}([\.\-])([0-9]{3})\4[0-9]{4}$)

    SSNs:
    (^[0-9]{9}$)|(^[0-9]{3}\-[0-9]{2}\-[0-9]{4}$)

    A different approach to emails:
    ^[\w-\.]+@(\w+[\w-]+\.){0,3}\w+[\w-]+\.[a-zA-Z]{2,4}$

    How about even last names:
    ^[A-Za-z]*[\.\ '\-]?[A-Za-z]*$

    #4Posted by Mike | Dec 1, 2003, 09:22 AM
  • pete

    how about another UK RegExp that isnt so fussy of cahracter cassing..

    ^[A-Za-z]{1,2}[\d]{1,2}([A-Za-z])?\s?[\d][A-Za-z]{2}$

    #5Posted by pete | Dec 2, 2003, 09:39 AM
  • Martin Garbutt

    Just a quick comment regarding the UK postal code R.E:

    [A-Z]{1,2}\d[A-Z\d]? \d[ABD-HJLNP-UW-Z]{2}

    Wont this also match:

    AAAN NAA

    (A=character)
    {N=digit)

    which it shouldnt do!!!

    #6Posted by Martin Garbutt | Feb 16, 2004, 11:54 AM
  • Jerry

    Dutch postcodes are real easy: "NNNN AA" = four digits, a space, and two characters. The numbers range from 1000 to 9999, the characters from "AA" to "ZZ", omitting no characters.

    As opposed to many countries' postcodes, the Dutch postcodes are unique per block or at least street. So stating the postcode plus house number refers to a unique house.

    Jerry

    #7Posted by Jerry | Mar 10, 2004, 04:09 AM
  • Infinite Gravity Data Services

    Regarding Canadian postal codes, you can refine your regexp even more. You are correct in listing the 18 valid characters for the first letter of the postal code. For the other letters, there are 20 valid characters: [ABCEGHJKLMNPRSTVWXYZ].

    So the complete expression is:
    [ABCEGHJKLMNPRSTVXY]\d[ABCEGHJKLMNPRSTVWXYZ] \d[ABCEGHJKLMNPRSTVWXYZ]\d

    For more information about Canadian postal codes or geocoding data, check out our site at http://www.infinitegravity.ca

    #8Posted by Infinite Gravity Data Services | Oct 19, 2004, 01:41 PM
  • Alexei

    I have added $ to the end of the canadian postal code validation to prevent entry of extra characters:
    [ABCEGHJKLMNPRSTVXY]\d[ABCEGHJKLMNPRSTVWXYZ] \d[ABCEGHJKLMNPRSTVWXYZ]\d$

    #9Posted by Alexei | Nov 14, 2006, 11:13 AM
  • Douglas Greenshields

    A much tighter one for the UK would be (allowing for lower-case characters and one or zero spaces between parts - you should dilute to your own taste):

    ^ ?(([BEGLMNSWbeglmnsw][0-9][0-9]?)|(([A-PR-UWYZa-pr-uwyz][A-HK-Ya-hk-y][0-9][0-9]?)|(([ENWenw][0-9][A-HJKSTUWa-hjkstuw])|([ENWenw][A-HK-Ya-hk-y][0-9][ABEHMNPRVWXYabehmnprvwxy])))) ?[0-9][ABD-HJLNP-UW-Zabd-hjlnp-uw-z]{2}$

    @Martin

    That regular expression won't match "AAAN NAA". Though that comment was from over three years ago!

    #10Posted by Douglas Greenshields | May 25, 2007, 12:47 PM
  • akom

    hi ppl im not sure how the uk post code works... can anyone enlighten me pls..
    i like to match any address in uk with house number 621 and postcode le26un

    #11Posted by akom | Feb 8, 2009, 01:12 PM
  • Jonathan

    Thanks for pointing out the FSA rules.

    With some work, I found the following works when there is a space AND no space between the first and second half of the code.

    @regexpr(OWNER, "[ABCEGHJKLMNPRSTVXY][0-9][A-Z]( |)[0-9][A-Z][0-9]")

    #12Posted by Jonathan | Mar 10, 2009, 03:32 PM
  • Tony Proctor

    Ireland has a new postal code system called loc8 (not before time). It is funded by Garmin and not government-accepted yet. However, here's a prototype regex string for it:

    ^[a-zA-Z][0-9A-Za-z]{2}-[0-9]{2}-[0-9A-Za-z]{3}$

    #13Posted by Tony Proctor | Jul 14, 2010, 06:31 PM
  • Gary Delaney

    The regex string posted by Tony Proctor is incorrect and should not be used. The Loc8 Code has internal calculations inherent
    which dictate some of the characters. For this reason a simple syntax definition (incorrect in itself as shown) is insuffient. Loc8
    was designed to satisfy safety critical requirements an therefore basic syntax validation is wholly insuffient and foolhardy. Rights to to
    the inherent validation calculations are reserved. If anyone wishes to dicuss use of the correct format;- please contact me directly
    Many tks
    Gary

  • OB

    For Canadian it's a good idea to allow the space between sections to exist or not as users do not always use.

    ^([ABCEGHJKLMNPRSTVXY]\d[ABCEGHJKLMNPRSTVWXYZ])\ {0,1}(\d[ABCEGHJKLMNPRSTVWXYZ]\d)$

    #15Posted by OB | Sep 3, 2010, 01:08 PM
  • Chris

    This is a decent regex that my company (Net Driven) is using for US and Canadian zip/postal code validation. My name links to one of the pages we use it on.

    ^((\d{5})|(([ABCEGHJKLMNPRSTVXY]|[abceghjklmnprstvxy])\d([ABCEGHJKLMNPRSTVWXYZ]|[abceghjklmnprstvwxyz])(\s|)\d([ABCEGHJKLMNPRSTVWXYZ]|[abceghjklmnprstvwxyz])\d))$

    Just US: ^(\d{5})$

    Just Canada: ^(([ABCEGHJKLMNPRSTVXY]|[abceghjklmnprstvxy])\d([ABCEGHJKLMNPRSTVWXYZ]|[abceghjklmnprstvwxyz])(\s|)\d([ABCEGHJKLMNPRSTVWXYZ]|[abceghjklmnprstvwxyz])\d)$

    This checks for the correct characters as well as allowing lower/uppercase and with/out the space.

    #16Posted by Chris | Apr 22, 2011, 01:31 PM
  • Chris

    This is a decent regex that my company (Net Driven) is using for US and Canadian zip/postal code validation. My name links to one of the pages we use it on.

    ^((\d{5})|(([ABCEGHJKLMNPRSTVXY]|[abceghjklmnprstvxy])\d([ABCEGHJKLMNPRSTVWXYZ]|[abceghjklmnprstvwxyz])(\s|)\d([ABCEGHJKLMNPRSTVWXYZ]|[abceghjklmnprstvwxyz])\d))$

    Just US: ^(\d{5})$

    Just Canada: ^(([ABCEGHJKLMNPRSTVXY]|[abceghjklmnprstvxy])\d([ABCEGHJKLMNPRSTVWXYZ]|[abceghjklmnprstvwxyz])(\s|)\d([ABCEGHJKLMNPRSTVWXYZ]|[abceghjklmnprstvwxyz])\d)$

    This checks for the correct characters as well as allowing lower/uppercase and with/out the space.

    #17Posted by Chris | Apr 22, 2011, 01:34 PM
  • Liam Morland

    Some letters are not used in Canadian postal codes, so this is a better regex, which matches all valid codes and no invalid codes:
    ^[ABCEGHJKLMNPRSTVXY][0-9][ABCEGHJKLMNPRSTVWXYZ] [0-9][ABCEGHJKLMNPRSTVWXYZ][0-9]$

  • CF

    Russian postal codes: [1-6]\d{5} (6 digits, the first of them can not be 0 and (at the moment) is not greater than 6)

    #19Posted by CF | Nov 24, 2011, 02:47 PM
  • Gene Ramsay

    The regex for canada does not include DFIOQU.
    These letters are a problem with scanners

    #20Posted by Gene Ramsay | Mar 19, 2012, 07:05 AM