NAV
javascript python php

Postcode Lookup API

Our UK Postcode Lookup API provides access to:

With our API, you can implement:

You can get the address data as JSON/JSONP/XML or you can use our ready-made JavaScript class.

To try all the API features, please sign up for a free trial account. Alternatively, you can test with the free postcodes.

If you are looking to implement an international solution, please look at our Global Address Auto-Complete API.

JSON API

The JSON API gives access to Royal Mail PAF data and Geocoding. It supports CORS, can return data as JSON or JSONP and allows sorting.

JSON is the preferred way to go for any new custom integrations. Before you do lots of work, please check our list of Address Finder Plugins. You might find something suitable there.

We also have a wrapper for our JSON API on Github:

JSON API wrapper on Github

If you are looking to implement an international solution, please look at our Global Address Auto-Complete API.

Full Address (RapidAddress)

RapidAddress returns full address details for every address matching the search query postcode.

Example request

function getTestData(){
    // Pass parameters via JSON
    var parameters = {
        key: "xxxxx-xxxxx-xxxxx-xxxxx",
        postcode: "aa11aa",
        response: "data_formatted"
    };
    var url = "http://pcls1.craftyclicks.co.uk/json/rapidaddress";
    // or via GET parameters
    // var url = "http://pcls1.craftyclicks.co.uk/json/rapidaddress?key=xxxxx-xxxxx-xxxxx-xxxxx&postcode=aa11aa&response=data_formatted";

    request = new XMLHttpRequest();
    request.open('POST', url, false);
    // Only needed for the JSON parameter pass
    request.setRequestHeader('Content-Type', 'application/json');
    // Wait for change and then either JSON parse response text or throw exception for HTTP error
    request.onreadystatechange = function() {
        if (this.readyState === 4){
            if (this.status >= 200 && this.status < 400){
                // Success!
                data = JSON.parse(this.responseText);
            } else {
                throw 'HTTP Request Error';
            }
        }
    };
    // Send request
    request.send(JSON.stringify(parameters));
    return data;
}

// console.log(getTestData());
import urllib2
import urllib
import json

def getTestData():
    url = "https://pcls1.craftyclicks.co.uk/json/"

    url += 'rapidaddress'
    params = {
        'postcode': 'aa11aa',
        'key': 'xxxxx-xxxxx-xxxxx-xxxxx',
        'response': 'data_formatted'
    }

    req = urllib2.Request(url + '?' + urllib.urlencode(params))

    res = urllib2.urlopen(req)
    data = json.loads(res.read())
    return data

#print json.dumps(getTestData(), sort_keys=True, indent=4, separators=(',', ': '))
<?php
function getTestData(){
    $data = array(
        "postcode"  => "aa11aa",
        "key"       => "xxxxx-xxxxx-xxxxx-xxxxx",
        "response"  => "data_formatted"
    );
    $data_string = json_encode($data);

    $ch = curl_init('http://pcls1.craftyclicks.co.uk/json/rapidaddress');
    curl_setopt($ch, CURLOPT_CUSTOMREQUEST, "POST");
    curl_setopt($ch, CURLOPT_POSTFIELDS, $data_string);
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
    curl_setopt($ch, CURLOPT_HTTPHEADER, array(
        'Content-Type: application/json',
        'Content-Length: ' . strlen($data_string))
    );

    $result = curl_exec($ch);
    return $result;
}
// echo '<pre>'.getTestData().'</pre>';
?>

HTTP(S) Request

GET/POST http://pcls1.craftyclicks.co.uk/json/rapidaddress

or

GET/POST https://pcls1.craftyclicks.co.uk/json/rapidaddress

Query Parameters

Pass parameters either as GET or POST in JSON.

Parameter Required Description Values Default
key yes Using the API requires a 20 character access token, which you should insert here. You will receive an access token when you sign up for an account. Your 20 digit code
postcode yes This is the postcode for which you want to request data A UK postcode
callback no If callback is set, the JSON data will be wrapped as JSONP with the function name from the callback true, false false
response no This sets the format of the response from the API. paf_compact: All address data returned
data_formatted: Address lines are pre-formatted
paf_compact
lines no Only active when ‘response’ is set to data_formatted. This sets the number of address lines in the response from the API. 1, 2, 3 2
sort no This option sets how the results are sorted in the response. none: Results are not sorted
asc: Results returned in ascending order
desc: results returned in descending order.
none
include_geocode no Sets whether or not to include the geocoding data. Please note that the usage of this feature within this API endpoint is free. true, false false

Response: data_formatted

The API will respond to the request with the following structure.

{
    "delivery_points":[
        {
            "organisation_name":"THE BAKERY",
            "department_name":"",
            "line_1":"1 HIGH STREET",
            "line_2":"CRAFTY VALLEY",
            "udprn":"12345678"
        },
        {
            "organisation_name":"FILMS R US",
            "department_name":"",
            "line_1":"3 HIGH STREET",
            "line_2":"CRAFTY VALLEY",
            "udprn":"12345679"
        }
    ],
    "delivery_point_count":2,
    "postal_county":"POSTAL COUNTY",
    "traditional_county":"TRADITIONAL COUNTY",
    "town":"BIG CITY",
    "postcode":"AA1 1AA"
}

