Skip to content

Scottish Government Spatial Data API Documentation

Overview

The Scottish Government provides spatial data services through spatialdata.gov.scot (hosted at maps.gov.scot). These services provide access to geographic and administrative boundary data for Scotland, including postcodes, council areas, and statistical geographies.

Base URL: https://maps.gov.scot/server/services/

Purpose in Drone Operations Application

We use this API to automatically classify flight locations as Rural or Urban based on geographic coordinates, replacing the manual Rural/Urban selection during project creation.


1. WFS Postcode Lookup Service

Service Overview

Service Type: Web Feature Service (WFS) 2.0.0 Service Name: NRS/SPD (National Records of Scotland / Scottish Postcode Directory) Endpoint: https://maps.gov.scot/server/services/NRS/SPD/MapServer/WFSServer

What is WFS?

WFS (Web Feature Service) is an OGC (Open Geospatial Consortium) standard for querying geographic features. It returns actual feature data (shapes, attributes) rather than just images.

Use Case: Find Postcode from Coordinates

Given a latitude/longitude coordinate, find the postcode area and its associated geographic data.

Request Structure

Full Example Request

https://maps.gov.scot/server/services/NRS/SPD/MapServer/WFSServer?
  SERVICE=WFS&
  VERSION=2.0.0&
  REQUEST=GetFeature&
  TYPENAMES=NRS_SPD:PostcodeUnit&
  SRSNAME=EPSG:4326&
  BBOX=56.26240011503864,-5.5617506222610125,56.26240011503864,-5.5617506222610125,EPSG:4326

URL Parameters Explained

Parameter Value Description
SERVICE WFS Specifies this is a Web Feature Service request
VERSION 2.0.0 WFS version (2.0.0 is current standard)
REQUEST GetFeature Request type - retrieves actual feature data
TYPENAMES NRS_SPD:PostcodeUnit Layer name - postcode units from NRS Scottish Postcode Directory
SRSNAME EPSG:4326 Spatial Reference System - WGS84 (standard lat/long)
BBOX lat,lon,lat,lon,EPSG:4326 Bounding box - defines search area

BBOX (Bounding Box) Parameter

Format: minLat,minLon,maxLat,maxLon,EPSG:4326

For point lookup: Use the same coordinates for min and max:

BBOX=56.26240,-5.56175,56.26240,-5.56175,EPSG:4326

For area lookup: Use different min/max coordinates:

BBOX=56.25,-5.57,56.27,-5.55,EPSG:4326

Response Format

The API returns XML in GML (Geography Markup Language) format.

Response Structure

<?xml version="1.0" encoding="utf-8"?>
<wfs:FeatureCollection xmlns:wfs="http://www.opengis.net/wfs/2.0"
                       xmlns:gml="http://www.opengis.net/gml/3.2"
                       xmlns:SPD="maps.gov.scot"
                       numberMatched="1"
                       numberReturned="1">
  <wfs:member>
    <SPD:PostcodeUnit gml:id="PostcodeUnit.142595">
      <SPD:objectid>142595</SPD:objectid>
      <SPD:postcode>PA34 4XD</SPD:postcode>
      <SPD:district>PA34</SPD:district>
      <SPD:sector>PA34 4</SPD:sector>
      <SPD:doi>01/08/1973</SPD:doi>
      <SPD:council>S12000035</SPD:council>
      <SPD:oa22>S00140557</SPD:oa22>
      <SPD:dz22>S01014331</SPD:dz22>
      <SPD:ew22>S13002520</SPD:ew22>
      <SPD:shape_leng>35386.93547170</SPD:shape_leng>
      <SPD:shape>
        <gml:MultiSurface>
          <gml:surfaceMember>
            <gml:Polygon>
              <gml:exterior>
                <gml:LinearRing>
                  <gml:posList>
                    56.29083940 -5.52476249
                    56.28951273 -5.52303961
                    ... [polygon coordinates]
                  </gml:posList>
                </gml:LinearRing>
              </gml:exterior>
            </gml:Polygon>
          </gml:surfaceMember>
        </gml:MultiSurface>
      </SPD:shape>
    </SPD:PostcodeUnit>
  </wfs:member>
</wfs:FeatureCollection>

Key Response Fields

Field Example Description
SPD:postcode PA34 4XD Full postcode (unit level)
SPD:district PA34 Postcode district
SPD:sector PA34 4 Postcode sector
SPD:council S12000035 Local authority code (Argyll and Bute)
SPD:oa22 S00140557 Output Area code (2022 census)
SPD:dz22 S01014331 Data Zone code (2022)
SPD:ew22 S13002520 Electoral Ward code (2022)
SPD:shape GML Polygon Geographic boundary shape

Council Area Codes

The SPD:council field contains GSS (Government Statistical Service) codes for Scottish local authorities:

Code Council Area
S12000033 Aberdeen City
S12000034 Aberdeenshire
S12000041 Angus
S12000035 Argyll and Bute
S12000036 City of Edinburgh
S12000005 Clackmannanshire
S12000006 Dumfries and Galloway
S12000042 Dundee City
S12000008 East Ayrshire
S12000045 East Dunbartonshire
S12000010 East Lothian
S12000011 East Renfrewshire
S12000014 Falkirk
S12000047 Fife
S12000049 Glasgow City
S12000017 Highland
S12000018 Inverclyde
S12000019 Midlothian
S12000020 Moray
S12000013 Na h-Eileanan Siar (Western Isles)
S12000021 North Ayrshire
S12000050 North Lanarkshire
S12000023 Orkney Islands
S12000048 Perth and Kinross
S12000038 Renfrewshire
S12000026 Scottish Borders
S12000027 Shetland Islands
S12000028 South Ayrshire
S12000029 South Lanarkshire
S12000030 Stirling
S12000039 West Dunbartonshire
S12000040 West Lothian

