Sample code for rooftop geocoding
This page provides sample code to help you set up Postcoder rooftop geocoding.
Copy any example below and then insert your own API key to make it work. Sign up to get an API key.
Rooftop geocoding using JavaScript
This example uses the pafaddressbase and address endpoints to look up addresses and their coordinates in the UK and Ireland. It can be customised using the config settings at the end of the HTML. The UK address lookups use PAF and AddressBase data, and the Irish address lookups use Eircode data.
class PostcoderRooftop{
constructor(config) {
this.config = config
this.init()
}
init = () => {
this.endpointGB = 'https://ws.postcoder.com/pcw/' + this.config.apikey + '/pafaddressbase/'
this.endpointIE = 'https://ws.postcoder.com/pcw/' + this.config.apikey + '/address/ie/'
this.addresses = {}
this.addresslines = 4
this.searchbutton = document.querySelector(this.config.searchbutton)
this.searchterminput = document.querySelector(this.config.searchterm)
this.addressselectioncontainer = document.querySelector(this.config.addressselectioncontainer)
//hide the no result message
this.noresultmessage = document.querySelector(this.config.noresultmessage)
this.noresultmessage.style.display = 'none'
// add an empty container to show the selected address
this.addresscontainer = document.createElement('div')
this.addresscontainer.classList.add('address')
this.addressselectioncontainer.parentNode.insertBefore(this.addresscontainer, this.addressselectioncontainer.nextSibling)
// create an empty select and place it hidden in the page
this.select = document.createElement('select')
this.select.style.display = 'none'
this.addressselectioncontainer.appendChild(this.select)
// create and append the top 'select an address' option.
let option = document.createElement('option')
option.text = 'Select an address'
this.select.appendChild(option)
// add select change event listener to the dropdown
this.select.addEventListener('change', this.handleSelectChange )
// add click event listener to the search button, to call the search function
this.searchbutton.addEventListener('click', this.search)
// add 'enter' event listener to the search input, to call the search function
this.searchterminput.addEventListener('keyup', event =>{
if (event.keyCode === 13) {
event.preventDefault()
this.search()
}
})
// initalise an OpenLayers map and marker, on London
window.onload = (event) => {
const london = ol.proj.fromLonLat([-0.12755, 51.507222])
this.view = new ol.View({
center: london,
zoom: 9,
})
this.map = new ol.Map({
target: this.config.mapcontainer,
controls: ol.control.defaults({ attribution: false }),
layers: [
new ol.layer.Tile({
source: new ol.source.OSM()
})
],
view: this.view,
})
this.markerlayer = new ol.layer.Vector({
source: new ol.source.Vector(),
style: new ol.style.Style({
image: new ol.style.Icon({
anchor: [0.5, 1],
src: 'https://postcoder.com/images/svg/map-pin.svg'
})
})
})
this.map.addLayer(this.markerlayer)
this.marker = new ol.Feature(new ol.geom.Point(london))
this.markerlayer.getSource().addFeature(this.marker)
}
}
handleSelectChange = event => {
// check to see if this selection was to load the next page of results
if( this.select.value.charAt(0) === 'p'){
// search the next page of results
let page = this.select.value.substring(1)
this.search(event, page)
}else{
this.selectAddress( this.select.value )
}
}
search = (event, page = 0) => {
let searchterm = encodeURIComponent(this.searchterminput.value)
//hide the no result message
this.noresultmessage.style.display = 'none'
// hide the select
this.select.style.display = 'none'
//determine the country
if(typeof this.config.countrycode !== 'undefined' && this.config.countrycode !== ''){
// defined in config
var country = this.config.countrycode
}else{
// get from dropdown
var country = document.querySelector(this.config.country).value
}
// if page 0, remove any previous options
if(page === 0){
while (this.select.options.length > 1) {
this.select.remove(1)
}
}else{
// remove the bottom 'next page' option
this.select.remove(this.select.options.length - 1)
}
// different endpoint for GB and IE
if( country == 'IE'){
var url = this.endpointIE + searchterm + '?lines='+this.addresslines + '&addtags=latitude,longitude&exclude=organisation,country&page=' + page
}else{
var url = this.endpointGB + searchterm + '?lines='+this.addresslines + '&exclude=organisation,country&page=' + page
}
// fetch the json formatted result from Postcoder and pass it to processResult
fetch(url)
.then( response => {
if (!response.ok) {
throw response
}
return response.json()
})
.then( json => {
this.processResult(json)
})
.catch( err => {
if(typeof err.text === 'function'){
err.text().then( errorMessage => {
console.log('Postcoder request error ' + err.status + ' : ' + errorMessage)
})
}else{
console.log(err)
}
})
}
processResult = addresses =>{
this.addresses = addresses
//if zero results, ask for manual address entry
if( addresses.length === 0 ){
//show the no result message
this.noresultmessage.style.display = 'block'
}
// if one result, populate the form
else if(addresses.length === 1){
this.selectAddress(0)
}
// multiple addresses, show drop down to select from
else{
// create and append the address options, using the summaryline of the returned addresses
for (let i = 0; i < addresses.length; i++) {
let option = document.createElement('option')
option.value = i
option.text = addresses[i].summaryline
this.select.appendChild(option)
}
// if there are morevalues, add paging
if(this.addresses[this.addresses.length - 1]['morevalues'] === 'true'){
// add a 'load next page' option
let option = document.createElement('option')
option.value = 'p' + this.addresses[this.addresses.length - 1]['nextpage']
// last address contains total number of results, show the user how many are remaining
let remainingresults = this.addresses[this.addresses.length - 1]['totalresults'] - this.select.options.length + 1
option.text = 'Load more results, ' + remainingresults + ' of ' + this.addresses[this.addresses.length - 1]['totalresults'] + ' remaining'
this.select.appendChild(option)
}
// ensure the select is visible
this.select.style.display = 'block'
}
}
selectAddress = i =>{
// get the selected address
let address = this.addresses[i]
let fields = ['organisation','addressline1','addressline2','addressline3','addressline4','posttown','county','postcode']
let displayaddress = ''
// display the selected adress in the address container
for (let i = 0; i < fields.length; i++) {
if(typeof address[fields[i]] !== 'undefined'){
displayaddress += address[fields[i]] + '<br>'
}
}
this.addresscontainer.innerHTML = displayaddress
this.showMap( i )
}
showMap = i =>{
// get the selected address
let address = this.addresses[i]
if(address.latitude && address.longitude){
let position = ol.proj.fromLonLat([address.longitude, address.latitude])
this.view.animate({
center: position,
zoom: 18,
duration: 2000,
})
this.marker.getGeometry().setCoordinates(position)
}
}
}
<!doctype html>
<html lang="en">
<head>
<link rel="stylesheet" href="postcoder.css" >
<script src="postcoder_rooftop.js"></script>
<!-- using OpenLayers map -->
<script src="https://cdn.jsdelivr.net/gh/openlayers/openlayers.github.io@master/en/v6.9.0/build/ol.js"></script>
</head>
<body>
<form>
<label for="txt_country">Country</label>
<select id="txt_country">
<option value="IE">Ireland</option>
<option value="GB" selected>Great Britian</option>
</select>
<label for="txt_search">Search for an address or postcode</label>
<button type="button" id="btn_search">
Search
</button>
<div class="search_wrap">
<input id="txt_search" type="search" autocomplete="off" autocapitalize="off" >
</div>
<div id="address_selection_container"></div>
<div id="no_result_message">
Address not found, please enter manually.
</div>
<div id="map" class="map"></div>
</form>
<script>
new PostcoderRooftop({
apikey: 'PCW45-12345-12345-1234X',
searchterm: '#txt_search', // query selector of the searchterm input field
addressselectioncontainer: '#address_selection_container', // container for the address selection drop down
noresultmessage: '#no_result_message',
country: '#txt_country', // Country select list; leave blank if not using a country select list
countrycode: '', // Hard code if not using a country select list; leave blank otherwise
searchbutton: '#btn_search',
mapcontainer: 'map' // id for the map container
})
</script>
</body>
</html>
input, select {
display: block;
box-sizing: border-box;
width: 100%;
padding: 10px;
height: 40px;
margin-bottom: 0.5em;
border-width: 1px;
border-style: solid;
border-color: lightgray;
}
.search_wrap {
overflow: hidden;
}
.search_wrap div {
font-size: 0.75em;
}
button {
padding: 8px;
margin-left: 0.5em;
float: right;
font-family: sans-serif;
}
label {
display: block;
margin-top: 1.25em;
margin-bottom: 0.25em;
}
select {
position: relative;
z-index: 1;
padding-right: 40px;
}
.isvalid:after {
content: '\2713';
color: green;
}
.notvalid:after {
content: '\2717';
color: red;
}
#successindicator {
float: right;
margin-left: 0.5em;
display: flex;
justify-content: center;
align-content: center;
flex-direction: column;
height: 40px;
}
#json_result_container {
margin: 5em 0 0;
background-color: #eee;
color: #333;
/* border: solid lightgrey 1px; */
padding: 1em;
overflow: auto;
}
#autocomplete_wrap{
position: relative;
}
#suggestion_list{
position: absolute;
background-color: #fff;
outline: -webkit-focus-ring-color auto 1px;
list-style-type: none;
margin: 0;
padding: 0;
max-height: 400px;
overflow-y: auto;
}
#suggestion_list li{
cursor: pointer;
padding: 10px 5px;
}
#suggestion_list li.header{
border-bottom: 2px solid #ddd;
}
#suggestion_list li:hover, #suggestion_list li.selected{
background-color: #ddd;
}
#suggestion_list li span.location{
font-size: 0.75em;
color: #666;
}
.arrow {
border: solid black;
border-width: 0 3px 3px 0;
display: inline-block;
padding: 3px;
}
.left {
margin-left: 3px;
transform: rotate(135deg);
-webkit-transform: rotate(135deg);
}
.address{
height: 140px;
margin: 8px;
}
.map {
height: 300px;
width: 100%;
}
body {
font-family: sans-serif;
padding: 0;
margin: 0;
}
Rooftop geocoding using Python, PHP or C#
These examples show how to make a request to the pafaddressbase endpoint to look up a UK address and its coordinates.
AddressBase: Enable access on your API key using the Features page or by contacting us.
from urllib.parse import quote
import requests
import json
# Request parameters
api_key = "PCW45-12345-12345-1234X"
search_term = "NR1 4DH"
# Prepare request and encode user-entered parameters with %xx encoding
request_url = f"https://ws.postcoder.com/pcw/{api_key}/pafaddressbase/{quote(search_term, safe='')}"
# Send request
response = requests.get(request_url)
# Process response
if response.status_code == 200:
json = response.json()
if len(json) > 0:
for address in json:
print(address["summaryline"], address["latitude"], address["longitude"])
else:
print("No results")
else:
print(f"Request error: {response.content.decode()}")
// Request parameters
$api_key = "PCW45-12345-12345-1234X";
$search_term = "NR1 4DH";
// Prepare request and encode user-entered parameters with %xx encoding
$request_url = "https://ws.postcoder.com/pcw/$api_key/pafaddressbase/" . urlencode($search_term);
// Send request
$result = file_get_contents($request_url, false, stream_context_create(["http" => ["ignore_errors" => true]]));
// Process response
$status_line = $http_response_header[0];
preg_match("{HTTP\/\S*\s(\d{3})}", $status_line, $match);
$status_code = $match[1];
if ($status_code == 200) {
$json = json_decode($result);
if (count($json) > 0) {
foreach ($json as $address) {
echo("$address->summaryline $address->latitude $address->longitude <br>");
}
} else {
echo("No results");
}
} else {
echo("Request error");
}
using System;
using System.Threading.Tasks;
using System.Web;
using System.Net.Http;
using Newtonsoft.Json.Linq;
public class Program
{
public static async Task Main()
{
// Request parameters
string apiKey = "PCW45-12345-12345-1234X";
string searchTerm = "NR1 4DH";
// Prepare request and encode user-entered parameters with %xx encoding
string requestUrl = $"https://ws.postcoder.com/pcw/{apiKey}/pafaddressbase/{HttpUtility.UrlEncode(searchTerm)}";
using (HttpClient client = new HttpClient())
{
// Send request
var response = await client.GetAsync(requestUrl);
var responseContent = await response.Content.ReadAsStringAsync();
// Process response
if (response.IsSuccessStatusCode)
{
JArray responseJson = JArray.Parse(responseContent);
if (responseJson.Count > 0)
{
foreach (JObject address in responseJson)
{
Console.WriteLine($"{address["summaryline"]}, {address["latitude"]}, {address["longitude"]}");
}
}
else
{
Console.WriteLine("No results");
}
}
else
{
Console.WriteLine($"Request error: {responseContent}");
}
}
}
}