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¶
Approach 1: Data Zone Classification (Recommended)¶
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