LogoLogo
OS Docs HomeOS NGDOS APIs OS Download ProductsMore than MapsOS Data Hub
  • OS NGD Documentation
  • GETTING STARTED
    • OS NGD Key Benefits to Customers
    • OS NGD Core Principles
      • Terminology and access
      • File formats and naming
      • Data ordering and currency
      • COU supplies
      • Data schema versioning
      • Unique identifiers
      • Coordinate reference systems
      • Attribute information for feature types
    • OS NGD Sample Data Information
    • OS NGD Webinars, Tutorials and Case Studies
  • ACCESSING OS NGD
    • Downloading with OS Select+Build
      • Getting Started with GeoPackage
        • ArcGIS Pro
        • ArcMap
        • Cadcorp SIS
        • MapInfo Professional
        • QGIS
        • FME
        • GDAL
      • Getting Started with CSV
        • Loading CSV files
        • Processing COUs
      • Getting Started with Attribute Filtering
      • Getting Started with Temporal Filtering
    • Accessing OS NGD APIs
      • Getting started with an API project
      • OS NGD API – Features
        • What data is available?
        • Technical Specification
          • Landing page
          • Conformance
          • Collections
          • Collection
          • Schema
          • Queryables
          • Features
          • Feature
        • Getting Started
          • GIS Software
            • Cadcorp SIS
            • ESRI ArcGIS Online
            • ESRI ArcGIS Pro
            • QGIS
          • Libraries
            • Leaflet
            • MapLibre GL JS
            • OpenLayers
            • Python (Geopandas)
        • Code Examples
      • OS NGD API – Tiles
        • What data is available?
        • Technical Specification
          • Landing page
          • Conformance
          • Collections
          • Collection
          • Tile Matrix Sets
          • Tiles
          • Styles
        • Getting Started
          • GIS Software
            • Cadcorp SIS
            • QGIS
          • Libraries
            • Leaflet
            • MapLibre GL JS
            • OpenLayers
        • Code Examples
    • Additional Resources
      • Tutorials
      • Stylesheets
  • OS NGD NEWS
    • OS NGD News
    • What's New?
    • Change Log
    • OS NGD Improvements
    • Future OS NGD Data Enhancements
  • Data and Service Status
    • Data and Service Status Information
  • 🆕Live Service Disruption and Planned Maintenance
  • Current Known Data Issues
  • 🆕Resolved Data Issues
  • USING OS NGD DATA
    • OS NGD Buildings
      • Building Feature Type
      • How Building data is created
      • Building attribution
      • Known limitations
      • Summary
    • OS NGD Structures
      • Field Boundary
        • Field Boundary Feature Type
        • How Field Boundary data is created
        • Field Boundary attribution
        • Known limitations
        • Summary
    • OS NGD Transport
      • Pavements
        • Pavement polygons
        • Pavement attribution
        • Pavement Link feature type
      • Trams
        • Tram attribution on Road Link
        • Tram On Road Feature Type
        • Trams in the Rail Network
      • Street Light
        • Known limitations
    • OS NGD Land Cover Enhancements
      • Introduction
      • Habitat mapping
      • Percentage coverage
      • Cross reference table
      • Known limitations
      • Summary
    • Data Catalogue
    • FAQs
    • OS NGD Product Viewer Tool
  • DATA STRUCTURE
    • OS NGD Address
      • GB Address
        • Built Address
        • Historic Address
        • Non-Addressable Object
        • Pre-Build Address
        • Street Address
      • Islands Address
        • Built Address
        • Historic Address
        • Non-Addressable Object
        • Pre-Build Address
        • Street Address
      • Related Components
        • Alternate Address
        • Postal Address
        • Other Classification
        • Related Entity
      • Versioning information
      • GB Address Local Custodian Codes
      • Islands Address Local Custodian Codes
    • OS NGD Administrative and Statistical Units
      • Boundaries
        • Boundary High Water Mark
        • Ceremonial County
        • Country
        • Devolved Parliament Constituency
        • Devolved Parliament Electoral Region
        • Electoral Division
        • GLA Assembly Constituency
        • Historic County
        • Historic European Region
        • Lower Tier Local Authority
        • Parish Or Community
        • Polling District
        • Region
        • Regional Authority
        • Upper Tier Local Authority
        • Ward
        • Westminster Constituency
    • OS NGD Buildings
      • Building Features
        • Building
        • 🆕Building Access Location
        • Building Line
        • Building Part
    • OS NGD Geographical Names
      • Named Features
        • 🆕Crowd Sourced Name Point
        • Named Area
        • Named Point
        • Named Road Junction
    • OS NGD Land
      • Land Features
        • Land
        • Land Point
        • Landform
        • Landform Line
        • Landform Point
    • OS NGD Land Use
      • Land Use Features
        • Site
        • Site Access Location
        • ❌Site Routing Point
    • OS NGD Structures
      • Structure Features
        • Compound Structure
        • Field Boundary
        • Structure
        • Structure Line
        • Structure Point
    • OS NGD Transport
      • Routing and Asset Management Information (RAMI)
        • Average And Indicative Speed
        • Highway Dedication
        • Maintenance Area
        • Maintenance Line
        • Maintenance Point
        • Reinstatement Area
        • Reinstatement Line
        • Reinstatement Point
        • Restriction
        • Routing Hazard
        • Routing Structure
        • Special Designation Area
        • Special Designation Line
        • Special Designation Point
      • Transport Features
        • Cartographic Rail Detail
        • Rail
        • Road Line
        • Road Track Or Path
        • 🆕Street Light
      • Transport Network
        • Connecting Link
        • Connecting Node
        • Ferry Link
        • Ferry Node
        • Ferry Terminal
        • Path
        • Path Link
        • Path Node
        • Pavement Link
        • Railway Link
        • Railway Link Set
        • Railway Node
        • Road
        • Road Junction
        • Road Link
        • Road Node
        • Street
        • Tram On Road
    • OS NGD Water
      • Water Features
        • Inter Tidal Line
        • River Basin District Catchment
        • Tidal Boundary
        • Water
        • Water Point
        • Waterbody Catchment
      • Water Network
        • Water Link
        • Water Link Set
        • Water Node
  • Code Lists
    • Code Lists Overview
      • accesstypevalue
      • 🆕accesslevelvalue
      • 🆕accessmodevalue
      • 🆕accessobstructionvalue
      • 🆕accesspurposevalue
      • addressbasepostalvalue
      • addressclassificationsourcevalue
      • addressdescriptionvalue
      • addressstatusvalue
      • addressstreettypevalue
      • associatedstreetdatadescriptionvalue
      • averageandindicativespeeddescriptionvalue
      • basementpresencesourcevalue
      • boundaryhighwatermarkdescriptionvalue
      • boundarytypevalue
      • 🆕buildingaccesslocationdescriptionvalue
      • buildingageperiodvalue
      • buildingagesourcevalue
      • buildingconnectivitytypevalue
      • buildingdescriptionvalue
      • buildinglinedescriptionvalue
      • buildingpartdescriptionvalue
      • buildingpartoslandcovertieravalue
      • buildingpartoslandcovertierbvalue
      • buildingusevalue
      • buildstatusvalue
      • builtstructureheightconfidencevalue
      • capturemethodvalue
      • capturespecificationvalue
      • ceremonialcountydescriptionvalue
      • changetypevalue
      • classificationcorrelationvalue
      • compoundstructuredescriptionvalue
      • connectinglinkdescriptionvalue
      • connectingnodedescriptionvalue
      • constructionmaterialsourcevalue
      • constructionmaterialvalue
      • countryvalue
      • countrydescriptionvalue
      • 🆕crowdsourcednamedescriptionvalue
      • 🆕crowdsourcednamematchtypevalue
      • cyclefacilityvalue
      • dataentitycatalogue
      • dedicationvalue
      • devolvedparliamentconstituencydescriptionvalue
      • devolvedparliamentelectoralregiondescriptionvalue
      • electoraldivisiondescriptionvalue
      • extentoflinkvalue
      • ferrylinkdescriptionvalue
      • ferrynodedescriptionvalue
      • ferryterminaldescriptionvalue
      • fieldboundarydescriptionvalue
      • formofroadnodevalue
      • formofwaytypevalue
      • gaugevalue
      • glaassemblyconstituencydescriptionvalue
      • gssrolevalue
      • hazardtypevalue
      • heightingmethodvalue
      • highwaydedicationnetworkfeaturetypevalue
      • historiccountydescriptionvalue
      • historiceuropeanregiondescriptionvalue
      • intertidallinedescriptionvalue
      • 🆕illuminationvalue
      • junctiontypedescriptionvalue
      • landdescriptionvalue
      • landformdescriptionvalue
      • landformlinedescriptionvalue
      • landformpointdescriptionvalue
      • landoslandcovertieravalue
      • landoslandcovertierbvalue
      • landformvalue
      • landpointdescriptionvalue
      • languagevalue
      • linkdirectionvalue
      • 🆕linkreferenceconfidencevalue
      • lowertierlocalauthoritydescriptionvalue
      • maintenancevalue
      • 🆕matchedfeaturetypengdvalue
      • 🆕matchedthemengdvalue
      • matchstatusvalue
      • classificationcorrelationvalue
      • namedareaextentdefinitionvalue
      • nameddatevalue
      • nameddayvalue
      • namedescriptiongroupvalue
      • namedescriptionvalue
      • namedperiodvalue
      • namedroadjunctiondescriptionvalue
      • namedtimevalue
      • networkfeaturetypevalue
      • 🆕networknodefeaturetypevalue
      • networkoverunderbridgevalue
      • operationalstatevalue
      • operationalstatusvalue
      • oslandusetieravalue
      • oslandusetierbvalue
      • parentboundarydescriptionvalue
      • parentfeaturetypevalue
      • parishorcommunitydescriptionvalue
      • pathdescriptionvalue
      • pathnodedescriptionvalue
      • physicallevelvalue
      • 🆕physicalstatevalue
      • physicallevelvalue
      • pollingdistrictdescriptionvalue
      • positionalaccuracyvalue
      • postcodetypevalue
      • presencevalue
      • raildescriptionvalue
      • raildetaildescriptionvalue
      • railoslandcovertieravalue
      • railoslandcovertierbvalue
      • railwaylinkdescriptionvalue
      • railwaylinksetdescriptionvalue
      • railwaynodedescriptionvalue
      • railwayusevalue
      • regionalauthoritydescriptionvalue
      • regiondescriptionvalue
      • reinstatementtypevalue
      • relationshiptypevalue
      • restrictiontypedescriptionvalue
      • restrictionvalue
      • riverbasindistrictcatchmentdescriptionvalue
      • roadclassificationvalue
      • roaddescriptionvalue
      • roadfunctionvalue
      • roadlinedescriptionvalue
      • roadnodedescriptionvalue
      • roadstructurevalue
      • roadtrackorpathdescriptionvalue
      • roadtrackorpathoslandcovertieravalue
      • roadtrackorpathoslandcovertierbvalue
      • roadwidthconfidencelevelvalue
      • 🆕roofconfidenceindicatorvalue
      • 🆕roofmaterialvalue
      • 🆕roofshapevalue
      • pavementdescriptionvalue
      • sideofroadvalue
      • siteaccesslocationdescriptionvalue
      • sitedescriptionvalue
      • siteextentdefinitionvalue
      • siteroutingpointdescriptionvalue
      • sourceofmeasurevalue
      • specialdesignationtypevalue
      • stakeholdervalue
      • statusvalue
      • streetclassificationvalue
      • streetdescriptionvalue
      • streetgeometrysourcevalue
      • 🆕streetlightdescriptionvalue
      • streetstatevalue
      • streetsurfacevalue
      • streettypevalue
      • structuredescriptionvalue
      • structureoslandcovertieravalue
      • structureoslandcovertierbvalue
      • structurelinedescriptionvalue
      • structurepointdescriptionvalue
      • structuretypevalue
      • structurevalue
      • surfacetypevalue
      • themevalue
      • tidalboundarydescriptionvalue
      • trackrepresentationvalue
      • tramdescriptionvalue
      • 🆕transportfeaturetypevalue
      • uppertierlocalauthoritydescriptionvalue
      • usrnmatchindicatorvalue
      • vehiclequalifiervalue
      • warddescriptionvalue
      • waterbodycatchmentdescriptionvalue
      • waterbodycategoryvalue
      • waterdescriptionvalue
      • wateroslandcovertieravalue
      • wateroslandcovertierbvalue
      • waterlinkdescriptionvalue
      • waterlinkflowdirectionvalue
      • waterlinkgeometrysourcevalue
      • waterlinklevelofdetailvalue
      • waterlinkpermanencevalue
      • waterlinkphysicalcontainmentvalue
      • waterlinkprimacyvalue
      • waterlinksetdescriptionvalue
      • waterlinkwatertypevalue
      • watermarkvalue
      • waternodedescriptionvalue
      • waterpointdescriptionvalue
      • watertypevalue
      • westminsterconstituencydescriptionvalue
      • yesnovalue
  • EXTRA LINKS
    • Accessibility
    • Contact Us
    • Copyright
    • PSGA Product Summary
