UK Post Code Distance Calculation in PHP
I have always wondered how some websites calculate distance between post codes. A new project came along which needed to calculate the distance between 2 post codes.
The solution is basically a database or CSV of post codes, each record will contain the first part of the postcode and the latitude and longitude. What you will need is the SQL file or the CSV file and a bit of old school mathematics. I have also included the county or area in both SQL and CSV, you will not need these, but I have included them anyway as they might help you.
To calculate the distance between the two points of latitude I will use the Haversine formula. This basically means the shortest distance over the earth’s surface as the crow fly’s (ignores any hills etc.). It is spherical trigonometry, much better than normal trigonometry as we are calculating the distances from two points on the earth’s surface. The Haversin formula assumes the earth is a perfect sphere which it is not, it is more ellipsoidal. Therefore this formula will work well for small distances and as we are working with just UK post codes then this is acceptable error margin. If you are looking to develop a project that uses world wide distances then you would probably be best looking at the Vencety formula.
The Haversine Formula Method

The first point we will use is CB2 (Cambridge) lat: 52.163, long: 0.133
The first point we will use is SS4 (Southend on Sea) lat: 51.594, long: 0.715$lat1 = 52.163 latitude of the first point
$long1 = 0.133 longitude of the first point
$lat2 = 51.594 latitude of the second point
$long2 = 0.715 longitude of the second point
$earth = 6373 the Earth’s mean radius, 6373 KM (according to wikipedia) we can also use miles 3960.
sine angle of lattitude
$sinelat = sin ( $lat2 - $lat1 )
sine angle of longitude
$sinelong= sin ( $long2 - $long1 )
and the rest of the haversine formula
$a = ( $sinlat * $sinlat ) + cos ( $lat1 ) * cos ( $lat2 ) * ( $sinlong * $sinlong )
$c = 2 * asin ( min ( 1 , sqrt ( $a ) ) )
$d = round ( $earth * $c )
So the direct distance from post code CB2 to SS4 is 47 miles which is about right.
The above formula as a function:
< ?php
function getDistance($lat1, $long1, $lat2, $long2)
{
//$earth = 6371; //km change accordingly
$earth = 3960; //miles
//Point 1 cords
$lat1 = deg2rad($lat1);
$long1= deg2rad($long1);
//Point 2 cords
$lat2 = deg2rad($lat2);
$long2= deg2rad($long2);
//Haversine Formula
$dlong=$long2-$long1;
$dlat=$lat2-$lat1;
$sinlat=sin($dlat/2);
$sinlong=sin($dlong/2);
$a=($sinlat*$sinlat)+cos($lat1)*cos($lat2)*($sinlong*$sinlong);
$c=2*asin(min(1,sqrt($a)));
$d=round($earth*$c);
return $d;
}
// pull cords out of database
echo "Distance in miles from CB2 to SS4: ".getDistance(52.163, 0.133, 51.594, 0.715);
?>
I have also packaged a demo application to give you a better understanding.
You can view the demo working here.
You can view the source code or download it all zipped up.
on April 16th, 2007 at 5:19 pm
Nice article Paul, thanks for this !
on April 20th, 2007 at 11:53 am
Hi, an excellent piece of wok can you tell where the csv came from please.
on April 25th, 2007 at 12:01 am
Thanks Andy =)
The database is currently being compiled by my company and will be soon be offering API solutions for postcode and geo information. More info check out: http://www.nurvex.co.uk
on May 2nd, 2007 at 3:08 pm
You are not consistent with you determination of dlon and dlat used on the formula and what is used in the function.
on May 2nd, 2007 at 3:09 pm
I made a mistake, it is the sinlat and sinlong that is different.
on May 14th, 2007 at 4:10 pm
I may be mistanken, but my understanding is that the postoffice/OS own the copyright on data representing postcode aslatitude/longitude values?
on May 18th, 2007 at 2:58 pm
loving your work. v handy. cheers.
on May 19th, 2007 at 2:00 pm
No you can’t own copyright of coordinates, you can copyright and licence a database with them in but we are creating a separate one using a new technique of locating them. If you check UK Postcodes on Wikipedia I believe there are some community efforts of doing the same.
on May 28th, 2007 at 4:19 am
disregard my previous comment. I copied / pasted your function from your source and put it in project to test (previously just visually compared). It works! I still don`t know where my code is different :(
well done. sorry for the premature judgement!
on May 29th, 2007 at 12:34 pm
That is really usefull info, but I am stuck on a project where I need co-ordinates for CB22 and CB23.
Any suggestions as to where I can find them?
on May 29th, 2007 at 2:36 pm
Hey John
Our premium post code database has all up to date changes, if you are looking for an up to date database it might be worth thinking about. The one you see attached to this post is just the basic one. In September 2006 Royal Mail changed the CB2 and CB3 postcodes:
The CB2 4XX, CB2 5XX, CB2 5XX are now CB22 XXX.
The CB3 6XX, CB3 7XX, CB3 8XX are now CB23 XXX.
So just add these in the csv:
CB22,Cambridge,52.163,0.133
CB23,Cambridge,52.213,0.025
on June 21st, 2007 at 11:25 am
Excellent Work
Thanks a Lot
on June 29th, 2007 at 12:44 pm
Where can I obtain the ‘premium post code database’ ?
Cheers