For each postcode, the response contains the following information:

Parameter Type Description
delivery_points array This is an array of objects, each of which contains the data for an individual address. See the table below for more details about the information contained in these objects.
delivery_point_count integer Number of elements in the delivery_points array
postal_county string Former postal county for this postcode
traditional_county string Traditional county for this postcode
town string Town name in uppercase (Royal Mail standard)
postcode string Formatted postcode

data_formatted: delivery_points

Parameter Type Description
organisation_name string Registered organisation at the address.
department_name string Specific department of said organisation.
line_1 string Line 1 of the address
line_2 string Line 2 of the address
line_3 string Line 3 of the address
udprn string Royal Mail unique identifier

Response: paf_compact

The API will respond to the request with the following structure.

{
    "thoroughfare_count": 1,
    "thoroughfares": [
        {
            "delivery_points": [
                {
                    "organisation_name": "THE BAKERY",
                    "department_name": "",
                    "po_box_number": "",
                    "building_number": "1",
                    "sub_building_name": "",
                    "building_name": "",
                    "udprn": "12345678"
                },
                {
                    "organisation_name": "FILMS R US",
                    "department_name": "",
                    "po_box_number": "",
                    "building_number": "3",
                    "sub_building_name": "",
                    "building_name": "",
                    "udprn": "12345679"
                }
            ],
            "delivery_point_count": 2,
            "dependent_thoroughfare_name": "",
            "dependent_thoroughfare_descriptor": "",
            "thoroughfare_name": "HIGH",
            "thoroughfare_descriptor": "STREET"
        }
    ],
    "postal_county": "POSTAL COUNTY",
    "traditional_county": "TRADITIONAL COUNTY",
    "dependent_locality": "CRAFTY VALLEY",
    "double_dependent_locality": "",
    "town": "BIG CITY",
    "postcode": "AA1 1AA"
}

For each postcode, the response contains the following information:

Parameter Type Description
thoroughfares array This array contains thoroughfare details and delivery_points, an array containing all the address details for every address matching the postcode. See the table below for more details.
thoroughfare_count integer Number of elements in the thoroughfares array
postal_county string Former postal county for this postcode
traditional_county string Traditional county for this postcode
town string Town name in uppercase (Royal Mail standard)
postcode string Formatted postcode
dependent_locality string Sub-locality within town or city
double_dependent_locality string District within sub-locality

paf_compact: thoroughfares

Parameter Type Description
delivery_points array This is an array of objects, each of which contains the data for an individual address. See the table below for more details about the information contained in these objects.
delivery_point_count integer Number of elements in the delivery_points array
dependent_thoroughfare_name string Name of the dependent thoroughfare
dependent_thoroughfare_descriptor string The dependent thoroughfare descriptor, e.g. Road, Street, Avenue
thoroughfare_name string Name of the thoroughfare
thoroughfare_descriptor string The thoroughfare descriptor, e.g. Road, Street, Avenue

paf_compact: delivery_points

Parameter Type Description
organisation_name string Registered organisation at the address.
department_name string Specific department of said organisation.
po_box_number string PO Box number
building_number string Number of building
sub_building_name string Sub-name of building
building_name string Name of building
udprn string Royal Mail unique identifier

Street Level (BasicAddress)

BasicAddress returns details of every street matching the search query postcode.

Example request

function getTestData(){
    // Pass parameters via JSON
    var parameters = {
        key: "xxxxx-xxxxx-xxxxx-xxxxx",
        postcode: "aa11aa",
    };
    var url = "http://pcls1.craftyclicks.co.uk/json/basicaddress";
    // or via GET parameters
    // var url = "http://pcls1.craftyclicks.co.uk/json/basicaddress?key=xxxxx-xxxxx-xxxxx-xxxxx&postcode=aa11aa&response=data_formatted";

    request = new XMLHttpRequest();
    request.open('POST', url, false);
    // Only needed for the JSON parameter pass
    request.setRequestHeader('Content-Type', 'application/json');
    // Wait for change and then either JSON parse response text or throw exception for HTTP error
    request.onreadystatechange = function() {
        if (this.readyState === 4){
            if (this.status >= 200 && this.status < 400){
                // Success!
                data = JSON.parse(this.responseText);
            } else {
                throw 'HTTP Request Error';
            }
        }
    };
    // Send request
    request.send(JSON.stringify(parameters));
    return data;
}

// console.log(getTestData());
import urllib2
import urllib
import json

def getTestData():
    url = "https://pcls1.craftyclicks.co.uk/json/"

    url += 'basicaddress'
    params = {
        'postcode': 'aa11aa',
        'key': 'xxxxx-xxxxx-xxxxx-xxxxx',
        'response': 'data_formatted'
    }

    req = urllib2.Request(url + '?' + urllib.urlencode(params))

    res = urllib2.urlopen(req)
    data = json.loads(res.read())
    return data

