Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...










# Define your bounding box
bbox = [-314177.76517933805,6641680.87433119,-304909.7754997604,6653318.411887609] # Example: Glastonbury Canal
# Initialize an empty list to collect all features
all_features = []
# Loop through 20 pages
for page in range(20):
offset = page * 100 # Calculate the offset based on the page number
params = {
"key": api_key,
"bbox": ",".join(map(str, bbox)),
"limit": 100,
"offset": offset,
"bbox-crs": "http://www.opengis.net/def/crs/EPSG/0/3857",
"crs": "http://www.opengis.net/def/crs/EPSG/0/3857",
}
# Send a request to the OS NGD API - Features
response = requests.get(f"{base_url}/collections/{collection}/items", params=params)
# Check if the request was successful
if response.status_code == 200:
data = response.json()
features = data.get("features", [])
all_features.extend(features)
if len(features) < params["limit"]: # Stop as there are no more features to retrieve
break
else:
print(f"Error: {response.status_code}")
break # Stop the loop in case of an error# Extract the geometries and attributes for each feature
geometry = [shape(feature["geometry"]) for feature in all_features]
attributes = [feature["properties"] for feature in all_features]
# Create a GeoDataFrame from the geometries and attributes
gdf = gpd.GeoDataFrame(attributes, geometry=geometry)
# Set the CRS of the GeoDataFrame to EPSG:3857 (Web Mercator)
gdf.set_crs("EPSG:3857", inplace=True)# Plot the features
gdf.plot(figsize=(12,8),facecolor="#2d8fb6", edgecolor="#b19d3e", lw=0.05)import requests
import geopandas as gpd
from shapely.geometry import shape# OS NGD API - Features API Key
api_key = "INSERT_API_KEY"
# OS NGD API - Features base URL
base_url = "https://api.os.uk/features/ngd/ofa/v1"
# OS NGD API - Features CollectionId
collection= "wtr-fts-water-2"apiKey'INSERT_API_KEY_HERE'centerzoommaxBoundsattributionControl


<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>OS NGD API – Features | Template (EPSG:3857) | Leaflet</title>
<!--Add the Ordnance Survey Styling-->
<link rel="stylesheet" href="https://cdn.jsdelivr.net/gh/OrdnanceSurvey/[email protected]/os-api-branding.css" />
<script src="https://cdn.jsdelivr.net/gh/OrdnanceSurvey/[email protected]/os-api-branding.js"></script>
<!--Add the Leaflet libraries-->
<link rel="stylesheet" href="https://unpkg.com/[email protected]/dist/leaflet.css" />
<script src="https://unpkg.com/[email protected]/dist/leaflet.js"></script>
<style>
/* Set the map container size and style */
body { margin: 0; padding: 0; }
#map { position: absolute; top: 0; bottom: 0; width: 100%; }
</style>
</head>
<body>
<!--Create a div element to hold the map-->
<div id="map"></div>
<!--Add your Javascript code below-->
<script>
// Your Javascript code will go here
</script>
</body>
</html>// Add event which will be triggered when the map has finshed moving (pan + zoom).
// Implements a simple strategy to only request data when the map viewport invalidates
// certain bounds.
map.on('moveend', function() {
let bounds1 = new L.latLngBounds(bounds.getSouthWest(), bounds.getNorthEast()),
bounds2 = map.getBounds();
if( JSON.stringify(bounds) !== JSON.stringify(bounds1.extend(bounds2)) ) {
bounds = bounds2;
fetchFeatures(bounds);
}
});// Set API Key
const apiKey = 'INSERT_API_KEY_HERE';
const collectionId= 'INSERT_COLLECTIONID_HERE';// Initialize the map.
const mapOptions = {
minZoom: 7,
maxZoom: 20,
center: [ 50.727589, -3.541809 ],
zoom: 18,
maxBounds: [
[ 49.528423, -10.76418 ],
[ 61.331151, 1.9134116 ]
],
attributionControl: false
};
const map = L.map('map', mapOptions);
// Load and display ZXY tile layer on the map.
const basemap = L.tileLayer(`https://api.os.uk/maps/raster/v1/zxy/Light_3857/{z}/{x}/{y}.png?key=${apiKey}`, {
maxZoom: 20
}).addTo(map);// Add layer group to make it easier to add or remove layers from the map.
const lyrGroup = new L.layerGroup().addTo(map);
// Define an asynchronous function to fetch and display the NGD Features API features.
async function fetchFeatures(bounds) {
// Generate a BBOX string for the map extent.
const bbox = bounds.toBBoxString();
// Construct the NGD Features API request URL.
const url = `https://api.os.uk/features/ngd/ofa/v1/collections/${collectionId}/items?key=${apiKey}&bbox=${bbox}`;
// Fetch features from the API endpoint.
const features = await fetch(url).then(response => response.json());
// Parse the GeoJSON data and display it on the map.
lyrGroup.clearLayers().addLayer(L.geoJSON(features));
}
// Get the visible map bounds (BBOX).
let bounds = map.getBounds();
// Initial fetch and display of features.
fetchFeatures(bounds);





