Postcodes.io allows UK postcode data to be queried over a JSON HTTP API.
Docker images are available for simple self hosting and rapid, local querying of the UK postcode dataset
All services can be accessed from the following HTTP[S] endpoint
https://api.postcodes.io
The API accepts GET and POST requests. POST methods use content type
application/json
The Postcodes.io application and database are packaged as Docker images for rapid local deployment and data extraction.
To perform one-time data extraction tasks using SQL, see our local data extraction guide.
JSON(P) only. CORS is enabled.
Each response comes with an appropriate HTTP Status code (except for JSONP requests). These include 200 for success, 400 for a bad request, 404 for not found and 500 for server error. The HTTP Status code is also included in the response body.
Postcodes.io does not require any authentication.
To check for errors, examine the HTTP response code. 200 response indicates success while any other code will provide important information about why an error occured.
Alternatively, you can examine status code in the 'status' property in the result body.
All JSONP requests return 200 responses because of silent errors. When using JSONP, be sure to use the latter method to check for errors.
JSONP requests are supported. Simply appended the URI with a callback name. e.g.
https://api.postcodes.io/postcodes/GU50BD?callback=foo
The API currently does not use any form of versioning. Any changes to the API will be backwards-compatible, this includes: adding new properties to responses, adding new endpoints, adding new optional request parameters and changing the order of properties.
If we make backwards-incompatible changes in the future, this will be released under a versioned endpoint.
Data points returned by the /postcodes
and
/outcodes
API
Note: Some fields may be null
if not applicable or
populated. These fields return type is specified as
type|null
Field | Description |
---|---|
postcode string
|
Postcode. All current (‘live’) postcodes within the United Kingdom, the Channel Islands and the Isle of Man, received monthly from Royal Mail. 2, 3 or 4-character outward code, single space and 3-character inward code. |
outcode string
|
Outward Code. The outward code is the part of the postcode before the single space in the middle. It is between two and four characters long. A few outward codes are non-geographic, not divulging where mail is to be sent. Examples of outward codes include "L1", "W1A", "RH1", "RH10" or "SE1P". |
incode string
|
Inward Code. The inward part is the part of the postcode after the single space in the middle. It is three characters long. The inward code assists in the delivery of post within a postal district. Examples of inward codes include "0NY", "7GZ", "7HF", or "8JQ". |
quality integer
|
Positional Quality. Shows the status of the
assigned grid reference.
|
eastings integer|null
|
Eastings. The Ordnance Survey postcode grid
reference Easting to 1 metre resolution. Grid references for
postcodes in Northern Ireland relate to the Irish Grid system. May
be null if geolocation not available.
|
northings integer|null
|
Northings. The Ordnance Survey postcode grid
reference Northing to 1 metre resolution. Grid references for
postcodes in Northern Ireland relate to the Irish Grid system. May
be null if geolocation not available.
|
country string
|
Country. The country (i.e. one of the four constituent countries of the United Kingdom or the Channel Islands or the Isle of Man) to which each postcode is assigned. |
nhs_ha string|null
|
Strategic Health Authority. The health area code for the postcode. |
admin_county string|null
|
County. The current county to which the postcode has been assigned. |
admin_district string|null
|
District. The current district/unitary authority to which the postcode has been assigned. |
admin_ward string|null
|
Ward. The current administrative/electoral area to which the postcode has been assigned. |
longitude double float|null
|
Longitude. The WGS84 longitude given the
Postcode's national grid reference. May be null if
geolocation not available.
|
latitude double float|null
|
Latitude. The WGS84 latitude given the Postcode's
national grid reference. May be null if geolocation
not available.
|
parliamentary_constituency string|null
|
Westminster Parliamentary Constituency. The Westminster Parliamentary Constituency code for each postcode. |
european_electoral_region string|null
|
European Electoral Region (EER). The European Electoral Region code for each postcode. |
primary_care_trust string|null
|
Primary Care Trust (PCT). The code for the Primary Care areas in England, LHBs in Wales, CHPs in Scotland, LCG in Northern Ireland and PHD in the Isle of Man; there are no equivalent areas in the Channel Islands. Care Trust/ Care Trust Plus (CT)/ local health board (LHB)/ community health partnership (CHP)/ local commissioning group (LCG)/ primary healthcare directorate (PHD). |
region string|null
|
Region (formerly GOR). The Region code for each postcode. The nine GORs were abolished on 1 April 2011 and are now known as ‘Regions’. They were the primary statistical subdivisions of England and also the areas in which the Government Offices for the Regions fulfilled their role. Each GOR covered a number of local authorities. |
parish string|null
|
Parish (England)/community (Wales). The smallest type of administrative area in England is the parish (also known as 'civil parish'); the equivalent units in Wales are communities. |
lsoa string|null
|
2011 Census lower layer super output area (LSOA). The 2011 Census lower layer SOA code for England and Wales, SOA code for Northern Ireland and data zone code for Scotland. |
msoa string|null
|
2011 Census middle layer super output area (MSOA). The 2011 Census middle layer SOA (MSOA) code for England and Wales and intermediate zone for Scotland. |
ced string|null
|
County Electoral District. The county electoral
division code for each English postcode. Pseudo codes are included
for the remainder of the UK. The field will be
null for English postcodes with no grid reference.
English county councils use county electoral divisions (CED) to
elect councillors. These CEDs must be confined within district
boundaries, but need not be based on whole electoral wards. The
only exceptions are the Isles of Scilly and the Greater London
Authority (GLA). CEDs do not exist within UAs.
|
ccg string|null
|
Sub ICB Location (LOC)/ Local Health Board (LHB)/ Community Health Partnership (CHP)/ Local Commissioning Group (LCG)/ Primary Healthcare Directorate (PHD). The code for the Sub ICB Locations in England, LHBs in Wales, CHPs in Scotland, LCG in Northern Ireland and PHD in the Isle of Man; there are no equivalent areas in the Channel Islands. This was formerly Clinical Commissioning Group. From July 2022, CCGs were replaced by Sub-ICB locations. |
nuts string|null
|
International Terratorial Levels (ITL) (Former Nomenclature of Units for Territorial Statistics (NUTS). The national LAU1-equivalent code for each postcode. Pseudo codes are included for Channel Islands and Isle of Man. The field will otherwise be blank for postcodes with no grid reference.
As of May 2021. NUTS has changed to International Territorial Levels (ITL). Postcodes.io will report ITL in nuts and codes.nuts to preserve backwards compatibility.
Following the UK’s withdrawal from the EU, a new UK-managed international statistical geography - ITL (International Territorial Levels) - was introduced from 1st January 2021, replacing the former NUTS classification. They align with international standards, enabling comparability both over time and internationally. To ensure continued alignment, the ITLs mirror the NUTS system. They also follow a similar review timetable – every three years. NUTS is a hierarchical classification of spatial units that provides a breakdown of the European Union’s territory for producing regional statistics that are comparable across the Union. The ITL area classification in the UK comprises current national administrative and electoral areas, except in Scotland where some ITL areas comprise whole and/or part Local Enterprise Regions. The ONSPD contains the LAU1 code (9-character LAD/UA code for England, Wales and Northern Ireland and 'S30' code for Scotland). A comprehensive lookup of LAU and ITL codes is included with the accompanying metadata. |
codes Object
|
Returns an ID or Code associated with the postcode. Typically, these are a 9 character code known as an ONS Code or GSS Code. This is currently only available for districts, parishes, counties, CCGs, NUTS and wards. |
codes.admin_district string|null
|
See description of admin_district field. |
codes.admin_county string|null
|
See description of admin_county field. |
codes.admin_ward string|null
|
See description of admin_ward field. |
codes.parish string|null
|
See description of parish field. |
codes.ccg string|null
|
See description of ccg field. |
codes.ccg_code string|null
|
CCG Short Code. e.g. "07N" . |
codes.nuts string|null
|
The ITL code associated with the postcode. |
codes.lau2 string|null
|
The LAU2 code associated with the postcode. |
codes.lsoa string|null
|
See description of lsoa field. |
codes.msoa string|null
|
See description of msoa field. |
Data returned by the /outcodes
API
Field | Description |
---|---|
outcode string
|
Outcode. The outcode or outward code is the part of the postcode before the single space in the middle. It is between two and four characters long. Examples of outward codes include "L1", "W1A", "RH1", "RH10" or "SE1P". A few outward codes are non-geographic, not divulging where mail is to be sent. |
eastings integer|null
|
Eastings. The Ordnance Survey postcode grid reference Easting to 1 metre resolution; blank for postcodes in the Channel Islands and the Isle of Man. Grid references for postcodes in Northern Ireland relate to the Irish Grid system. Computed as the arithmetic mean of the input coordinates. Returns 0 if geolocation is not available. |
northings integer|null
|
Northings. The Ordnance Survey postcode grid reference Northing to 1 metre resolution; blank for postcodes in the Channel Islands and the Isle of Man. Grid references for postcodes in Northern Ireland relate to the Irish Grid system. Computed as the arithmetic mean of the input coordinates. Returns 0 if geolocation is not available. |
admin_county string[]
|
County. The current counties under the outcode. |
admin_district string[]
|
District. The current district/unitary authorites under the outcode. |
admin_ward string[]
|
Ward. The current administrative/electoral areas under the outcode. |
longitude double float | null
|
Longitude. The WGS84 longitude given the
Postcode's national grid reference. Computed as the arithmetic
mean of input coordinates. May be null if geolocation
not available.
|
latitude double float | null
|
Latitude. The WGS84 latitude given the Postcode's
national grid reference. Computed as the arithmetic mean of input
coordinates. May be null if geolocation not
available.
|
country string[]
|
Country. The countries included in the outcode. |
parish string[]
|
Parish (England)/community (Wales). The parishes included in the outcode. |
Data returned by the /scotland/*
APIs
Field | Description |
---|---|
postcode string
|
Postcode. Royal Mail postcode. |
scottish_parliamentary_constituency string
|
Scottish Parliamentary Constituency 2014 Scottish Parliamentary Constituency. |
codes Object
|
Returns an ID or Code associated with the postcode. Typically, these are a 9 character code known as an ONS Code or GSS Code. |
codes.scottish_parliamentary_constituency string
|
Scottish Parliamentary Constituency GSS Code. A code that identifies a 2014 Scottish Parliamentary Constituency. |
Data returned by the /terminated_postcodes/*
APIs
Field | Description |
---|---|
postcode string
|
Postcode. All currently terminated postcodes within the United Kingdom, the Channel Islands and the Isle of Man, received every 3 months from Royal Mail. 2, 3 or 4-character outward code, single space and 3-character inward code. |
year_terminated integer
|
Termination year. Year of termination of a postcode. |
month_terminated integer
|
Termination month. Month of termination of a postcode. 1-January, 2-February ... 12-December. |
longitude double float
|
Longitude. The WGS84 longitude given the Postcode's national grid reference. |
latitude double float
|
Latitude. The WGS84 latitude given the Postcode's national grid reference. |
Data returned by the /places
API
Note: Some fields may be null
if not applicable or
populated. These fields return type is specified as
type|null
Field | Description |
---|---|
code string
|
code. A unique identifier that enables records to be identified easily. The identifier will be persistent for all LocalTypes except Section of Named Road and Section of Numbered Road. |
eastings integer
|
Eastings. The Ordnance Survey postcode grid reference Easting to 1 metre resolution; blank for postcodes in the Channel Islands and the Isle of Man. |
northings integer
|
Northings. The Ordnance Survey postcode grid reference Northing to 1 metre resolution; blank for postcodes in the Channel Islands and the Isle of Man. |
[max|min]_northings, [max|min]_eastings integer
|
Maximum & Minimum, Northings & Eastings. Bounding box or Minimum Bounding Rectangle (MBR) for roads and settlements. For Settlements and Sections of Named and Numbered Roads, the MBR gives a representation of the extent of these features and is not snapped to the real world extent. |
country string
|
Country. OS Places relates to Great Britain only.
i.e. England , Scotland , Wales .
|
longitude double float
|
Longitude. The WGS84 longitude given the Place's national grid reference. |
latitude double float
|
Latitude. The WGS84 latitude given the Place's national grid reference. |
local_type string
|
Local Type. The Ordnance Survey classification
for the named place being represented by the specific feature,
e.g. City , Town , Village ,
Hamlet , Other Settlement ,
Suburban Area .
|
outcode string
|
Outcode. The postcode district, for example,
SO15 .
|
name_1 string
|
Name. The proper noun that applies to the real world entity. Names that are prefixed by the definite article are not formatted for alphabetical sorting, that is, ‘The Pennines’ not ‘Pennines, The’. |
name_1_lang string|null
|
Language of Name. The language type is only set
where more than one name exists, e.g. cym (Welsh),
eng (English), gla (Scottish Gaelic).
|
name_2 string|null
|
Name (in case of multiple languages). The proper noun that applies to the real world entity. Names that are prefixed by the definite article are not formatted for alphabetical sorting, that is, ‘The Pennines’ not ‘Pennines, The’. |
name_2_lang string|null
|
Language of Name. The language type is only set where more than one name exists, e.g. cym (Welsh), eng (English), gla (Scottish Gaelic). |
county_unitary string|null
|
Administrative Area. The name of the County (non-metropolitan or Metropolitan), Unitary Authority or Greater London Authority administrative area that the point geometry for feature is within or nearest to. |
county_unitary_type string|null
|
Administrative Area Type. Classifies the type of administrative unit. |
district_borough string|null
|
District or Borough. The name of the District, Metropolitan District or London Borough administrative unit that the point geometry for the feature is within. |
district_borough_type string|null
|
Borough Type. Classifies the type of administrative unit. |
region string
|
Region. The name of the European Region (was Government O ice Region) that the point geometry for the feature is within or nearest to. |
This uniquely identifies a postcode.
Returns a single postcode entity for a given postcode (case, space insensitive).
If no postcode is found it returns "404" response code.
GEThttps://api.postcodes.io/postcodes/:postcode
Accepts a JSON object containing an array of postcodes. Returns a list of matching postcodes and respective available data.
Be sure to submit JSON requests setting Content-Type
to
application/json
Accepts up to 100 postcodes.
POSThttps://api.postcodes.io/postcodes
This method requires a JSON object containing an array of postcodes to be posted, e.g.
{ "postcodes" : ["PR3 0SG", "M45 6GN", "EX165BL"] }
filter=
(not required) A comma separated whitelist of
attributes to be returned in the result object(s), e.g.
filter=postcode,longitude,latitude
.
null
responses will continue to return null
.
If no attributes match the result object, an empty object is returned
Returns nearest postcodes for a given longitude and latitude.
GEThttps://api.postcodes.io/postcodes?lon=:longitude&lat=:latitude
limit=
(not required) Limits number of postcodes matches to
return. Defaults to 10. Needs to be less than 100.
radius=
(not required) Limits number of postcodes matches
to return. Defaults to 100m. Needs to be less than 2,000m.
widesearch=
(not required) Search up to 20km radius, but
subject to a maximum of 10 results. Since lookups over a wide area can
be very expensive, we've created this method to allow you choose to make
the trade off between search radius and number of results. Defaults to
false. When enabled, radius and limits over 10 are ignored.
distance
Distance in metres from specified postode
Note that the old style of reverse geocoding (including optional headers above) will still be supported. Namely,
GEThttps://api.postcodes.io/postcodes/lon/:longitude/lat/:latitude
Bulk translates geolocations into Postcodes. Accepts up to 100 geolocations.
POSThttps://api.postcodes.io/postcodes
limit=
(not required) Applies a global limit parameter to all geolocation lookup objects. Defaults to 10. Needs to be less than 100.
radius=
(not required) Applies a global search radius to all geolocation lookup objects. Defaults to 100m. Needs to be less than 2,000m.
widesearch=
(not required) Applies a global widesearch parameter to all geolocation lookup objects. Defaults to `false`.
This method requires a JSON object containing an array of geolocation objects to be POSTed. Each geolocation object accepts an optional radius (metres) and limit argument. Both default to 100m and 10 respectively. It also accepts a widesearch argument, e.g.
{ "geolocations" : [{ "longitude" : -3.15807731271522, "latitude" : 51.4799900627036 },{ "longitude" : -1.12935802905177, "latitude" : 50.7186356978817, "limit" : 100, "radius" : 500 }] }
filter=
(not required) A comma separated whitelist of
attributes to be returned in the result object(s). e.g.
filter=postcode,longitude,latitude
.
null
responses will continue to return null
.
If no attributes match the result object, an empty object is returned
widesearch=
(not required) Search up to 20km radius, but
subject to a maximum of 10 results
distance
Distance in metres from specified postode
Submit a postcode query and receive a complete list of postcode matches and all associated postcode data.
This is essentially a postcode search which prefix matches and returns postcodes in sorted order (case insensitive)
This method is space sensitive, i.e. it detects for spaces between outward and inward parts of the postcode (some examples detailed in this issue)
The result set can either be empty or populated with up to 100 postcode entities. Either way it will always return a 200 response code
GEThttps://api.postcodes.io/postcodes?q=[query]
query=
(not required) aliases toq=
limit=
(not required) Limits number of postcodes matches to
return. Defaults to 10. Needs to be less than 100.
Convenience method to validate a postcode. Returns true or false (meaning valid or invalid respectively)
GEThttps://api.postcodes.io/postcodes/:postcode/validate
View our guide on postcode validation to see a more detailed explanation
Returns nearest postcodes for a given postcode.
GEThttps://api.postcodes.io/postcodes/:postcode/nearest
limit=
(not required) Limits number of postcodes matches to
return. Defaults to 10. Needs to be less than 100.
radius=
(not required) Limits number of postcodes matches
to return. Defaults to 100m. Needs to be less than 2,000m.
distance
Distance in metres from specified postode
Convenience method to return an list of matching postcodes.
GEThttps://api.postcodes.io/postcodes/:postcode/autocomplete
limit=
(not required) Limits number of postcodes matches to
return. Defaults to 10. Needs to be less than 100.
Returns a random postcode and all available data for that postcode.
GEThttps://api.postcodes.io/random/postcodes
outcode=
(not required) Filters random postcodes by
outcode. Returns null if invalid outcode.
Geolocation data for the centroid of the outward code specified. The outward code represents the first half of any postcode (separated by a space).
GEThttps://api.postcodes.io/outcodes/:outcode
Returns nearest outcodes for a given longitude and latitude.
GEThttps://api.postcodes.io/outcodes?lon=:longitude&lat=:latitude
limit=
(not required) Limits number of postcodes matches to
return. Defaults to 10. Needs to be less than 100.
radius=
(not required) Limits number of postcodes matches
to return. Defaults to 5,000m. Needs to be less than 25,000m.
Returns nearest outcodes for a given outcode.
GEThttps://api.postcodes.io/outcodes/:outcode/nearest
limit=
(not required) Limits number of postcodes matches to
return. Defaults to 10. Needs to be less than 100.
radius=
(not required) Limits number of postcodes matches
to return. Defaults to 5,000m. Needs to be less than 25,000m.
Lookup a Scottish postcode. Returns SPD data associated with postcode. At the moment this is just Scottish Parliamentary Constituency.
Returns 404 if postcode does not exist in SPD or is not valid. For
postcodes not in SPD but in ONSPD, 404 is returned with error message
Postcode exists in ONSPD but not in SPD
.
GEThttps://api.postcodes.io/scotland/postcodes/:postcode
Lookup a terminated postcode. Returns the postcode, year and month of termination. Returns 404 if postcode does not exist in our database of terminated postcodes or not valid.
GEThttps://api.postcodes.io/terminated_postcodes/:postcode
Find a place by OSGB code (e.g. "osgb4000000074564391"). Returns all available data if found. Returns 404 if place does not exist.
GEThttps://api.postcodes.io/places/:code
Submit a place query and receive a complete list of places matches and associated data.
GEThttps://api.postcodes.io/places?q=[query]
query=
(not required) aliases toq=
limit=
(not required) Limits number of places matches to
return. Defaults to 10. Needs to be less than 100.
Returns a random place and all associated data
GEThttps://api.postcodes.io/random/places
There may be occasions where you want to host postcodes.io yourself. We've laid out instructions below on how to do this.
We currently provide 4 methods to import the necessary datasets and run the postcodes.io API application:
npm run setup
. This will download the
database and import the data from a pg_dump
into a
locally running instance of PostgreSQL.
pg_dump
. You can download the
pg_dump
and attempt to import the database yourself with
psql
or pg_restore
.
Postcodes.io can be installed using two Docker containers: the postcodes.io application container and the postcodes.io database container.
If you want to launch the postcodes.io HTTP interface and underlying
database quickly, you may do so with docker-compose
.
Clone the project repository and run docker-compose:
$ docker-compose up -d
Running the above command in your terminal will create and network the
containers. The HTTP service will be available on port
8000
.
The Postcodes.io application, which provides the HTTP interface, is
packaged as a Docker container identified on the Docker Hub as
idealpostcodes/postcodes.io
.
Example usage:
$ docker run -d -p 8000 idealpostcodes/postcodes.io
Configuration available via Environment Variables:
POSTGRES_USER
POSTGRES_PASSWORD
POSTGRES_DATABASE
POSTGRES_HOST
POSTGRES_PORT
PORT
(HTTP Port to run on)
idealpostcodes/postcodes.io.db
points to a
PostgreSQL & PostGIS
base image and preloads the latest pg_dump
in the
initialisation process.
The database Docker image is updated with new releases of the ONSPD dataset. See the Changelog for when a new dataset has been ingested.
Take Note: Upon starting a container for the first
time, PostGIS will be enabled and the pg_dump
will take
15-60s to restore depending on your system resources.
Example usage:
$ docker run -p 5432 -e POSTGRES_USER=postcodesio -e POSTGRES_DB=postcodesiodb -e POSTGRES_PASSWORD=password idealpostcodes/postcodes.io.db
As this contains the official PostreSQL base image, the available configuration environment variables are documented at: hub.docker.com/_/postgres/
Currently the install process targets Linux and macOS systems. Please let us know if you have issues on those or any other operating systems.
Postcodes.io is packaged with a script to provision PostgreSQL and download a dump of the dataset. The script will:
pg_dump
into the new
database
To run,
$ npm run setup
pg_dump
You can download a pg_dump
of the database. This is the
same dump used by the install script. The link to the latest dump can be
found in our
repository.
To setup the database from our pg_dump
download,
gunzip
and use either psql
or
pg_restore
to import the data into PostgreSQL.
For example,
$ cat postcodeiodb.sql | psql postcodesiodb
The install scripts can be linked to your shell (or can be found in the
bin/
directory). To link, navigate to
postcodes.io/
and run $ npm link
Download the latest Office for National Statistics "Postcode Lookup
Dataset". Unzip the data locally. Run the import script
$ postcodesio-onspd
passing the path to the CSV data.
$ postcodesio-onspd /path/to/data/ONSPD/Data/data.csv
Download the latest National Records Scotland "Scottish Postcode
Directory". Unzip the data locally. Run the import script
$ postcodesio-scotpd
passing the path CSV data directory.
$ postcodesio-scotpd /path/to/data
Download the latest Ordnance Survey Open Names dataset. Unzip the data
locally. Run the import script $ postcodesio-oson
passing
the path that contains the CSV data files.
$ postcodesio-oson /path/to/data/opname_csv_gb/Data/
Application configuration is documented in
the configuration README
at /config/README.md
.