#print json.dumps(getTestData(), sort_keys=True, indent=4, separators=(',', ': '))
<?php
function getTestData(){
    $data = array(
        "postcode"  => "aa11aa",
        "key"       => "xxxxx-xxxxx-xxxxx-xxxxx",
        "response"  => "data_formatted"
    );
    $data_string = json_encode($data);

    $ch = curl_init('http://pcls1.craftyclicks.co.uk/json/basicaddress');
    curl_setopt($ch, CURLOPT_CUSTOMREQUEST, "POST");
    curl_setopt($ch, CURLOPT_POSTFIELDS, $data_string);
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
    curl_setopt($ch, CURLOPT_HTTPHEADER, array(
        'Content-Type: application/json',
        'Content-Length: ' . strlen($data_string))
    );

    $result = curl_exec($ch);
    return $result;
}
// echo '<pre>'.getTestData().'</pre>';
?>

HTTP(s) Request

GET/POST http://pcls1.craftyclicks.co.uk/json/basicaddress

or

GET/POST https://pcls1.craftyclicks.co.uk/json/basicaddress

Query Parameters

Pass parameters either in GET or in JSON.

Parameter Required Description Values Default
key yes Using the API requires a 20 character access token, which you should insert here. You will receive an access token when you sign up for an account. Your 20 digit code
postcode yes This is the postcode for which you want to request data A UK postcode
callback no If callback is set, the JSON data will be wrapped as JSONP with the function name from the callback true, false false
response no This sets the format of the response from the API. paf_compact: All address data returned
data_formatted: Address lines are pre-formatted
paf_compact
lines no Only active when 'response’ is set to data_formatted. This sets the number of address lines in the response from the API. 1, 2, 3 2
sort no This option sets how the results are sorted in the response. none: Results are not sorted
asc: Results returned in ascending order
desc: results returned in descending order.
none
include_geocode no Sets whether or not to include the geocoding data. Please note that the usage of this feature within this API endpoint is free. true, false false

Response: data_formatted

The API will respond to the request with the following structure.

{
    "thoroughfares": [
        {
            "line_1": "HIGH STREET",
            "line_2": "CRAFTY VALLEY"
        }
    ],
    "thoroughfare_count": 1,
    "postal_county": "POSTAL COUNTY",
    "traditional_county": "TRADITIONAL COUNTY",
    "town": "BIG CITY",
    "postcode": "AA1 1AA"
}

For each postcode, the response contains the following information:

Parameter Type Description
thoroughfares array This array contains thoroughfare details and delivery_points, an array containing all the address details for every address matching the postcode. See the table below for more details.
thoroughfare_count integer Number of elements in the thoroughfares array
postal_county string Former postal county for this postcode
traditional_county string Traditional county for this postcode
town string Town name in uppercase (Royal Mail standard)
postcode string Formatted postcode

thoroughfares

Parameter Type Description
line_1 string Line 1 of the formatted address
line_2 string Line 2 of the formatted address
line_3 string Line 3 of the formatted address

Response: paf_compact

The API will respond to the request with the following structure.

{
    "thoroughfare_count": 1,
    "thoroughfares": [
        {
            "dependent_thoroughfare_name": "",
            "dependent_thoroughfare_descriptor": "",
            "thoroughfare_name": "HIGH",
            "thoroughfare_descriptor": "STREET"
        }
    ],
    "postal_county": "POSTAL COUNTY",
    "traditional_county": "TRADITIONAL COUNTY",
    "dependent_locality": "CRAFTY VALLEY",
    "double_dependent_locality": "",
    "town": "BIG CITY",
    "postcode": "AA1 1AA"
}

For each postcode, the response contains the following information:

Parameter Type Description
thoroughfares array This array contains thoroughfare details and delivery_points, an array containing all the address details for every address matching the postcode. See the table below for more details.
thoroughfare_count integer Number of elements in the thoroughfares array
postal_county string Former postal county for this postcode
traditional_county string Traditional county for this postcode
town string Town name in uppercase (Royal Mail standard)
postcode string Formatted Postcode
dependent_locality string Sub-locality within town or city
double_dependent_locality string District within sub-locality

thoroughfares

Parameter Type Description
dependent_thoroughfare_name string Name of the dependent thoroughfare
dependent_thoroughfare_descriptor string The dependent thoroughfare descriptor, e.g. Road, Street, Avenue
thoroughfare_name string Name of the thoroughfare
thoroughfare_descriptor string The thoroughfare descriptor, e.g. Road, Street, Avenue

Geocoding

Example request

function getTestData(){
    // Pass parameters via JSON
    var parameters = {
        key: "xxxxx-xxxxx-xxxxx-xxxxx",
        // supply the array of postcodes to geocode. max 25.
        postcodes: ["aa11aa","aa11ab"],
        distance: {
            // supply a postcode to measure to
            "base_postcode": "aa11ae"
            /* or northing easting
            "base_ne" : {
                "northing" : 182949,
                "easting"  : 542267
            }
            */
        },
        preserve_index: 1
    };
    var url = "http://pcls1.craftyclicks.co.uk/json/geocode";
    // or via GET parameters
    // var url = "http://pcls1.craftyclicks.co.uk/json/geocode?key=xxxxx-xxxxx-xxxxx-xxxxx&postcode=aa11aa";

    request = new XMLHttpRequest();
    request.open('POST', url, false);
    // Only needed for the JSON parameter pass
    request.setRequestHeader('Content-Type', 'application/json');
    // Wait for change and then either JSON parse response text or throw exception for HTTP error
    request.onreadystatechange = function() {
        if (this.readyState === 4){
            if (this.status >= 200 && this.status < 400){
                // Success!
                data = JSON.parse(this.responseText);
            } else {
                throw 'HTTP Request Error';
            }
        }
    };
    // Send request
    request.send(JSON.stringify(parameters));
    return data;
}

