UK Postcode lookup API. Wrapper for API uses Royal Mail's Postcode Address File (PAF). Node.js Library

Ideal Postcodes is a simple JSON API to query UK postcodes and addresses. Find out more at

Our API is based off Royal Mail's Postcode Address File and is updated daily. Each convenience method incurs a small charge (typically 2p) - free methods are labelled as free and based off open data sources.


$ npm install ideal-postcodes

Create a Key

Sign up at and create a key.


Include your api key when requiring the ideal-postcodes module. This will return an client, which can be used to perform various tasks on the API such as looking up a postcode.

var idealPostcodes = require("ideal-postcodes")("your_key_goes_here")

Each client instance provides a number of convenience methods to allow you to get specific jobs done quickly and easily. These convenience methods are listed below:

Get all addresses for a postcode (docs)

Retrieve a complete list of addresses at a given postcode.

idealPostcodes.lookupPostcode(postcode, callback)
  • postcode (string). The postcode to search.
  • callback (function). Standard callback which accepts 2 arguments: error and addresses

Use the postcode "ID1 1QD" to test integration for free. The complete list of test postcodes is available in the documentation. Note that this method returns an empty array if no matching postcode is found.

idealPostcodes.lookupPostcode("ID1 1QD", function (erroraddresses) {
    if (error) {
        // Implement some error handling 
//  [ { 
//          postcode: 'ID1 1QD', 
//          post_town: 'LONDON', 
//          line_1: 'Kingsley Hall', 
//          line_2: 'Powis Road', 
//          line_3: '',  
//          organisation_name: '', 
//          building_name: 'Kingsley Hall', 
//          udprn: 12345678  
//          ...and so on... 
//      }, ... 

Search for an address (docs)

This will perform a search for addresses which match your search term.

idealPostcodes.lookupAddress(searchQuery, callback)
  • searchQuery (string | object). The address to search for. If string is passed, the string is used as a search term and default settings are applied (limit 10 results, return first page). If an object is provided, this object requires a query attribute pointing to your search string. It also accepts optional limit and page attributes.
  • callback (function). Standard callback which accepts 2 arguments: error and searchResults

Use the address "ID1 1QD" to test integration for free. The complete list of test methods is available in the documentation.

idealPostcodes.lookupAddress("ID1 1QD", function (errorsearchResults) {
    if (error) {
        // Implement some error handling 
// or alternatively 
    query: "ID1 1QD",   // required 
    limit: 10,                  // optional 
    page: 0                         // optional 
}, function (errorsearchResults) {
    if (error) {
        // Implement some error handling 
// { 
//   "result":{ 
//     "total":2, 
//     "limit":10, 
//     "page":0, 
//     "hits":[{ 
//       "dependant_locality" : "", 
//       "postcode_type" : "L", 
//       "po_box" : "", 
//       "post_town" : "LONDON", 
//       "delivery_point_suffix" : "1A", 
//       "double_dependant_locality" : "", 
//       "su_organisation_indicator" : " ", 
//       "longitude" : -0.127695242183412, 
//       "department_name" : "", 
//       "district" : "Westminster", 
//       continued... 

Get nearby postcode for a given geolocation (docs)

Retrieve the nearest postcodes for a given geolocation. (Free to use)

idealPostcodes.queryLocation(location, callback)
  • location (object). Requires a longitude (number) and latitude (number) attribute. Limit (number) and radius (number) are optional.
  • callback (function). Standard callback which accepts 2 arguments: error and locations
    longitude: -0.20864,    // Required 
    latitude: 51.48994,     // Required 
    limit: 10       ,           // Optional, limits number of results 
    radius: 100                     // Optional, limits search radius 
}, function (errorlocations) {
    if (error) {
        // Implement some error handling 
//  [{ 
//      postcode: "W14 9DT", 
//      northings: 178299, 
//      eastings: 524466, 
//      longitude: -0.208644362766368, 
//      latitude: 51.4899488390558, 
//      distance: 1.029038833 
//      }, ... 

Retrieve an address using UDPRN (docs)

Retrieve the specific address for a specific UDPRN.

idealPostcodes.lookupUdprn(udprn, callback)
  • udprn (string). A number which uniquely identifies the address.
  • callback (function). Standard callback which accepts 2 arguments: error and locations

Note that this method returns null if no matching address is found. Use the test UDPRN "0" to test integration for free.

idealPostcodes.lookupUdprn(0, function (erroraddress) {
    if (error) {
        // Implement some error handling 
// { 
//  "postcode":"ID1 1QD", 
//  "postcode_inward":"IQD", 
//  "postcode_outward":"ID1", 
//  "post_town":"LONDON", 
//  "dependant_locality":"", 
//  "double_dependant_locality":"", 
//  "thoroughfare":"Barons Court Road", 
//  "dependant_thoroughfare":"", 
//  "building_number":"2", 
//  "building_name":"", 
//  "sub_building_name":"", 
//  "po_box":"", 
//  "department_name":"", 
//  "organisation_name":"", 
//  "udprn":25962203, 
//  "postcode_type":"S", 
//  "su_organisation_indicator":"", 
//  "delivery_point_suffix":"1G", 
//  "line_1":"2 Barons Court Road", 
//  "line_2":"", 
//  "line_3":"", 
//  "premise":"2", 
//  "county": "", 
//  "district": "Hammersmith and Fulham", 
//  "ward": "North End", 
//  "longitude":-0.208644362766368, 
//  "latitude":51.4899488390558, 
//  "eastings":524466, 
//  "northings":178299 
// }    

Listed below are free utility methods, e.g. finding the status of your key.

Find out if your key is in a usable state (docs)

Find out if your key is in a usable state. E.g. it has a positive balance, it is currently under your defined usage limits, etc.

  • callback (function). Standard callback which accepts 2 arguments: error and key. Key contains a boolean available attribute which indicates whether your key is currently usable.
idealPostcodes.keyAvailability(function (errorkey) {
    if (error) {
        // Implement some error handling 
    console.log(key.avaialble); // => true   

Find out private key information (docs)

This method reveals private information about your key such as the lookup balance, whitelisted URLs, etc. It requires a secret key to be invoked.

  • callback (function). Standard callback which accepts 2 arguments: error and key.
idealPostcodes.keyDetails(function (errorkey) {
    if (error) {
        // Implement some error handling 
// { 
//   "lookups_remaining": 8288, 
//   "daily_limit": { 
//       "limit": 1000, 
//       "consumed": 361 
//   }, 
//   "individual_limit": { 
//       "limit": 15 
//   }, 
//   "allowed_urls": [ 
//       "", 
//       "" 
//   ], 
//   "notifications": { 
//       "emails": [""], 
//       "enabled": true 
//   }, 
//       "automated_topups": { 
//       "enabled": true 
//   } 
// } 

If you intend to use this method, you must pass your secret key (which can be found on your account page) along with your API key when instantiating the client. E.g.

var idealPostcodes = require("ideal-postcodes")("your_key_goes_here", "secret_key_goes_second");

Each convenience method adopts the standard javascript error handling method. I.e. Any error is passed as the first argument of the callback. E.g.

idealPostcodes.lookupPostcode("ID1 1QD", function (erroraddresses) {
    if (error) {
        // Handle your errors here 

Possible errors to look out for are listed in the documentation.

This module is also bundled with a CLI, which provides a couple of useful tools: Real-time log streaming and key information lookup.

The CLI requires global installation (potentially with sudo privileges, depending on your setup).

$ npm install -g ideal-postcodes

The idealpostcodes script will be available in your $PATH, allowing you to perform tasks in your terminal. E.g.

$ idealpostcodes logstream -k <your_key> -s <your_secret>

Typically the CLI will require you to enter your api_key and secret_key. You can store your keys as environment variables to save you from having to look them up everytime.

$ export IDEALPOSTCODES_KEY="<your_key>"
$ export IDEALPOSTCODES_SECRET="<your_secret>"
$ idealpostcodes <command>

The CLI allows you to listen for requests on your key in real-time, which details the request type and what kind of response was provided. This is ideal for integration and debugging.

Start listening to for incoming requests on your key with:

$ idealpostcodes logstream -k <your_key> -s <your_secret>
# -k and -s flags can be omitted if your environment variables are defined

Available poptions for $ idealpostcodes logstream

$ idealpostcodes logstream --json # Output logs as single line JSON objects
$ idealpostcodes logstream --quiet # Stops meta information such as connection, reconnection or disconnect messages from being written to stdout

Since the CLI writes to stdout, you can pipe the output to perform a range of tasks in your terminal. Some examples...

$ idealpostcodes logstream > idealpostcodes.log # Write the output to a file
$ idealpostcodes logstream | grep 'IP Address' # Write the IP address of incoming requests to console
$ idealpostcodes logstream --json --quiet | # Process raw JSON logs in a script

You can also quickly check information on your key via your terminal.

$ idealpostcodes info -k <your_key> -s <your_secret>


  • Fix CLI bug for 304 responses with 0 Content Body


  • CLI Bug Fixes.


  • Implemented command line interfance to stream key logs in real-time and view key information.




  • Major rewrite to make way for more convenience methods
  • Implemented postcodes resource. Added location-based postcode searches
  • Overhauled test suite

More documentation can be found here