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

# Use Mapbox APIs in OpenLayers

[OpenLayers](https://openlayers.org/) is a full-featured open-source web mapping library. It supports raster XYZ tile sources, native MVT (Mapbox Vector Tile) rendering, and GeoJSON data layers. With the [ol-mapbox-style](https://github.com/openlayers/ol-mapbox-style) adapter, it can also consume Mapbox Style JSON to render styled vector basemaps from Mapbox tilesets.

> **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/ja/dive-deeper/how-to-use-mapbox-securely/) for guidance on restricting tokens and avoiding exposure.

One key difference from Leaflet: OpenLayers renders internally in Web Mercator (EPSG:3857), so coordinates from external sources (WGS84 / EPSG:4326) must be reprojected. Use `ol.proj.fromLonLat([lng, lat])` to convert when creating geometries, and pass `featureProjection: 'EPSG:3857'` when reading GeoJSON features.

## Raster basemap tiles

The [Static Tiles API](https://docs.mapbox.com/api/maps/static-tiles/) renders any Mapbox style as raster tiles. Add them using an `XYZ` source inside a `Tile` layer.

```js
new ol.layer.Tile({
  source: new ol.source.XYZ({
    url: '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,
    attributions:
      '© <a href="https://www.mapbox.com/about/maps/">Mapbox</a> ' +
      '© <a href="http://www.openstreetmap.org/copyright">OpenStreetMap</a>'
  })
})
```

## Satellite imagery

The [Raster Tiles API](https://docs.mapbox.com/api/maps/raster-tiles/) serves the `mapbox.satellite` imagery tileset as standard XYZ tiles. These are 256px tiles with no labels or road overlays.

```js
new ol.layer.Tile({
  source: new ol.source.XYZ({
    url: 'https://api.mapbox.com/v4/mapbox.satellite/{z}/{x}/{y}@2x.jpg90?access_token=YOUR_MAPBOX_ACCESS_TOKEN',
    maxZoom: 22,
    attributions:
      '© <a href="https://www.mapbox.com/about/maps/">Mapbox</a> ' +
      '© <a href="https://www.maxar.com/">Maxar</a>'
  })
})
```

To display satellite imagery with road and label overlays, use the `satellite-streets-v12` style through the Static Tiles API instead:

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

## Vector tiles with custom style

OpenLayers can render Mapbox Vector Tiles natively, and the [ol-mapbox-style](https://github.com/openlayers/ol-mapbox-style) library (`olms`) translates Mapbox Style JSON into OpenLayers rendering rules. This lets you define your own visual style over the `mapbox.mapbox-streets-v8` tileset — the same vector data that powers Mapbox's hosted styles.

```html
<script src="https://cdn.jsdelivr.net/npm/ol@10/dist/ol.js"></script>
<script src="https://cdn.jsdelivr.net/npm/ol-mapbox-style@12/dist/olms.js"></script>
```

Create the map without any layers, then call `olms.apply()` with a style JSON object that references the streets-v8 tile URL directly:

```js
const accessToken = 'YOUR_MAPBOX_ACCESS_TOKEN';

const map = new ol.Map({
  target: 'map',
  view: new ol.View({ center: ol.proj.fromLonLat([-74.006, 40.7128]), zoom: 13 })
  // No layers — olms.apply() adds them from the style object
});

const customStyle = {
  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: 'place-label', type: 'symbol', source: 'mapbox-streets', 'source-layer': 'place_label',
      layout: { 'text-field': ['get', 'name'], 'text-font': ['Open Sans Regular'], 'text-size': 12 },
      paint: { 'text-color': '#a0a0cc', 'text-halo-color': '#1a1a2e', 'text-halo-width': 1 } }
    // add more layers to style buildings, parks, roads, etc.
  ]
};

olms.apply(map, customStyle);
```

The layer definitions reference `source-layer` names from the [streets-v8 tileset schema](https://docs.mapbox.com/data/tilesets/reference/mapbox-streets-v8/). You can add as many layers as needed to achieve your desired visual style.

`olms.apply()` returns a Promise — chain `.then()` to add OpenLayers vector layers on top of the basemap after it loads:

```js
olms.apply(map, customStyle).then(() => {
  map.addLayer(new ol.layer.Vector({
    source: new ol.source.Vector({
      features: new ol.format.GeoJSON().readFeatures(myGeoJson, {
        featureProjection: 'EPSG:3857'
      })
    })
  }));
});
```

## Directions and Isochrone API

The [Directions API](https://docs.mapbox.com/api/navigation/directions/) and [Isochrone API](https://docs.mapbox.com/api/navigation/isochrone/) return GeoJSON. Use `ol.format.GeoJSON` to parse the responses into OpenLayers features, then add them to a `Vector` layer. Always pass `featureProjection: 'EPSG:3857'` so OpenLayers reprojects the WGS84 coordinates automatically.

```js
const geoJsonFormat = new ol.format.GeoJSON();
const vectorSource = new ol.source.Vector();
map.addLayer(new ol.layer.Vector({ source: vectorSource }));

// 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();
const colors = ['#1d4ed8', '#3b82f6', '#93c5fd'];

isoData.features.reverse().forEach((feature, i) => {
  const olFeatures = geoJsonFormat.readFeatures(feature, { featureProjection: 'EPSG:3857' });
  olFeatures.forEach(f => f.setStyle(new ol.style.Style({
    fill: new ol.style.Fill({ color: colors[i] + '40' }),
    stroke: new ol.style.Stroke({ color: colors[i], width: 1.5 })
  })));
  vectorSource.addFeatures(olFeatures);
});

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

const routeFeature = geoJsonFormat.readFeature(routeData.routes[0].geometry, {
  featureProjection: 'EPSG:3857'
});
routeFeature.setStyle(new ol.style.Style({
  stroke: new ol.style.Stroke({ color: '#1d4ed8', width: 4 })
}));
vectorSource.addFeature(routeFeature);
```

## 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 overlay on the map and use `ol.proj.fromLonLat` to convert the result coordinates before updating the view.

```html
<head>
  <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/ol@10/ol.css" />
  <script src="https://cdn.jsdelivr.net/npm/ol@10/dist/ol.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 markerSource = new ol.source.Vector();
    const markerLayer = new ol.layer.Vector({
      source: markerSource,
      style: new ol.style.Style({
        image: new ol.style.Icon({
          anchor: [0.5, 1],
          src: 'https://cdn.jsdelivr.net/npm/leaflet@1.9.4/dist/images/marker-icon.png'
        })
      })
    });

    const map = new ol.Map({
      target: 'map',
      layers: [
        new ol.layer.Tile({
          source: new ol.source.XYZ({
            url:
              'https://api.mapbox.com/styles/v1/mapbox/streets-v12/tiles/512/{z}/{x}/{y}@2x?access_token=' +
              ACCESS_TOKEN,
            tileSize: 512,
            maxZoom: 22,
            attributions:
              '© <a href="https://www.mapbox.com/about/maps/">Mapbox</a> ' +
              '© <a href="http://www.openstreetmap.org/copyright">OpenStreetMap</a>'
          })
        }),
        markerLayer
      ],
      view: new ol.View({
        center: ol.proj.fromLonLat([-74.006, 40.7128]),
        zoom: 12
      })
    });

    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;
        const coords = ol.proj.fromLonLat([lng, lat]);  // reproject for OpenLayers

        map.getView().animate({ center: coords, zoom: 15, duration: 600 });

        markerSource.clear();
        markerSource.addFeature(new ol.Feature(new ol.geom.Point(coords)));
      });
    });
  </script>
</body>
```

## Related guides

-   [Use Mapbox APIs in Leaflet.js](https://docs.mapbox.com/help/ja/dive-deeper/mapbox-in-leaflet/)
-   [Use Mapbox APIs in MapLibre GL JS](https://docs.mapbox.com/help/ja/dive-deeper/mapbox-in-maplibre/)
-   [Add a Mapbox map as a basemap in QGIS and ArcMap Pro with WMTS](https://docs.mapbox.com/help/ja/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.