Example Test Locations

Edinburgh City Centre (Urban)

Latitude: 55.953251
Longitude: -3.188267
Expected Postcode: EH1 area
Expected Council: S12000036 (City of Edinburgh)

Request:

https://maps.gov.scot/server/services/NRS/SPD/MapServer/WFSServer?
SERVICE=WFS&VERSION=2.0.0&REQUEST=GetFeature&
TYPENAMES=NRS_SPD:PostcodeUnit&SRSNAME=EPSG:4326&
BBOX=55.953251,-3.188267,55.953251,-3.188267,EPSG:4326

Highland Rural Area

Latitude: 56.262400
Longitude: -5.561750
Expected Postcode: PA34 4XD
Expected Council: S12000035 (Argyll and Bute)

Request:

https://maps.gov.scot/server/services/NRS/SPD/MapServer/WFSServer?
SERVICE=WFS&VERSION=2.0.0&REQUEST=GetFeature&
TYPENAMES=NRS_SPD:PostcodeUnit&SRSNAME=EPSG:4326&
BBOX=56.262400,-5.561750,56.262400,-5.561750,EPSG:4326


Implementation Notes

Python Example

import requests
import xml.etree.ElementTree as ET

def lookup_postcode(latitude, longitude):
    """
    Lookup postcode and council area from coordinates.

    Args:
        latitude (float): Latitude in WGS84 (EPSG:4326)
        longitude (float): Longitude in WGS84 (EPSG:4326)

    Returns:
        dict: {
            'postcode': str,
            'council_code': str,
            'district': str,
            'data_zone': str
        }
    """
    base_url = "https://maps.gov.scot/server/services/NRS/SPD/MapServer/WFSServer"

    params = {
        'SERVICE': 'WFS',
        'VERSION': '2.0.0',
        'REQUEST': 'GetFeature',
        'TYPENAMES': 'NRS_SPD:PostcodeUnit',
        'SRSNAME': 'EPSG:4326',
        'BBOX': f'{latitude},{longitude},{latitude},{longitude},EPSG:4326'
    }

    response = requests.get(base_url, params=params)
    response.raise_for_status()

    # Parse XML response
    root = ET.fromstring(response.content)

    # Define namespaces
    ns = {
        'wfs': 'http://www.opengis.net/wfs/2.0',
        'SPD': 'maps.gov.scot'
    }

    # Extract data
    member = root.find('.//wfs:member', ns)
    if member is None:
        return None

    return {
        'postcode': member.find('.//SPD:postcode', ns).text,
        'council_code': member.find('.//SPD:council', ns).text,
        'district': member.find('.//SPD:district', ns).text,
        'data_zone': member.find('.//SPD:dz22', ns).text
    }

# Usage
result = lookup_postcode(55.953251, -3.188267)
print(result)
# {'postcode': 'EH1 1YZ', 'council_code': 'S12000036', ...}

Error Handling

  • No results (numberReturned="0"): Coordinates outside Scotland or in unpopulated area
  • Multiple results: Coordinates on boundary between postcodes (rare)
  • HTTP errors: Network issues, service downtime
  • Invalid coordinates: Lat/lon outside valid ranges

Performance Considerations

  • Response time: Typically 200-500ms
  • Rate limiting: Not officially documented, use reasonable request rates
  • Caching: Cache results by rounded coordinates to reduce API calls
  • Timeout: Set 5-10 second timeout on requests

Next Steps for Rural/Urban Classification

Use the SPD:dz22 (Data Zone) code to look up urban/rural classification from Scottish Government's Urban Rural Classification dataset.

Pros: - Official government classification - Already categorised into 8-fold or 6-fold classifications - Matches operational definitions

Cons: - Requires additional API call or reference data - More complex implementation

Approach 2: Council-Based Classification

Classify entire council areas as predominantly urban or rural.

Pros: - Simple lookup table - Single API call

Cons: - Overly simplistic (e.g., Highland has both urban and rural areas) - May not match operational requirements

Approach 3: Population Density Analysis

Use Scottish Government population density data for the Data Zone.

Pros: - Flexible threshold setting - Matches CAA population density requirements

Cons: - Requires additional data sources - Needs threshold calibration


References

  • Scottish Government Spatial Data: https://spatialdata.gov.scot
  • Maps.gov.scot Portal: https://maps.gov.scot
  • Scottish Postcode Directory: Part of National Records of Scotland (NRS)
  • WFS Standard: https://www.ogc.org/standards/wfs
  • EPSG:4326: WGS84 geographic coordinate system (standard GPS coordinates)

Version History

Date Version Changes
2025-12-28 1.0 Initial documentation - WFS Postcode Lookup

TODO: Additional Services to Document

  • [ ] Urban Rural Classification API
  • [ ] Scottish Government Statistics API for population density
  • [ ] Council boundary lookups
  • [ ] Integration with CAA airspace data