This is more a note to myself than anything, but I hope this can be a use of other developers looking to regex validate UK Postcodes. This validates all postcodes including London ones fine. Here’s the code:
^([A-PR-UWYZ0-9][A-HK-Y0-9][AEHMNPRTVXY0-9]?[ABEHMNPRVWXY0-9]? {1,2}[0-9][ABD-HJLN-UW-Z]{2}|GIR 0AA)$
Here’s an example as a CodeIgniter form validation callback, which you could use by calling callback_is_valid_uk_postcode in your form validation code. The logic is obviously transferable, though.
/**
* CALLBACK - determine if the provided postcode is valid.
*
* @param string $postcode
* @return bool TRUE if valid, FALSE otherwise
* @author George Edwards
*/
function is_valid_uk_postcode($postcode) {
$pattern = "/^([A-PR-UWYZ0-9][A-HK-Y0-9][AEHMNPRTVXY0-9]?[ABEHMNPRVWXY0-9]? {1,2}[0-9][ABD-HJLN-UW-Z]{2}|GIR 0AA)$/"
if (preg_match($pattern, $postcode)) {
return TRUE;
}
$this->validation->set_message('is_valid_uk_postcode', 'That is not a valid %s.');
return FALSE;
}
Credit to writing this material goes to regexlib.com.

Is there an example page somewhere?
Hi Tom
Unfortunately not as the site I am developing is Intranet based. Based on the function above, you could simplify it to the following. If you had an incoming $_POST request from a form submission, you could do the following:
<?php if (isset($_POST) && isset($_POST['postcode']) ) { if ( preg_match($pattern, $_POST['postcode'] ) { die 'valid postcode!'; } else { die 'invalid postcode!'; } } else { die 'form not submitted?'; ?>If you needed a more thorough example let me know
Hi,
Have you tested this $pattern against a large database of valid/invalid postcodes to confirm it works…?
Thanks.
Yes. I use it on a large project and have not had any problems.
There is a syntax error on line 9, it does not end with a ;
This grep validates codes which are not valid UK postcodes: for example ’111 0AA’, ’1234 0AA’. And it excludes valid ones (eg ‘N1C 4UZ’). It also excludes technically invalid but perfectly reasonable postcode representations (eg ‘sw1a 0aa’ and ‘SW1A0AA’).
Wikipedia offers this, which is better but doesn’t have sensible capture groups:
(GIR 0AA)|(((A[BL]|B[ABDHLNRSTX]?|C[ABFHMORTVW]|D[ADEGHLNTY]|E[HNX]?|F[KY]|G[LUY]?|H[ADGPRSUX]|I[GMPV]|JE|K[ATWY]|L[ADELNSU]?|M[EKL]?|N[EGNPRW]?|O[LX]|P[AEHLOR]|R[GHM]|S[AEGKLMNOPRSTY]?|T[ADFNQRSW]|UB|W[ADFNRSV]|YO|ZE)[1-9]?[0-9]|((E|N|NW|SE|SW|W)1|EC[1-4]|WC[12])[A-HJKMNPR-Y]|(SW|W)([2-9]|[1-9][0-9])|EC[1-9][0-9]) [0-9][ABD-HJLNP-UW-Z]{2})
I know this is an old post but it was very useful.
However shoudlnt it be
^([A-PR-UWYZ0-9][A-HK-Y0-9][AEHMNPRTVXY0-9]?[ABEHMNPRVWXY0-9]? {0,1}[0-9][ABD-HJLN-UW-Z]{2}|GIR 0AA)$
to allow either no space or a single space?
Hi All,
I use the following regex provided by royal mail [with a few tweeks], pass it a postcode that has had all spacing removed and is capitalised then it will validate correctly
/^((((A[BL]|B[ABDHLNRSTX]?|C[ABFHMORTVW]|D[ADEGHLNTY]|E[HNX]?|F[KY]|G[LUY]?|H[ADGPRSUX]|I[GMPV]|JE|K[ATWY]|L[ADELNSU]?|M[EKL]?|N[EGNPRW]?|O[LX]|P[AEHLOR]|R[GHM]|S[AEGKLMNOPRSTY]?|T[ADFNQRSW]|UB|W[ADFNRSV]|YO|ZE)[1-9]?[0-9]|((E|N|NW|SE|SW|W)1|EC[1-4]|WC[12])[A-HJKMNPR-Y]|(SW|W)([2-9]|[1-9][0-9])|EC[1-9][0-9])[0-9][ABD-HJLNP-UW-Z]{2})$/