// console.log(getTestData());
import urllib2
import urllib
import json

def getTestData():
    url = "https://pcls1.craftyclicks.co.uk/json/"

    url += 'basicaddress'
    params = {
        'postcode': 'aa11aa',
        'key': 'xxxxx-xxxxx-xxxxx-xxxxx',
        'response': 'data_formatted'
    }

    req = urllib2.Request(url + '?' + urllib.urlencode(params))

    res = urllib2.urlopen(req)
    data = json.loads(res.read())
    return data

#print json.dumps(getTestData(), sort_keys=True, indent=4, separators=(',', ': '))
<?php
function getTestData(){
    $data = array(
        "postcodes" => ["aa11aa","aa11ab"],
        "key" => "xxxxx-xxxxx-xxxxx-xxxxx",
        "distance" => [
            "base_postcode" => "aa11ae"
        ]
    );
    $data_string = json_encode($data);

    $ch = curl_init('http://pcls1.craftyclicks.co.uk/json/geocode');
    curl_setopt($ch, CURLOPT_CUSTOMREQUEST, "POST");
    curl_setopt($ch, CURLOPT_POSTFIELDS, $data_string);
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
    curl_setopt($ch, CURLOPT_HTTPHEADER, array(
        'Content-Type: application/json',
        'Content-Length: ' . strlen($data_string))
    );

    $result = curl_exec($ch);
    return $result;
}
// echo '<pre>'.getTestData().'</pre>';
?>

HTTP(S) Request

GET/POST http://pcls1.craftyclicks.co.uk/json/geocode

or

GET/POST https://pcls1.craftyclicks.co.uk/json/geocode

Query Parameters

Pass parameters either in GET or in JSON. Some parameters are only available in JSON.

Parameter Type Required Available Description
key string yes Both Using the API requires a 20 character access token, which you should insert here. You will receive an access token when you sign up for an account.
postcodes array of strings yes JSON These are the postcodes for which you request data (max 25).
postcode string yes GET The postcode for which you request data
callback string no Both If callback is set, the JSON data will be wrapped as JSONP with the function name from the callback.
distance object no JSON Specify an extra location to calculate distance to
preserve_index bool no JSON Specify how the results should be grouped.
false: index by formatted postcode
true: keep input order and return array

Response

The API will respond to the request with the following structure, if preserve_index is unset or false.

{
    "AA11AA": {
        "lat": 51.5132253,
        "lng": -0.0748047,
        "os": {
            "easting": 533689,
            "northing": 181123
        },
        "distance": 46922
    },
    "AA11AB": {
        "lat": 51.513362,
        "lng": -0.0891883,
        "os": {
            "easting": 532691,
            "northing": 181112
        },
        "distance": 45930
    }
}

The API will respond to the request with the following structure, if preserve_index is true.

[
    {
        "lat": 51.5132253,
        "lng": -0.0748047,
        "os": {
            "easting": 533689,
            "northing": 181123
        },
        "distance": 46922,
        "postcode": "AA11AA"
    },
    {
        "lat": 51.513362,
        "lng": -0.0891883,
        "os": {
            "easting": 532691,
            "northing": 181112
        },
        "distance": 45930,
        "postcode": "AA11AB"
    }
]

For each postcode, the response contains the following information:

Parameter Description
lat Latitude
lng Longitude
os If the postcode exists in OS Code Point Open, northing and easting is available. If the data is not part of the OS dataset, it’s not set. In this case, the lat and lng are estimates only.
distance In meters. (the official Ordnance Survey NE system is based on the metric system.)

XML API

Examples for the XML API are only available in PHP and Python.

The XML API gives access to Royal Mail PAF data only (Geocoding is not available). It supports CORS.

XML is useful for implementing server side postcode lookup on systems where JSON is hard to use. Please also check our list of Address Finder Plugins. You might find something suitable there and save yourself some integration work.

If you are looking to implement an international solution, please look at our Global Address Auto-Complete API.

Full Address (RapidAddress)

RapidAddress returns full address details for every address matching the search query postcode.

Example request (Python and PHP only)

import urllib2
import urllib
import xml.dom.minidom

def getTestData():
    url = "https://pcls1.craftyclicks.co.uk/xml/"

    url += 'rapidaddress'
    params = {
        'postcode': 'aa11aa',
        'key': 'xxxxx-xxxxx-xxxxx-xxxxx',
        'response': 'data_formatted'
    }

    req = urllib2.Request(url + '?' + urllib.urlencode(params))
    res = urllib2.urlopen(req)

    return xml.dom.minidom.parseString( res.read() )

xmldata = getTestData()
print xmldata.toprettyxml()
<?php
function getTestData(){
    $data = array(
        "postcode"  => "aa11aa",
        "key"       => "xxxxx-xxxxx-xxxxx-xxxxx",
        "response"  => "data_formatted"
    );

    $ch = curl_init('http://pcls1.craftyclicks.co.uk/xml/rapidaddress?key='.$data["key"].'&postcode='.$data["postcode"].'&response='.$data["response"]);
    curl_setopt($ch, CURLOPT_CUSTOMREQUEST, "GET");
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);

    $result = curl_exec($ch);
    return $result;
}
// echo '<pre>'.getTestData().'</pre>';
?>

