> For the complete documentation index, see [llms.txt](https://docs.mapbox.com/help/llms.txt)

# Use Mapbox APIs in MapLibre GL JS

[MapLibre GL JS](https://maplibre.org/maplibre-gl-js/docs/) is an open-source fork of Mapbox GL JS that implements the [Mapbox Style Specification](https://docs.mapbox.com/style-spec/reference/). Because it shares the same API surface and style format, it integrates with Mapbox raster and vector tile APIs, and with most Mapbox services, using familiar patterns.

> **Note: For full Mapbox ecosystem support, use Mapbox GL JS**
> 
> [Mapbox GL JS](https://docs.mapbox.com/mapbox-gl-js/guides/) is the recommended library for building web maps with Mapbox. It provides first-class support for the full Mapbox ecosystem — including vector tile rendering, Mapbox Standard styles, Search JS, and Navigation SDKs — and is actively developed alongside Mapbox APIs.
> 
> That said, Mapbox's core Maps services use open standards: raster tile URLs follow the XYZ/TMS convention, vector tiles use the [Mapbox Vector Tile specification](https://docs.mapbox.com/data/tilesets/guides/vector-tiles-standards/), and Navigation and Search APIs return standard GeoJSON. This makes them interoperable with third-party mapping libraries and GIS software that support these formats.

## Access tokens

All Mapbox APIs require an access token for authentication. Your token is passed as the `access_token` query parameter on every request.

You can find your default public token — or create a new one with specific scopes — on the [Access tokens page](https://console.mapbox.com/account/access-tokens/) in the Mapbox Developer Console. Public tokens start with `pk.`.

```
https://api.mapbox.com/styles/v1/mapbox/streets-v12/tiles/512/{z}/{x}/{y}@2x?access_token=YOUR_ACCESS_TOKEN
```

When using Mapbox APIs in a client-side web application, use a **public token** with URL restrictions configured to your domain, so the token can't be used by other sites. See [How to use Mapbox securely](https://docs.mapbox.com/help/dive-deeper/how-to-use-mapbox-securely/) for guidance on restricting tokens and avoiding exposure.

MapLibre does not natively resolve `mapbox://` scheme URIs — instead, use direct HTTPS tile URLs in your source definitions. The examples below use the Mapbox APIs' standard HTTPS endpoints.

## Vector tiles with custom style

MapLibre natively supports the Mapbox Style Specification, making it the most direct way to consume `mapbox.mapbox-streets-v8` vector tiles with a custom style. Pass the full style JSON as the `style` constructor option — no adapter library required.

The `glyphs` field points to a font service for rendering text labels. The Mapbox Fonts API provides the same fonts used in Mapbox Studio.

```js
const accessToken = 'YOUR_MAPBOX_ACCESS_TOKEN';

const map = new maplibregl.Map({
  container: 'map',
  center: [-74.006, 40.7128],
  zoom: 13,
  style: {
    version: 8,
    glyphs: `https://api.mapbox.com/fonts/v1/mapbox/{fontstack}/{range}.pbf?access_token=${accessToken}`,
    sources: {
      'mapbox-streets': {
        type: 'vector',
        tiles: [
          `https://api.mapbox.com/v4/mapbox.mapbox-streets-v8/{z}/{x}/{y}.mvt?access_token=${accessToken}`
        ],
        maxzoom: 16
      }
    },
    layers: [
      { id: 'background', type: 'background',
        paint: { 'background-color': '#1a1a2e' } },
      { id: 'water', type: 'fill',
        source: 'mapbox-streets', 'source-layer': 'water',
        paint: { 'fill-color': '#16213e' } },
      { id: 'road-major', type: 'line',
        source: 'mapbox-streets', 'source-layer': 'road',
        filter: ['in', 'class', 'primary', 'secondary', 'trunk'],
        paint: { 'line-color': '#445577', 'line-width': 2 } },
      { id: 'road-motorway', type: 'line',
        source: 'mapbox-streets', 'source-layer': 'road',
        filter: ['==', 'class', 'motorway'],
        paint: { 'line-color': '#e94560', 'line-width': 3 } },
      { id: 'place-label', type: 'symbol',
        source: 'mapbox-streets', 'source-layer': 'place_label',
        layout: {
          'text-field': ['get', 'name'],
          'text-font': ['Open Sans Regular'],
          'text-size': ['interpolate', ['linear'], ['zoom'], 10, 10, 14, 14]
        },
        paint: { 'text-color': '#a0a0cc', 'text-halo-color': '#1a1a2e', 'text-halo-width': 1 } }
      // add more layers to style buildings, parks, minor roads, etc.
    ]
  }
});
```

Layer definitions reference `source-layer` names from the [streets-v8 schema](https://docs.mapbox.com/data/tilesets/reference/mapbox-streets-v8/). You can also add a GeoJSON source alongside the vector tile source to overlay your own data:

```js
map.on('load', () => {
  map.addSource('my-data', { type: 'geojson', data: myGeoJson });
  map.addLayer({ id: 'my-layer', type: 'fill', source: 'my-data', paint: { 'fill-color': '#ff7800' } });
});
```

## Raster basemap tiles

MapLibre's style system manages all map sources and layers. Define a `raster` source in the style object with the [Static Tiles API](https://docs.mapbox.com/api/maps/static-tiles/) URL, then add a `raster` layer to display it.

```js
const map = new maplibregl.Map({
  container: 'map',
  center: [-74.006, 40.7128],
  zoom: 12,
  style: {
    version: 8,
    sources: {
      'mapbox-raster': {
        type: 'raster',
        tiles: [
          'https://api.mapbox.com/styles/v1/mapbox/streets-v12/tiles/512/{z}/{x}/{y}@2x?access_token=YOUR_MAPBOX_ACCESS_TOKEN'
        ],
        tileSize: 512,
        maxzoom: 22
      }
    },
    layers: [
      { id: 'basemap', type: 'raster', source: 'mapbox-raster' }
    ]
  }
});
```

Swap `streets-v12` for any [classic Mapbox style](https://docs.mapbox.com/api/maps/styles/#classic-mapbox-styles) or your own custom style ID from [Mapbox Studio](https://studio.mapbox.com).

## Satellite imagery

Use the [Raster Tiles API](https://docs.mapbox.com/api/maps/raster-tiles/) to add the `mapbox.satellite` imagery tileset. These are 256px tiles served as JPEG.

```js
style: {
  version: 8,
  sources: {
    'mapbox-satellite': {
      type: 'raster',
      tiles: [
        'https://api.mapbox.com/v4/mapbox.satellite/{z}/{x}/{y}@2x.jpg90?access_token=YOUR_MAPBOX_ACCESS_TOKEN'
      ],
      tileSize: 256,
      maxzoom: 22
    }
  },
  layers: [
    { id: 'satellite-layer', type: 'raster', source: 'mapbox-satellite' }
  ]
}
```

## Directions and Isochrone API

MapLibre handles GeoJSON data through named sources added to the map after the `load` event. This follows the same pattern as Mapbox GL JS — fetch the API responses, add them as `geojson` sources, and configure layers to render them.

```js
map.on('load', async () => {
  const origin = [-73.9855, 40.7580];
  const destination = [-73.9969, 40.7061];

  // Isochrones
  const isoRes = await fetch(
    `https://api.mapbox.com/isochrone/v1/mapbox/driving/${origin[0]},${origin[1]}` +
    `?contours_minutes=5,10,15&polygons=true&access_token=YOUR_MAPBOX_ACCESS_TOKEN`
  );
  const isoData = await isoRes.json();

  map.addSource('isochrone', { type: 'geojson', data: isoData });
  map.addLayer({
    id: 'isochrone-fill',
    type: 'fill',
    source: 'isochrone',
    paint: {
      // Data-driven color based on the 'contour' property of each polygon
      'fill-color': [
        'case',
        ['==', ['get', 'contour'], 5],  '#1d4ed8',
        ['==', ['get', 'contour'], 10], '#3b82f6',
        '#93c5fd'
      ],
      'fill-opacity': 0.25
    }
  });

  // Route
  const routeRes = await fetch(
    `https://api.mapbox.com/directions/v5/mapbox/driving/` +
    `${origin.join(',')};${destination.join(',')}` +
    `?geometries=geojson&access_token=YOUR_MAPBOX_ACCESS_TOKEN`
  );
  const routeData = await routeRes.json();

  map.addSource('route', {
    type: 'geojson',
    data: { type: 'Feature', geometry: routeData.routes[0].geometry }
  });
  map.addLayer({
    id: 'route-line',
    type: 'line',
    source: 'route',
    layout: { 'line-join': 'round', 'line-cap': 'round' },
    paint: { 'line-color': '#1d4ed8', 'line-width': 4 }
  });
});
```

## Search JS

[Mapbox Search JS](https://docs.mapbox.com/mapbox-search-js/guides/) provides `MapboxSearchBox`, a web component that fires a `retrieve` event when a user selects a result. Position it as an absolutely-placed overlay on the map and handle the event to fly to the result and place a marker.

```html
<head>
  <link rel="stylesheet" href="https://unpkg.com/maplibre-gl@4/dist/maplibre-gl.css" />
  <script src="https://unpkg.com/maplibre-gl@4/dist/maplibre-gl.js"></script>
  <script id="search-js" defer
    src="https://api.mapbox.com/search-js/v1.2.0/web.js">
  </script>
  <style>
    #map { position: absolute; top: 0; bottom: 0; width: 100%; }

    #search-container {
      position: absolute;
      top: 10px;
      left: 50%;
      transform: translateX(-50%);
      z-index: 1000;
      width: 320px;
    }
  </style>