Powered by GitBook
On this page
  • What you'll need
  • What's next?

Was this helpful?

Export as PDF
  1. ACCESSING OS NGD
  2. Accessing OS NGD APIs
  3. OS NGD API – Features
  4. Getting Started
  5. Libraries

MapLibre GL JS

Accessing OS NGD API – Features via MapLibre GL JS

PreviousLeafletNextOpenLayers

Last updated 4 months ago

Was this helpful?

is a free and powerful JavaScript library for displaying interactive maps on the web. It's based on Mapbox GL JS and provides a wide range of features for creating maps with custom styles, markers and interactivity.

What you'll need

  • OS Maps API and OS NGD API – Features added to an API project in the OS Data Hub with an API Key. See for more information.

  • A text editor like Visual Studio Code or Notepad to edit and save your HTML and JavaScript files.

1

Set up your HTML file

  • Create a new HTML file with a text editor (for example, Notepad, Visual Studio Code).

  • Add the basic HTML structure to your file with a placeholder <div> for the map.

<!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/os-api-branding@0.3.1/os-api-branding.css" />
    <script src="https://cdn.jsdelivr.net/gh/OrdnanceSurvey/os-api-branding@0.3.1/os-api-branding.js"></script>
    
    <!--Add the Maplibre GL JSlibraries-->
    <link rel="stylesheet" href="https://unpkg.com/maplibre-gl@2.4.0/dist/maplibre-gl.css" />
    <script src="https://unpkg.com/maplibre-gl@2.4.0/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>