HTTP(S) Request

GET http://pcls1.craftyclicks.co.uk/xml/rapidaddress

or

GET https://pcls1.craftyclicks.co.uk/xml/rapidaddress

Query Parameters

Pass parameters in GET.

Parameter Required Description Values Default
key yes Using the API requires a 20 character access token, which you should insert here. You will receive an access token when you sign up for an account. Your 20 digit code
postcode yes This is the postcode for which you want to request data A UK postcode
response no This sets the format of the response from the API. paf_compact: All address data returned
data_formatted: Address lines are pre-formatted
paf_compact
lines no Only active when ‘response’ is set to data_formatted. This sets the number of address lines in the response from the API. 1, 2, 3 2

Response: data_formatted

The API will respond to the request with the following structure.

<?xml version="1.0" encoding="UTF-8" ?>
<CraftyResponse>
    <address_data_formatted>
        <delivery_point>
            <organisation_name>THE BAKERY</organisation_name>
            <department_name></department_name>
            <line_1>1 HIGH STREET</line_1>
            <line_2>CRAFTY VALLEY</line_2>
            <udprn>12345678</udprn>
        </delivery_point>
        <delivery_point>
            <organisation_name>FILMS R US</organisation_name>
            <department_name></department_name>
            <line_1>3 HIGH STREET</line_1>
            <line_2>CRAFTY VALLEY</line_2>
            <udprn>12345679</udprn>
        </delivery_point>
        <delivery_point_count>5</delivery_point_count>
        <town>BIG CITY</town>
        <postal_county>POSTAL COUNTY</postal_county>
        <traditional_county>TRADITIONAL COUNTY</traditional_county>
        <postcode>AA1 1AA</postcode>
    </address_data_formatted>
</CraftyResponse>

For each postcode, the response contains the following information:

Parameter Description
delivery_point Each delivery_point contains the data for an individual address. See the table below for more details of the information the delivery_point contains.
delivery_point_count Number of delivery_points
postal_county Former postal county for this postcode
traditional_county Traditional county for this postcode
town Town name in uppercase (Royal Mail standard)
postcode Formatted Postcode

delivery_point

Parameter Description
organisation_name Registered organisation at the address.
department_name Specific department of said organisation.
line_1 Line 1 of the address
line_2 Line 2 of the address
line_3 Line 3 of the address
udprn Royal Mail unique identifier

Response: paf_compact

The API will respond to the request with the following structure.

<?xml version="1.0" encoding="UTF-8" ?>
<CraftyResponse>
    <address_data_paf_compact>
        <thoroughfare_count>1</thoroughfare_count>
        <thoroughfare>
            <delivery_point_count>5</delivery_point_count>
            <delivery_point>
                <organisation_name>THE BAKERY</organisation_name>
                <department_name></department_name>
                <po_box_number></po_box_number>
                <building_number>1</building_number>
                <sub_building_name></sub_building_name>
                <building_name></building_name>
                <udprn>12345678</udprn>
            </delivery_point>
            <delivery_point>
                <organisation_name>FILMS R US</organisation_name>
                <department_name></department_name>
                <po_box_number></po_box_number>
                <building_number>3</building_number>
                <sub_building_name></sub_building_name>
                <building_name></building_name>
                <udprn>12345679</udprn>
            </delivery_point>
            <dependent_thoroughfare_name></dependent_thoroughfare_name>
            <dependent_thoroughfare_descriptor></dependent_thoroughfare_descriptor>
            <thoroughfare_name>HIGH</thoroughfare_name>
            <thoroughfare_descriptor>STREET</thoroughfare_descriptor>
        </thoroughfare>
        <double_dependent_locality></double_dependent_locality>
        <dependent_locality>CRAFTY VALLEY</dependent_locality>
        <town>BIG CITY</town>
        <postal_county>POSTAL COUNTY</postal_county>
        <traditional_county>TRADITIONAL COUNTY</traditional_county>
        <postcode>AA1 1AA</postcode>
    </address_data_paf_compact>
</CraftyResponse>

For each postcode, the response contains the following information:

Parameter Description
thoroughfares This contains delivery_points, which contain all the address details for every address matching the postcode, and thoroughfare details. See the table below for more.
thoroughfare_count Number of thoroughfares
postal_county Former postal county for this postcode
traditional_county Traditional county for this postcode
town Town name in uppercase (Royal Mail standard)
postcode Formatted Postcode
dependent_locality Sub-locality within town or city
double_dependent_locality District within sub-locality

thoroughfare

Parameter Description
delivery_points Each delivery_point contains the data for an individual address. See the table below for more details of the information the delivery_point contains.
delivery_point_count Number of delivery_points
dependent_thoroughfare_name Name of the dependent thoroughfare
dependent_thoroughfare_descriptor The dependent thoroughfare descriptor, e.g. Road, Street, Avenue
thoroughfare_name Name of the thoroughfare
thoroughfare_descriptor The thoroughfare descriptor, e.g. Road, Street, Avenue