</head>
<body>
  <div id="map"></div>
  <div id="search-container"></div>
  <script>
    const ACCESS_TOKEN = 'YOUR_MAPBOX_ACCESS_TOKEN';

    const map = new maplibregl.Map({
      container: 'map',
      center: [-74.006, 40.7128],
      zoom: 12,
      style: {
        version: 8,
        sources: {
          'mapbox-raster': {
            type: 'raster',
            tiles: [
              `https://api.mapbox.com/styles/v1/mapbox/streets-v12/tiles/512/{z}/{x}/{y}@2x?access_token=${ACCESS_TOKEN}`
            ],
            tileSize: 512,
            attribution: '© Mapbox © OpenStreetMap'
          }
        },
        layers: [{ id: 'basemap', type: 'raster', source: 'mapbox-raster' }]
      }
    });

    let resultMarker = null;

    window.addEventListener('load', () => {
      const searchBox = new MapboxSearchBox();
      searchBox.accessToken = ACCESS_TOKEN;
      searchBox.options = { types: 'address,poi', proximity: [-74.006, 40.7128] };
      document.getElementById('search-container').appendChild(searchBox);

      searchBox.addEventListener('retrieve', (event) => {
        const feature = event.detail.features[0];
        const [lng, lat] = feature.geometry.coordinates;

        map.flyTo({ center: [lng, lat], zoom: 15 });

        if (resultMarker) resultMarker.remove();
        resultMarker = new maplibregl.Marker()
          .setLngLat([lng, lat])
          .setPopup(
            new maplibregl.Popup().setText(
              feature.properties.name || feature.properties.full_address
            )
          )
          .addTo(map)
          .togglePopup();
      });
    });
  </script>
