MapLibre GL JS

Accessing OS NGD API - Tiles via MapLibre GL JS

MapLibre GL JS 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 pf features for creating maps with custom styles, markers and interactivity.

What you'll need

  • OS NGD API - Tiles added to an API project in the OS Data Hub with an API Key.

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

Create a basic vector map

Step 1: Set Up Your HTML file

  1. Create a new HTML file with a text editor (e.g. Notepad, Visual Studio Code).

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

<!DOCTYPE html>
<html lang="en">
    <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 – Tiles | Template (EPSG:3857) | MapLibre GL JS</title>
    <!--Add the Ordnance Survey Styling-->
    <link rel="stylesheet" href="" />
    <script src=""></script>
    <!--Add the MapLibre GL JS libaries -->
     <link rel="stylesheet" href="" />
    <script src=""></script>
        /* Set the map container size and style */
        body { margin: 0; padding: 0; }
        #map { position: absolute; top: 0; bottom: 0; width: 100%; }
    <!--Create a div element to hold the map-->
    <div id="map"></div>
    <!--Add your Javascript code below--> 
        // Your Javascript code will go here



Step 2: Insert your API Key

  1. 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.

  2. Inside the <script> tag, add another variable called collectionIdwith the collection ID for the OS NGD API - Tiles base map - ngd-base

// Set API Key and collection ID
 const apiKey = 'INSERT_API_KEY_HERE';
 const collectionId = 'ngd-base';

Step 3: Adding Fetch and Response Interceptor

  • We need to intercept and customise the style request, adding a tiles property to provide a correctly formatted URL and authentication through the apiKey is enabled to ensure the correct tiles are requested.

Add the following code inside the Javascript block:

// Modify the JSON style request incorporate a `tiles` property which lists an array of tile endpoints.
// The '&key=' HTTP query parameter is also appended to each tile endpoint to authenticate the request.
// NOTE: The {z}, {x} and {y} template values are replaced with the corresponding integers at runtime.
    const { fetch: originalFetch } = window;
    window.fetch = async (...args) => {
        let [ resource, config ] = args;

        let response = await originalFetch(resource, config);
        if( response.url != `${collectionId}/styles/3857` )
            return response;

        // Response interceptor.
        const json = () =>
            response.clone().json().then((data) => {
                data.sources[ collectionId ].tiles = [ `${data.sources[ collectionId ].url}/{z}/{y}/{x}?key=${apiKey}` ];
                delete data.sources[ collectionId ].url;
                return data;

        response.json = json;
        return response;

Step 4: Create a Map and map view

  1. Initialize the map object using the maplibregl.Map class to configure the vector tile layer and define its properties - container, minZoom, maxZoom, maxBounds, style, center and zoom.

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

// Initialize the map object.
    const map = new maplibregl.Map({
        container: 'map',
        minZoom: 6,
        maxZoom: 19,
        maxBounds: [ [ -8.74, 49.84 ], [ 1.96, 60.9 ] ],
        style: `${collectionId}/styles/3857`,
        center: [ -3.541809, 50.727589 ],
        zoom: 17,
        attributionControl: false

    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 default style for the 'collectionId' defined.

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

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

What's Next

Congratulations! You've successfully created a vector map using MapLibre GL JS using the OS NGD API - Tiles in a few steps. Continue to explore Ordnance Survey's code examples to learn more about advanced features and functionality such as adding markers, pop-ups, and additional layers.

Last updated