delivery_point

Parameter Description
organisation_name Registered organisation at the address.
department_name Specific department of said organisation.
po_box_number PO Box number
building_number Number of building
sub_building_name Sub-name of building
building_name Name of building
udprn Royal Mail unique identifier.

Street Level (BasicAddress)

BasicAddress returns details of every street matching the search query postcode.

Example request (Python and PHP only)

import urllib2
import urllib
import xml.dom.minidom

def getTestData():
    url = "https://pcls1.craftyclicks.co.uk/xml/"

    url += 'basicaddress'
    params = {
        'postcode': 'aa11aa',
        'key': 'xxxxx-xxxxx-xxxxx-xxxxx',
        'response': 'data_formatted'
    }

    req = urllib2.Request(url + '?' + urllib.urlencode(params))
    res = urllib2.urlopen(req)

    return xml.dom.minidom.parseString( res.read() )

xmldata = getTestData()
print xmldata.toprettyxml()
<?php
function getTestData(){
    $data = array(
        "postcode"  => "aa11aa",
        "key"       => "xxxxx-xxxxx-xxxxx-xxxxx",
        "response"  => "data_formatted"
    );

    $ch = curl_init('http://pcls1.craftyclicks.co.uk/xml/basicaddress?key='.$data["key"].'&postcode='.$data["postcode"].'&response='.$data["response"]);
    curl_setopt($ch, CURLOPT_CUSTOMREQUEST, "GET");
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);

    $result = curl_exec($ch);
    return $result;
}
// echo '<pre>'.getTestData().'</pre>';
?>

HTTP(s) Request

GET http://pcls1.craftyclicks.co.uk/xml/basicaddress

or

GET https://pcls1.craftyclicks.co.uk/xml/basicaddress

Query Parameters

Pass parameters either in GET or in JSON.

Parameter Required Description Values Default
key yes Using the API requires a 20 character access token, which you should insert here. You will receive an access token when you sign up for an account. Your 20 digit code
postcode yes This is the postcode for which you want to request data A UK postcode
response no This sets the format of the response from the API. paf_compact: All address data returned
data_formatted: Address lines are pre-formatted
paf_compact
lines no Only active when ‘response’ is set to data_formatted. This sets the number of address lines in the response from the API. 1, 2, 3 2

Response: data_formatted

The API will respond to the request with the following structure.

<?xml version="1.0" encoding="UTF-8" ?>
<CraftyResponse>
    <address_data_formatted>
        <thoroughfare>
            <line_1>HIGH STREET</line_1>
            <line_2>CRAFTY VALLEY</line_2>
        </thoroughfare>
        <town>BIG CITY</town>
        <postal_county>POSTAL COUNTY</postal_county>
        <traditional_county>TRADITIONAL COUNTY</traditional_county>
        <postcode>AA1 1AA</postcode>
    </address_data_formatted>
</CraftyResponse>

For each postcode, the response contains the following information:

Parameter Description
thoroughfare Each thoroughfare contains details for a thoroughfare matching the postcode. See the table below for more details.
thoroughfare_count Number of thoroughfares
postal_county Former postal county for this postcode
traditional_county Traditional county for this postcode
town Town name in uppercase (Royal Mail standard)
postcode Formatted Postcode

thoroughfare

Parameter Description
line_1 Line 1 of the formatted address
line_2 Line 2 of the formatted address
line_3 Line 3 of the formatted address

Response: paf_compact

The API will respond to the request with the following structure.

<?xml version="1.0" encoding="UTF-8" ?>
<CraftyResponse>
    <address_data_paf_compact>
        <thoroughfare_count>1</thoroughfare_count>
        <thoroughfare>
            <dependent_thoroughfare_name></dependent_thoroughfare_name>
            <dependent_thoroughfare_descriptor></dependent_thoroughfare_descriptor>
            <thoroughfare_name>HIGH</thoroughfare_name>
            <thoroughfare_descriptor>STREET</thoroughfare_descriptor>
        </thoroughfare>
        <double_dependent_locality></double_dependent_locality>
        <dependent_locality>CRAFTY VALLEY</dependent_locality>
        <town>BIG CITY</town>
        <postal_county>POSTAL COUNTY</postal_county>
        <traditional_county>TRADITIONAL COUNTY</traditional_county>
        <postcode>AA1 1AA</postcode>
    </address_data_paf_compact>
</CraftyResponse>

For each postcode, the response contains the following information:

Parameter Description
thoroughfare Each thoroughfare contains details for a thoroughfare matching the postcode. See the table below for more details.
thoroughfare_count Number of thoroughfares
postal_county Former postal county for this postcode
traditional_county Traditional county for this postcode
town Town name in uppercase (Royal Mail standard)
postcode Formatted Postcode
dependent_locality Sub-locality within town or city
double_dependent_locality District within sub-locality

thoroughfare

Parameter Description
dependent_thoroughfare_name Name of the dependent thoroughfare
dependent_thoroughfare_descriptor The dependent thoroughfare descriptor, e.g. Road, Street, Avenue
thoroughfare_name Name of the thoroughfare
thoroughfare_descriptor The thoroughfare descriptor, e.g. Road, Street, Avenue

JavaScript Class