</body>
```

## Related guides

-   [Use Mapbox APIs in Leaflet.js](https://docs.mapbox.com/help/dive-deeper/mapbox-in-leaflet/)
-   [Use Mapbox APIs in OpenLayers](https://docs.mapbox.com/help/dive-deeper/mapbox-in-openlayers/)
-   [Add a Mapbox map as a basemap in QGIS and ArcMap Pro with WMTS](https://docs.mapbox.com/help/tutorials/mapbox-arcgis-qgis/)

## Pricing

Most Mapbox services include a free tier that covers a generous volume of monthly usage — enough for development and many production use cases. Beyond the free tier, pricing is usage-based and varies by product.

| Service | Pricing details |
| --- | --- |
| Maps (raster and vector tiles) | [Maps pricing](https://www.mapbox.com/pricing#maps) |
| Directions API | [Navigation pricing](https://www.mapbox.com/pricing#navigation) |
| Isochrone API | [Navigation pricing](https://www.mapbox.com/pricing#navigation) |
| Search / Geocoding | [Search pricing](https://www.mapbox.com/pricing#search) |

See the [Mapbox pricing page](https://www.mapbox.com/pricing) for current free tier limits and rates. When consuming tiles through a third-party library (rather than Mapbox GL JS), tile requests are billed individually under the Maps API rather than being bundled into a map load.