2

Insert your API Key and OS NGD collection

  • To enable access to OS APIs an API Key is required. Inside the <script> tag, add a variable called apiKey, replacing 'INSERT_API_KEY_HERE' with the API Key from your project.

  • Add a variable called collectionId, replacing 'INSERT_COLLECTIONID_HERE' with the collection ID for the desired OS NGD feature type and version (for example, bld-fts-buildingpart-1).

// Set API Key 
 const apiKey = 'INSERT_API_KEY_HERE';
 
 const collectionId= 'INSERT_COLLECTIONID_HERE';
3

Add a basemap

  • To add the OS Maps API, you will need to define the map style using MapLibre GL JS's format. This specifies the source of map tiles, which will be retrieved from OS Maps API in the 'Light' raster tiles style.

  • Initialise the map object using the maplibregl.Map class to configure the basemap layer and define its properties – container, minZoom, maxZoom, maxBounds, style, center and zoom.

  • Add navigation controls to the map, excluding the compass button and disabling map rotation.

// 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
             }));

The above code creates the main map instance using the MapLibre GL JS library where you can specify various properties:

  • container: Defines where the map should be displayed. In this instance, it is set to the id of the <div> element.

  • minZoom and maxZoom: Sets the minimum and maximum zoom level for the map. Users will not be able to go beyond these levels.

  • maxBounds: Defines the maximum bounds and restricts panning the map.

  • style: Defines the style of the map, configured via a URL pointing at the style specified.

  • center: Sets the initial centre point of the map.

  • zoom: Sets the initial zoom level of the map.

4

Add an OS NGD API – Features layer

  • Create an empty GeoJSON placeholder to hold the feature objects called by OS NGD API – Features.

  • Create a function called fetchFeatures that fetches the API based on the current map extent (bounding box) by generating a bbox string.

  • Construct the API request URL to fetch OS NGD data from OS NGD API – Features. The URL includes the collectionId, bbox and apiKey.

  • Once the features have been returned in JSON, update the source data of the map's layers to display the features.

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))
}
5

Load and update features on the map dynamically

  • Event listeners are triggered when the map loads and finishes moving (panning or zooming) to load and update features based on the map's updated extent. Inside the map.on('load',...) event handler, we add styles for various types of features, including polygons, linestrings and points so that any collectionId specified will render.

The map.on('moveend',...) event handler will then fetch and update the features based on the map's current extent.

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);
        }
    });
});

Features within the viewport extent will load initially (first 100 features) and will continue to load as you pan and zoom across the map.

What's next?

Congratulations! You've successfully created a map using MapLibre GL JS and added an OS NGD layer using OS NGD API – Features in a few steps.

Now you can continue to explore Ordnance Survey's to learn more about advanced features and functionality, such as adding markers, pop-ups, and additional layers.

MapLibre GL JS
code examples
Getting started with an API project