Our JavaScript class provides a convenient API for client-side postcode lookup integration into any HTML page.

It is used in most of our Address Finder Plugins. It’s the quickest way to add postcode lookup to your website without having to write much code.

Download the latest version of the JavaScript Class from Github

If you are looking to implement an international solution, please look at our Global Address Auto-Complete API.

Creating a lookup object

Include our core class

Link to JavaScript class file (you will need to change src property to your own file path)

<script src="crafty_postcode.class.js"></script>

Download a copy of our javascript class and upload crafty_postcode.class.js your server. Include it in your HTML page.

Instantiate the object

Instantiate the object

<script>
  var cp_obj = CraftyPostcodeCreate();
  cp_obj.set("access_token", "xxxxx-xxxxx-xxxxx-xxxxx"); // your token here

  cp_obj.set("option_1", "value_1");
    ...
  cp_obj.set("option_n", "value_n");
</script>

Instantiate an object and set the config (for detail on all the options, see lower down this page).

Add multiple lookups

If you want to use address lookup more than once on a page, you can create multiple objects. Each object can be used independently of the others.

Add multiple lookups

<script>
  var cp_obj_1 = CraftyPostcodeCreate();
    ...
  var cp_obj_n = CraftyPostcodeCreate();
</script>

Select form elements

Method 1

<script>
  cp_obj.set("form", ""); //blank!
  cp_obj.set("elem_company", "companyname_id"); // input field ID
  cp_obj.set("elem_street1", "address1_id"); // input field ID
  //... etc ...
</script>

Method 2

<script>
  cp_obj.set("form", "XYZ"); //form name
  cp_obj.set("elem_company", "companyname"); // input field name
  cp_obj.set("elem_street1", "address1"); // input field name
  //... etc ...
</script>

There are two methods to tell the object where to find the address form fields:

Method 1:

Attach unique IDs to all the fields. Leave the “form” config blank.

Method 2:

Tell the script the name of the form and the names of the fields.

Minimum configuration

Minimum configuration

<script>
    var cp_obj = CraftyPostcodeCreate();
    cp_obj.set("access_token", "xxxxx-xxxxx-xxxxx-xxxxx"); // your token here
    cp_obj.set("form", "");
    cp_obj.set("elem_company", "");
    cp_obj.set("elem_street1", "address1");
    cp_obj.set("elem_street2", "");
    cp_obj.set("elem_street3", "");
    cp_obj.set("elem_town", "town");
    cp_obj.set("elem_county", "");
    cp_obj.set("elem_postcode", "postcode");
    cp_obj.set("elem_house_num", "");
</script>

Here you can find a simple, minimum configuration of our class.

All configuration options

Example of configuration using all available options

<script>
    var cp_obj = CraftyPostcodeCreate();
    cp_obj.set("access_token", "xxxxx-xxxxx-xxxxx-xxxxx"); // Your access token
    cp_obj.set("result_elem_id", "crafty_postcode_result_display");
    cp_obj.set("form", ""); // Use IDs to find the form elements
    cp_obj.set("elem_company", "");
    cp_obj.set("elem_street1", "address1"); // ID of address line 1 element
    cp_obj.set("elem_street2", "");
    cp_obj.set("elem_street3", "");
    cp_obj.set("elem_town", "town");
    cp_obj.set("elem_county", "");
    cp_obj.set("elem_postcode", "postcode");
    cp_obj.set("elem_house_num", "");
    cp_obj.set("traditional_county", 1);
    cp_obj.set("busy_img_url", file); // Set a custom busy image
    cp_obj.set("max_width", "500px"); // Set width of result box to 500px
    cp_obj.set("max_lines", 5); // Set max no of lines in result box to 5
    cp_obj.set("hide_result", 1); // Set result box to disappear when result selected
    cp_obj.set("org_uppercase", 0); // Return company name in leading upper case
    cp_obj.set("town_uppercase", 1); // Return town in upper case
    cp_obj.set("county_uppercase", 0); // Return county in leading upper case
    cp_obj.set("addr_uppercase", 0); // Return rest of address in leading upper case
    cp_obj.set("delimiter", ","); // Set delimiter to comma
    cp_obj.set("msg1", "Please wait while we find the address"); // Set busy image title
    // Set error messages
    cp_obj.set("err_msg1", "This postcode could not be found");
    cp_obj.set("err_msg2", "This postcode is not valid");
    cp_obj.set("err_msg3", "Unable to connect to server");
    cp_obj.set("err_msg4", "An unexpected error occurred");
    cp_obj.set("res_autoselect", 1); // Auto-select the first result
    cp_obj.set("res_select_on_change", 1); // Select results as user scrolls through box
    cp_obj.set("first_res_line", "—– please select your address —–"); // Adds a dummy first line
    cp_obj.set("debug_mode", 1); // Debug mode on
    cp_obj.set("lookup_timeout", 10000); // Timeout after 10 seconds
    cp_obj.set("on_result_ready", function(){
	// Do something when result received from server
    });
    cp_obj.set("on_result_selected", function(){
	// Do something when result selected by user
    }); 
    cp_obj.set("on_error", function(){
	// Do something when an error occurs
    }); 
    cp_obj.set("pre_populate_common_address_parts", 1); // Place common parts of address on form
    cp_obj.set("lookup_url", file);  // Use data relay script
    cp_obj.set("basic_address", 0); // Use RapidAddress
    cp_obj.set("single_res_autoselect", 1); // Auto-select a single result
    cp_obj.set("single_res_notice", "Search result auto-selected"); // Display on auto-select