apiKey'INSERT_API_KEY_HERE'layersviewol.loadingstrategy.bbox<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>OS NGD API – Features | Template (EPSG:3857) | OpenLayers</title>
<!--Add the Ordnance Survey Styling-->
<link rel="stylesheet" href="https://cdn.jsdelivr.net/gh/OrdnanceSurvey/[email protected]/os-api-branding.css" />
<script src="https://cdn.jsdelivr.net/gh/OrdnanceSurvey/[email protected]/os-api-branding.js"></script>
<!--Add the OpenLayers libraries-->
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/[email protected]/ol.css" />
<script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/ol.js"></script>
<style>
/* Set the map container size and style */
body { margin: 0; padding: 0; }
#map { position: absolute; top: 0; bottom: 0; width: 100%; }
</style>
</head>
<body>
<!--Create a div element to hold the map-->
<div id="map"></div>
<!--Add your Javascript code below-->
<script>
// Your Javascript code will go here
</script>
</body>
</html>// Set API Key
const apiKey = 'INSERT_API_KEY_HERE';
const collectionId= 'INSERT_COLLECTIONID_HERE';// Initialize the map object.
const map = new ol.Map({
target: 'map',
layers: [
new ol.layer.Tile({
source: new ol.source.XYZ({
url: `https://api.os.uk/maps/raster/v1/zxy/Light_3857/{z}/{x}/{y}.png?key=${apiKey}`
})
})
],
view: new ol.View({
projection: 'EPSG:3857',
extent: ol.proj.transformExtent([ -10.76418, 49.528423, 1.9134116, 61.331151 ], 'EPSG:4326', 'EPSG:3857'),
minZoom: 7,
maxZoom: 20,
center: ol.proj.fromLonLat([ -3.541809, 50.727589 ]),
zoom: 18
})
});// Create the NGD Features API layer (with BBOX strategy).
const ngdFeatures = new ol.layer.Vector({
source: new ol.source.Vector({
format: new ol.format.GeoJSON(),
url: function(extent) {
return (
`https://api.os.uk/features/ngd/ofa/v1/collections/${collectionId}/items?key=${apiKey}&bbox=${extent.join(',')}&bbox-crs=http://www.opengis.net/def/crs/EPSG/0/3857`
);
},
strategy: ol.loadingstrategy.bbox
})
});
// Add the NGD Features API layer to the map.
map.addLayer(ngdFeatures);<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>OS NGD API – Features | Template (EPSG:3857) | Maplibre GL JS</title>
<!--Add the Ordnance Survey Styling-->
<link rel="stylesheet" href="https://cdn.jsdelivr.net/gh/OrdnanceSurvey/[email protected]/os-api-branding.css" />
<script src="https://cdn.jsdelivr.net/gh/OrdnanceSurvey/[email protected]/os-api-branding.js"></script>
<!--Add the Maplibre GL JSlibraries-->
<link rel="stylesheet" href="https://unpkg.com/[email protected]/dist/maplibre-gl.css" />
<script src="https://unpkg.com/[email protected]/dist/maplibre-gl.js"></script>
<style>
/* Set the map container size and style */
body { margin: 0; padding: 0; }
#map { position: absolute; top: 0; bottom: 0; width: 100%; }
</style>
</head>
<body>
<!--Create a div element to hold the map-->
<div id="map"></div>
<!--Add your Javascript code below-->
<script>
// Your Javascript code will go here
</script>
</body>
</html>// Set API Key
const apiKey = 'INSERT_API_KEY_HERE';
const collectionId= 'INSERT_COLLECTIONID_HERE';// Create a map style object using the ZXY service.
const style = {
"version": 8,
"sources": {
"raster-tiles": {
"type": "raster",
"tiles": [`https://api.os.uk/maps/raster/v1/zxy/Light_3857/{z}/{x}/{y}.png?key=${apiKey}`],
"tileSize": 256
}
},
"layers": [{
"id": "os-maps-zxy",
"type": "raster",
"source": "raster-tiles"
}]
};
// Initialize the map object.
const map = new maplibregl.Map({
container: 'map',
minZoom: 6,
maxZoom: 19,
style: style,
maxBounds: [
[-10.76418, 49.528423],
[1.9134116, 61.331151]
],
center: [-3.541809, 50.727589],
zoom: 17
});
map.dragRotate.disable(); // Disable map rotation using right click + drag.
map.touchZoomRotate.disableRotation(); // Disable map rotation using touch rotation gesture.
// Add navigation control (excluding compass button) to the map.
map.addControl(new maplibregl.NavigationControl({
showCompass: false
}));let layers = [ 'polygon', 'linestring', 'point' ];
// Create an empty GeoJSON FeatureCollection.
const geoJson = {
"type": "FeatureCollection",
"features": []
};
// Define an asynchronous function to fetch and display the NGD Features API features.
async function fetchFeatures(bounds) {
// Generate a BBOX string for the map extent.
const bbox = bounds.toArray().toString();
// Construct the NGD Features API request URL.
const url = `https://api.os.uk/features/ngd/ofa/v1/collections/${collectionId}/items?&key=${apiKey}&bbox=${bbox}`;
// Fetch features from the API endpoint.
const features = await fetch(url).then(response => response.json());
// Update the source data with the new GeoJSON data.
layers.forEach((element) => map.getSource(element).setData(features))
}map.on('load', () => {
// Add a fill style layer to render polygons on the map.
map.addLayer({
"id": "polygon",
"type": "fill",
"source": {
"type": "geojson",
"data": geoJson
},
"layout": {},
"paint": {
"fill-color": "rgba(51,136,255,0.3)",
"fill-outline-color": "#38f"
},
"filter": [ "==", "$type", "Polygon" ]
});
// Add a line style layer to render linestrings on the map.
map.addLayer({
"id": "linestring",
"type": "line",
"source": {
"type": "geojson",
"data": geoJson
},
"layout": {},
"paint": {
"line-color": "#38f",
"line-width": 1
},
"filter": [ "==", "$type", "LineString" ]
});
// Add a circle style layer to render points on the map.
map.addLayer({
"id": "point",
"type": "circle",
"source": {
"type": "geojson",
"data": geoJson
},
"layout": {},
"paint": {
"circle-color": "rgba(51,136,255,0.8)",
"circle-radius": 4,
"circle-stroke-color": "#fff",
"circle-stroke-width": 1
},
"filter": ["==", "$type", "Point"]
});
// Get the visible map bounds (BBOX).
let bounds = map.getBounds();
// Initial fetch and display of features.
fetchFeatures(bounds);
// Add event which will be triggered when the map has finshed moving (pan + zoom).
// Implements a simple strategy to only request data when the map viewport invalidates
// certain bounds.
map.on('moveend', function() {
let bounds1 = new maplibregl.LngLatBounds(bounds.getSouthWest(), bounds.getNorthEast()),
bounds2 = map.getBounds();
if( JSON.stringify(bounds) !== JSON.stringify(bounds1.extend(bounds2)) ) {
bounds = bounds2;
fetchFeatures(bounds);
}
});
});