Validating UK postcodes with PHP


Postcodes in the UK do much more than mailsort. They are widely used to link individuals to various types of geographical, demographic and marketing data, and it's especially important that they are recorded and processed accurately. Thus, if your application processes UK postcodes, you'll need an effective way of validating them.

UK postcodes follow strict formatting rules. If you don't have access to the PAF, you can at least check that the postcodes in your application follow these rules. In this article, we offer a PHP function that does just that.

This function is currently available with PHP, Javascript, Visual Foxpro. If you want to share this function in other languages, please contact us.

checkPostcode function

Remember, postcode validation function below only checks that the code is in the correct format. A code might pass this test but still not be a genuine postcode. To determine whether a postcode actually exists, you would need to access the Postcode Address File. (But even that wouldn't be a perfect check, as the PAF is never completely up to date, postcodes are constantly being added, and existing premises are occasionally re-coded. Also, Royal Mail acknowledges that the PAF contains errors.)

function checkPostcode (&$toCheck) {
  // Permitted letters depend upon their position in the postcode.
  $alpha1 = "[abcdefghijklmnoprstuwyz]";                          // Character 1
  $alpha2 = "[abcdefghklmnopqrstuvwxy]";                          // Character 2
  $alpha3 = "[abcdefghjkpmnrstuvwxy]";                            // Character 3
  $alpha4 = "[abehmnprvwxy]";                                     // Character 4
  $alpha5 = "[abdefghjlnpqrstuwxyz]";                             // Character 5
  // Expression for postcodes: AN NAA, ANN NAA, AAN NAA, and AANN NAA with a space
  $pcexp[0] = '^('.$alpha1.'{1}'.$alpha2.'{0,1}[0-9]{1,2})([[:space:]]{0,})([0-9]{1}'.$alpha5.'{2})$';

  // Expression for postcodes: ANA NAA
  $pcexp[1] =  '^('.$alpha1.'{1}[0-9]{1}'.$alpha3.'{1})([[:space:]]{0,})([0-9]{1}'.$alpha5.'{2})$';

  // Expression for postcodes: AANA NAA
  $pcexp[2] =  '^('.$alpha1.'{1}'.$alpha2.'{1}[0-9]{1}'.$alpha4.')([[:space:]]{0,})([0-9]{1}'.$alpha5.'{2})$';
  // Exception for the special postcode GIR 0AA
  $pcexp[3] =  '^(gir)(0aa)$';
  // Standard BFPO numbers
  $pcexp[4] = '^(bfpo)([0-9]{1,4})$';
  // c/o BFPO numbers
  $pcexp[5] = '^(bfpo)(c\/o[0-9]{1,3})$';
  // Overseas Territories
  $pcexp[6] = '^([a-z]{4})(1zz)$/i';

  // Load up the string to check, converting into lowercase
  $postcode = strtolower($toCheck);

  // Assume we are not going to find a valid postcode
  $valid = false;
  // Check the string against the six types of postcodes
  foreach ($pcexp as $regexp) {
    if (ereg($regexp,$postcode, $matches)) {
      // Load new postcode back into the form element  
		  $postcode = strtoupper ($matches[1] . ' ' . $matches [3]);
      // Take account of the special BFPO c/o format
      $postcode = ereg_replace ('C\/O', 'c/o ', $postcode);
      // Remember that we have found that the code is valid and break from loop
      $valid = true;
  // Return with the reformatted valid postcode in uppercase if the postcode was 
  // valid
  if ($valid){
	  $toCheck = $postcode; 
		return true;
	else return false;


Click to download above scripts (1.05k).