</script>
Option Name Description Values Default
access_token Using the API requires a 20 character access token, which you should insert here. You will receive an access token when you sign up for an account. Your 20 digit token
result_elem_id This is the ID of the element that is used for displaying the results of the postcode lookup. ID
form The name of the address form to be used (names will be used to find elements). If left blank, IDs will be used to find form elements. Name
elem_company Company input element (optional) Name or ID
elem_house_num House number input element (optional) Name or ID
elem_street1 Address line 1 input element (required) Name or ID
elem_street2 Address line 2 input element (optional) Name or ID
elem_street3 Address line 3 input element (optional) Name or ID
elem_town Town/city input element (required) Name or ID
elem_county County/state select/input element (optional) Name or ID
elem_postcode Postcode input element (required). This is both an input and an output. Name or ID
traditional_county This sets the type of county that will be returned. 0: Former postal county
1: Traditional county name
0
busy_img_url Set the location of a ‘busy’ image which is shown while waiting for the server response. A file path ‘crafty_postcode_busy.gif’
max_width Set this if you want to limit the width of the result box (in px) Width in pixels, e.g. “450px”
max_lines Set the maximum number of text lines in the result box An integer
hide_result Set whether the result box should disappear when a result is selected 1, 0 0
org_uppercase Set format of organisation that is returned 0: Company name has leading upper case
1: All in upper case
1
town_uppercase Set format of town/city that is returned 0: Town has leading upper case
1: All in upper case (recommended by Royal Mail)
1
county_uppercase Set format of county/state that is returned 0: County has leading upper case
1: All in upper case
0
addr_uppercase Set format of other address lines that are returned 0: Rest of address lines have leading upper case
1: All in upper case
0
delimiter Set the delimiter to use between parts of the address Any character, eg “, ,
msg1 Message to attach as a title to the busy image A string 'Please wait while we find the address’
err_msg1 Error message if the postcode does not exist A string 'This postcode could not be found, please try again or enter your address manually’
err_msg2 Error message if the postcode is not correctly formatted A string 'This postcode is not valid, please try again or enter your address manually’
err_msg3 Error message if there is a network problem A string 'Unable to connect to address lookup server, please enter your address manually.’
err_msg4 Error message to cover any other problem A string (err_num) + 'An unexpected error occurred, please enter your address manually.’
res_autoselect Option to auto-select the first result as soon as the result box is shown 1, 0 1
res_select_on_change Option to select results as the user scrolls through the results box 1: Results will be selected
0: User must explicitly click to select
1
first_res_line Option to add a dummy first line to the results box A string, e.g. '—– please select your address —–’ blank
debug_mode If debug mode is on, more descriptive error messages will be displayed. 1, 0 0
lookup_timeout Maximum time to spend waiting for lookup server response Time in milliseconds 10000 (10 seconds)
on_result_ready Callback function name called when result is received from the lookup server A function
on_result_selected Callback function name called when the user clicks on a result A function
on_error Callback function called if there is an error A function
pre_populate_common_address_parts Option for placing all common parts of the address on the form every time the drop-down is shown 1, 0 0
lookup_url Set this option to use a data relay script File path Accesses the CraftyClicks web service directly
basic_address Set whether BasicAddress is used 0: Rapid/Flexi Address
1: BasicAddress
0
single_res_autoselect Option for auto-selecting a result if only one result is found 1, 0 1
single_res_notice If single_res_autoselect = 1 and there is only a single result, this message wil be shown A string

Debugging

Setting debug mode

<script>
  cp_obj.set("debug_mode",   "1");
</script>

If things don’t work right away, set the object into debug mode and see if the error messages give any clues:

If you still have no luck – email any error codes/messages to us at support@craftyclicks.co.uk. We will be happy to help.

Testing

If you wish to test our service, please use one of the following free test postcodes:

Errors

JSON error format

{
    "error_code": "0001",
    "error_msg": "No data was found for the requested postcode."
}

XML error format

<?xml version="1.0" encoding="UTF-8" ?>
<CraftyResponse>
    <error_code>0001</error_code>
    <error_msg>No data was found for the requested postcode.</error_msg>
</CraftyResponse>

The JSON API uses the following error codes:

Error Code Meaning
0001 Postcode not found – The requested postcode doesn’t exist.
0002 Invalid postcode format – The requested postcode cannot exist. (Misformatted)
0006 Too many postcodes requested – (Mass Geocoding API, max 25)
1001 JSON syntax error
1002 No postcode(s) – You didn’t supply a postcode.
7001 Demo limit exceeded – You ran out of free trial clicks.
8001 Invalid or no access token – You didn’t supply an active access token.
8003 Account credit allowance exceeded – You ran out of credits. Please review your balance.
8004 Access denied due to access rules – Your token configuration is limiting you.
8005 Access denied, account suspended – We disabled your account. Please contact us.
9001 Internal Server Error – We had a problem with our server. Try again later.