- 技術 💻
Mapboxとは?料金・使い方とGoogle Maps・MapLibreとの違い
結論
Mapbox(マップボックス)は、地図の表示・場所の検索・経路案内を自分のWebサイトやアプリに組み込むための開発基盤です。Webの地図は月5万ロードまで無料で、超えた分は1,000ロードあたり5ドルからの従量課金です(2026年10月29日時点)。使うにはアカウントとアクセストークンが要り、トークン不要で同じ書き方ができるオープンソースの互換ライブラリとして MapLibre GL JS があります。
この記事でわかること
- Mapboxの製品・料金(無料枠と従量)と、Google Maps Platformとの月額の比較
- MapLibre GL JSで外部タイルなしに地図を描いた実物(GeoJSON・スタイルJSON・クリック)
- トークンなし・CORS・WebGL・importのエラー原文と、Google Maps・Leaflet・MapLibreの判断表
Mapbox の地図は「データ(タイルやGeoJSON)」と「見た目の決まり(スタイルJSON)」を、ブラウザの中の描画ライブラリ(Mapbox GL JS)が組み合わせて絵にします。この形は互換の MapLibre GL JS でも同じです。
flowchart TD
S[スタイルJSON] --> L[GL JS / MapLibre<br>Mapboxはトークン必須]
D[タイル・GeoJSON] --> L
L --> C[WebGLで描画]
C --> E[マーカー・クリック]
よく調べられることの答えを先にまとめます。
| 知りたいこと | 答え | 詳しい節 |
|---|---|---|
| Mapboxとは | 地図・検索・ナビを組み込む開発基盤。Studio・API・SDKの集まり | Mapboxとは |
| Mapbox 料金 | Webは月5万ロード無料、超過は1,000ロード5ドルから | Mapboxの料金 |
| Mapbox 無料で使える? | 無料枠の範囲なら0円。トークンとアカウントは要る | Mapboxの料金 |
| Mapbox 使い方 | アカウント→トークン→GL JSを読み込み→new Map | Mapboxの使い方 |
| Google Mapsとの違い | 見た目を細かく変えやすい。月5万ロードまでならMapboxが安い | 違いの比較表 |
| MapLibreとの関係 | Mapbox GL JS v1を元にしたオープンソースの互換版 | ライセンスとMapLibre |
| トークンなしで動く? | Mapbox GL JSは動かない(エラー原文あり)。MapLibreは動く | トークンなしで動かすと |
| 地図が出ない | トークン・CORS・WebGL・importの書き方を順に見る | よくあるエラー |
確認環境:Ubuntu 24.04.5 LTS(2 CPU・メモリ 8GB)の上で、npm から入れた MapLibre GL JS 6.16.0(BSD-3-Clause)と Mapbox GL JS 3.34.1 を、Python 3.13.18 の http.server で 127.0.0.1 に置いた自分のページから読み込み、Chromium 153.0.8010.12(Playwright 1.63.0、ヘッドレス、描画は SwiftShader の WebGL)で表示・クリック・計測しました。地図のデータは自作の GeoJSON(点・線・面)と、そこから @maplibre/geojson-vt 6.3.0・@maplibre/vt-pbf 4.3.3 で作ったベクタータイルだけで、外部のタイルやフォントは読み込んでいません(127.0.0.1 以外への通信は Playwright で遮断し、遮断した件数を記録)。スタイルの検査は @maplibre/maplibre-gl-style-spec の gl-style-validate を使いました。Mapbox のアカウント作成・トークン取得は行っていないため、Mapbox Studio の操作・トークンの作り方・料金は Mapbox 公式ドキュメントと料金ページ、Google Maps Platform の料金は Google の公式ページ、OpenStreetMap のタイル利用方針は OSMF の公式ページで確かめています。図は mermaid 11.16.0 で描画を確かめました(確認日 2026年10月29日)。
本記事の内容は、ご自由にお使いください。
ご利用の際は、出典として本ページへのリンクを記載いただけますようお願いします。
(記載例)出典:株式会社RJC「Mapboxとは?料金・使い方とGoogle Maps・MapLibreとの違い」
Mapboxとは?地図の開発基盤でできること
この節では、Mapbox が何をする製品で、どんな部品に分かれているのかが分かります。
Mapbox は、アプリやWebサイトに独自デザインの地図、場所の検索、ナビゲーションを組み込むための「位置情報プラットフォーム」です。Mapbox 公式の「はじめ方」のページでは、Mapbox Studio(地図のデザイン)、API、ライブラリ、SDK を組み合わせて、Web・モバイル・ゲーム・組み込みシステム向けの地図アプリを作れると説明しています。日本では Mapbox とソフトバンクの合弁会社として Mapbox Japan があり、日本語の公式サイトとドキュメントがあります。
Google マップのように「誰かが作った地図を表示する」だけでなく、道路の色・文字の大きさ・表示する建物の種類まで、地図の見た目そのものを作り変えられるのが特徴です。製品は大きく4つに分かれます。
Maps(地図)
Web 向けの Mapbox GL JS、iOS・Android 向けの Maps SDK、タイルや静的画像を返す Maps API。
いちばん使われる部分
Search(検索)
住所から緯度経度を出すジオコーディング、その逆、地点の検索。Search Box API など。
入力補完のUIもある
Navigation(経路)
Directions API(経路検索)、Isochrone(到達圏)、Map Matching、モバイルの Navigation SDK。
ターンバイターン案内
Mapbox Studio
ブラウザで地図のスタイルを作って公開する画面。公開すると Style URL が付く。
コードを書かずに配色を変える
使われ方としては、店舗検索の地図、不動産や配車アプリの地図、物流の配送ルート、データの可視化(人口や売上を色で塗り分ける)などがあります。プログラムの側から見ると、中心になるのは Mapbox GL JS(Web)とスタイル(地図の見た目をJSONで書いたもの)の2つです。この記事の後半では、その2つを互換ライブラリで実際に動かします。
Mapboxの料金:無料枠と従量課金の早見表
この節では、Mapbox がいくらで使えるのか、無料枠がどこまでかが分かります。
Mapbox は、製品ごとに月ごとの無料枠があり、超えた分だけ払う従量課金です。料金ページでは「ほとんどの製品に意味のある無料枠がある」と書かれ、年間契約や大口の割引は営業への問い合わせです。下の表は料金ページ(米ドル、2026年10月29日時点)から主なものを抜き出しました。
| 製品(単位) | 無料枠(月) | 超過分の単価(最初の段階) | その次の段階 |
|---|---|---|---|
| Web の地図(Map Loads) | 50,000 ロード | $5.00/1,000(〜10万) | $4.00(〜20万)・$3.00(〜100万)・$2.50(〜500万) |
| モバイルの地図(MAU) | 25,000 人 | $4.00/1,000人(〜12.5万) | $3.20・$2.40 |
| Vector Tiles API | 200,000 リクエスト | $0.25/1,000 | $0.20・$0.15 |
| Raster Tiles API | 750,000 リクエスト | $0.25/1,000 | $0.20・$0.15 |
| Static Images API | 50,000 リクエスト | $1.00/1,000 | $0.80・$0.60 |
| Temporary Geocoding API | 100,000 リクエスト | $0.75/1,000 | $0.60・$0.45 |
| Directions API | 100,000 リクエスト | $2.00/1,000 | $1.60・$1.20 |
Web の地図で数えるのは「Map Load」です。料金ページの定義では、Mapbox GL JS の地図がページの中で初期化されるたびに1回と数え、その地図が読み込む Vector Tiles API と Raster Tiles API のリクエストは無制限に含まれます。Mapbox の料金ドキュメントには「地図をどれだけ操作しても1ロード」とあり、拡大・移動を何度しても増えません。反対に、ページを開き直すたび・地図を作り直すたびに1ロード増えます。
このほか、社内ツールのように少人数で使う場合の「Map Seats」(月3シートまで無料、4〜125シートは1シート$4.00)、住所の入力補完(Address Autofill、月1,000セッションまで無料)、モバイルの Navigation SDK(MAU とトリップ数で課金)などがあります。日本の利用者が従量課金で使う場合、取引は消費税のリバースチャージ方式の対象になると料金ページに書かれています。
費用は段階ごとに計算します。月30万ロードなら、最初の5万は無料、次の5万が $5×50=$250、次の10万が $4×100=$400、残り10万が $3×100=$300 で、合計 $950 です。料金は変わることがあるため、見積もりの前に公式の料金ページで最新の値を確かめます。
Mapbox・Google Maps・Leaflet・MapLibreの違い(比較表)
この節では、地図を組み込むときに比べられる4つの選択肢が、何を提供し、何が違うのかが分かります。
よく比べられる4つは、そもそもの種類が違います。Mapbox と Google Maps Platform は「地図データ+描画+API」をまとめて提供するサービス、Leaflet と MapLibre GL JS は「描画するためのライブラリ」だけで、地図データ(タイル)は別に用意します。
| 項目 | Mapbox | Google Maps Platform | MapLibre GL JS | Leaflet |
|---|---|---|---|---|
| 種類 | サービス(地図データ+ライブラリ+API) | サービス(地図データ+ライブラリ+API) | 描画ライブラリ | 描画ライブラリ |
| ライセンス | GL JS v2以降は Mapbox の利用規約 | Google の利用規約 | BSD-3-Clause | BSD-2-Clause |
| キー・トークン | アクセストークンが必須 | API キーが必須 | 不要(タイル提供元によっては要る) | 不要(同上) |
| 描き方 | WebGL・ベクタータイル | ラスター/ベクター | WebGL2・ベクタータイル | 主にラスタータイル(画像) |
| 見た目の変更 | Studio とスタイルJSONで細かく | Cloud-based maps styling など | スタイルJSONで細かく | タイル画像次第 |
| Web 地図の無料枠 | 月50,000ロード | Dynamic Maps 月10,000回 | ライブラリは無料 | ライブラリは無料 |
Google Maps Platform は2025年3月1日に、毎月$200のクレジットをやめ、SKU(課金の単位)ごとの月の無料利用枠に切り替えました(Google の公式ページ)。地図の表示にあたる Dynamic Maps は Essentials に分類され、月10,000回まで無料、10,001〜100,000回は1,000回あたり$7.00、100,001〜500,000回は$5.60です。同じ月間ロード数で計算すると次のようになります。
| 月の地図の読み込み | Mapbox(Map Loads) | Google(Dynamic Maps) |
|---|---|---|
| 10,000 | $0 | $0 |
| 50,000 | $0 | $280 |
| 100,000 | $250 | $630 |
| 300,000 | $950 | $1,750 |
| 1,000,000 | $3,050 | $4,970 |
この表は2社の公式料金ページの段階料金(2026年10月29日時点、米ドル、税・割引なし)を Python で足し上げたものです。数え方の定義は各社で違い、検索・経路・住所の補完を使えば別に費用がかかります。地図の表示だけを比べた目安として読み、見積もりでは使う API をすべて並べて計算します。
Leaflet は軽くて書き方が簡単なライブラリで、安定版は 1.9.4、2.0.0 のアルファ版が公開されています(Leaflet 公式のダウンロードページ)。Leaflet と組み合わせることが多い OpenStreetMap 公式のタイルサーバーは寄付で運営されており、利用方針で「重い利用はお知らせなく遮断することがある」「表示中以外のタイルの一括取得は禁止」「帰属表示を目立つ位置に出す」と定めています。商用サービスで大量に表示するなら、有料のタイル提供元か自前のタイルを用意します。
Mapboxの使い方:アカウント作成から地図表示まで
この節では、Mapbox で最初の地図を出すまでの手順が、公式ドキュメントに沿って分かります。
この記事ではアカウントの作成とトークンの取得を行っていないため、手順は Mapbox 公式ドキュメント(はじめ方・GL JS のインストール・トークンのガイド)で確かめた範囲で書きます。
アカウントを作る
mapbox.com からサインアップします。アカウントの管理は Mapbox Console で行い、トークンの作成、使用量の確認、請求の設定、スタイルやデータセットの管理ができます。
アクセストークンを用意する
アカウントには「デフォルトの公開トークン」が1つ必ずあります。公開するサイトでは、公開スコープだけを持つ別のトークンを作り、URL 制限を付けて使うことが公式で勧められています。
Mapbox GL JS を読み込む
CDN なら公式の api.mapbox.com/mapbox-gl-js/v3.33.0/ の JS と CSS、npm なら npm install mapbox-gl。雛形から作る npm create @mapbox/web-app もあります。
トークンを設定して new Map
mapboxgl.accessToken にトークンを入れ、container・center(経度, 緯度の順)・zoom を渡します。style を省くと Mapbox Standard が使われます。
Studio で見た目を作る(任意)
Mapbox Studio で新しいスタイルを作り、Imports パネルで色やフォントを調整して Publish します。公開したスタイルは mapbox://styles/ユーザー名/スタイルID の Style URL で GL JS から読み込めます。
npm で入れた場合の最小の形です。トークンは実物を書かず、ビルド時の環境変数から渡しています(Vite の例)。
import mapboxgl from 'mapbox-gl';
import 'mapbox-gl/dist/mapbox-gl.css';
mapboxgl.accessToken = import.meta.env.VITE_MAPBOX_TOKEN; // pk. で始まる公開トークン
const map = new mapboxgl.Map({
container: 'map', // 地図を入れる要素の id
center: [139.767, 35.681], // [経度, 緯度] の順
zoom: 12
// style を省くと Mapbox Standard
});
環境変数の書き方と、VITE_ を付け忘れて undefined になる原因は、関連記事「Reactの環境変数.envの使い方|VITE_がundefinedの原因」で扱っています。Vite で React のプロジェクトを作る手順は、関連記事「React環境構築をViteで行う手順|create viteの使い方」で扱っています。
Mapbox Studio の新規スタイル作成では、ベースマップとして Mapbox Standard か Mapbox Standard Satellite を選びます。Standard には Default・Faded・Monochrome のテーマがあり、2D と 3D の両方に使えます。以前は Basic・Streets・Light・Dark・Satellite などのテンプレートから選ぶ画面でしたが、2026年10月29日時点の Studio マニュアルでは Standard を元にする形が説明されています。
アクセストークンの種類と、公開ページでの守り方
この節では、Mapbox のトークンにどんな種類があり、Web ページに書くときに何に気を付けるかが分かります。
ブラウザで動く地図のトークンは、ページのソースを見れば誰でも読めます。Mapbox 公式のトークンのガイドも、公開ページやソースコードに含めたトークンは「探そうとすれば誰にでも見える」と書いています。だからこそ、種類とスコープ(権限)と URL 制限で被害を小さくします。
| 種類 | 先頭 | 使う場所 | 主な性質 |
|---|---|---|---|
| 公開トークン | pk. |
Web・モバイルアプリ | 公開スコープだけ(styles:tiles・styles:read・fonts:read など) |
| シークレットトークン | sk. |
サーバーだけ | アップロード・トークン管理などの権限。公開しない |
| 一時トークン | tk. |
短時間の用途 | 有効期限は最長1時間先まで |
| デフォルト公開トークン | pk. |
試すとき | URL 制限を付けられない。削除すると新しいものが自動で作られる |
公開するページのトークン
URL 制限は「最善の努力による軽減策」と公式に書かれており、完全な防御ではない
URL 制限を付けると、許可していない URL からのリクエストは 403: Forbidden になります。ワイルドカードや IP アドレスでの指定はできません。API キーを誤って公開リポジトリに入れたときの手順は関連記事「.envの使い方と注意点|APIキーを安全に管理する方法」で扱っています。
Mapbox GL JS v2以降のライセンスとMapLibreが生まれた経緯
この節では、なぜ Mapbox GL JS に互換のオープンソース版があるのか、使うときのライセンスの注意が分かります。
Mapbox GL JS は v1.13 まで BSD-3-Clause のオープンソースでしたが、2020年12月の v2.0 から Mapbox の利用規約に基づく独自ライセンスになりました。npm で入れた mapbox-gl 3.34.1 の LICENSE.txt の冒頭は次のとおりです。
mapbox-gl-js v2.0
Mapbox Web SDK
Copyright © 2021 - 2023 Mapbox, Inc. All rights reserved.
The software and files in this repository (collectively, "Software") are
licensed under the Mapbox TOS for use only with the relevant Mapbox product(s)
listed at www.mapbox.com/pricing.
GitHub の LICENSE.txt には、ほかに「有効な Mapbox アカウントを持っていることが前提」「課金・集計・データ収集のコードを変えたり妨げたりする改変は認めない」といった条件が書かれています。つまり、v2 以降の Mapbox GL JS を Mapbox 以外のタイルだけで使うことは想定されていません。
このライセンス変更の前の v1 を元に分かれた(フォークした)のが MapLibre GL JS です。MapLibre の README によると、初期の 1.x は Mapbox GL JS 1.x とそのまま置き換えられる互換版として作られ、その後は独自に機能を増やしてきました。ライセンスは BSD-3-Clause で、2026年10月29日時点の npm の最新は 6.16.0 です。スタイルJSONの形(version 8・sources・layers)は共通なので、MapLibre で書いた知識は Mapbox でもほぼそのまま使えます。
Mapbox GL JS(v2以降)
Mapbox の利用規約に基づくライセンス
アクセストークンが必須。Map Loads で課金
Mapbox Standard・3D・Studio のスタイルがそのまま使える
MapLibre GL JS
BSD-3-Clause のオープンソース
トークン不要。タイルは自前か別の提供元
スタイル仕様は v8 系で共通。Mapbox 独自の新機能は含まない
MapLibre GL JSで地図を描く(外部タイルなし)
この節では、トークンも外部タイルも使わずに、GeoJSON とスタイルJSON だけで地図を描いた実物が分かります。
手元の作業場所に npm install maplibre-gl で入れ、node_modules/maplibre-gl/dist をページから読める場所に置きました。データは東京の新宿付近の座標で、面(公園と池)、線(散歩道)、点(入口・展望台・休憩所)を GeoJSON で自作しています。点のデータは次の形です。
{ "type": "FeatureCollection", "features": [
{ "type": "Feature", "properties": { "name": "入口A", "rank": 2 }, "geometry": { "type": "Point", "coordinates": [139.698, 35.678] } },
{ "type": "Feature", "properties": { "name": "展望台", "rank": 4 }, "geometry": { "type": "Point", "coordinates": [139.705, 35.684] } },
{ "type": "Feature", "properties": { "name": "休憩所", "rank": 3 }, "geometry": { "type": "Point", "coordinates": [139.716, 35.679] } }
] }
GeoJSON の座標は [経度, 緯度] の順です。Google マップで見る「35.68, 139.70」(緯度が先)とは逆なので、入れ替えて書くと地図が南極付近やインド洋に飛びます。これを描くスタイルJSONが次です。
{
"version": 8,
"name": "t123-local",
"sources": {
"area": { "type": "geojson", "data": "data/area.geojson" },
"route": { "type": "geojson", "data": "data/route.geojson" },
"spots": { "type": "geojson", "data": "data/spots.geojson" }
},
"layers": [
{ "id": "bg", "type": "background", "paint": { "background-color": "#eef3f7" } },
{ "id": "area-fill", "type": "fill", "source": "area",
"paint": { "fill-color": ["match", ["get", "kind"], "park", "#b7e4c7", "water", "#a9d6f5", "#dddddd"], "fill-opacity": 0.8 } },
{ "id": "area-line", "type": "line", "source": "area", "paint": { "line-color": "#52796f", "line-width": 1 } },
{ "id": "route-line", "type": "line", "source": "route",
"layout": { "line-cap": "round", "line-join": "round" },
"paint": { "line-color": "#e76f51", "line-width": ["interpolate", ["linear"], ["zoom"], 12, 2, 16, 8] } },
{ "id": "spots-circle", "type": "circle", "source": "spots",
"paint": { "circle-radius": ["*", 3, ["get", "rank"]], "circle-color": "#264653", "circle-stroke-color": "#ffffff", "circle-stroke-width": 2 } }
]
}
ページの側は、地図を入れる要素と、ES モジュールとしての読み込みだけです(地図の要素は main にしています)。
<link rel="stylesheet" href="lib/maplibre-gl.css">
<main id="map" style="width:800px;height:500px"></main>
<script type="module">
import * as maplibregl from './lib/maplibre-gl.mjs';
const map = new maplibregl.Map({
container: 'map', style: 'style.json', center: [139.710, 35.682], zoom: 14
});
map.addControl(new maplibregl.NavigationControl(), 'top-right');
</script>
Python の http.server を 127.0.0.1 で起動し、Chromium で開いたときにブラウザが出したリクエストは次の8本だけでした。127.0.0.1 以外への通信を遮断する設定で記録し、遮断した件数は0件です。
/index.html
/lib/maplibre-gl.css
/lib/maplibre-gl.mjs
/lib/maplibre-gl-worker.mjs?v=6.16.0
/style.json
/data/area.geojson
/data/route.geojson
/data/spots.geojson
描画用の処理は Web Worker(maplibre-gl-worker.mjs)に分かれていて、本体が自動で読み込みます。ページを開いてから load イベントまでは 761ms(ほかの試行では 342〜646ms)でした。描画は WebGL で、このヘッドレスの Chromium ではソフトウェア実装の SwiftShader が使われています。
1外部への通信は0件
トークンもタイルサーバーも使わず、自分のサーバーの8ファイルだけで地図が出た。社内ネットワークだけの画面でも同じ形で使える。
2見た目はすべて style.json
色・太さ・半径を JS ではなくスタイルに書いた。点の大きさは rank の値から式で計算している。
3表示中の地物を取り出せる
map.queryRenderedFeatures() は11件を返した。面は枠線と塗りの2レイヤーに、タイルの境目でも分かれて数えられる。
描いた結果は、薄い青の背景の上に緑の四角(公園)と水色の四角(池)、その上を橙の線(散歩道)が通り、3つの丸(rank が大きいほど大きい)が並ぶ地図です。右上に拡大・縮小・方角のボタン、右下に「MapLibre」の帰属表示が出ました。queryRenderedFeatures() の結果は次のとおりです。
spots-circle/Point/入口A
spots-circle/Point/休憩所
spots-circle/Point/展望台
route-line/LineString/散歩道
route-line/LineString/散歩道
area-line/Polygon/公園エリア
area-line/Polygon/池
area-line/Polygon/公園エリア
area-fill/Polygon/公園エリア
area-fill/Polygon/池
area-fill/Polygon/公園エリア
同じ「公園エリア」が2回出るのは、GeoJSON も内部ではタイルに切って描くため、タイルの境目をまたぐ面が2つに分かれて返るからです。件数を数える用途では、properties の名前や ID で重複を除きます。
マーカー・ポップアップ・クリックイベントを付ける
この節では、地図に印を立てる・吹き出しを出す・クリックした地物を知る、の3つの書き方と動いた結果が分かります。
地図の上の印には2通りあります。Marker は HTML の要素を地図の上に重ねる方法、circle や symbol のレイヤーは WebGL で地図と一緒に描く方法です。数個なら Marker、数百を超えるならレイヤーが向きます。
map.on('load', () => {
// 1. HTML のマーカー(クリックでポップアップ)
new maplibregl.Marker({ color: '#2a9d8f' })
.setLngLat([139.722, 35.684])
.setPopup(new maplibregl.Popup().setText('ゴール'))
.addTo(map);
// 2. レイヤーのクリック(第2引数にレイヤー ID)
map.on('click', 'spots-circle', (e) => {
const f = e.features[0];
console.log('click:', f.properties.name, 'rank=' + f.properties.rank);
new maplibregl.Popup().setLngLat(f.geometry.coordinates).setText(f.properties.name).addTo(map);
});
// 3. 指の形のカーソル
map.on('mouseenter', 'spots-circle', () => { map.getCanvas().style.cursor = 'pointer'; });
map.on('mouseleave', 'spots-circle', () => { map.getCanvas().style.cursor = ''; });
});
展望台の座標を map.project([139.705, 35.684]) で画面の位置に直し、Playwright でその位置をクリックしました。
click at [283.49, 192.62]
after click log ['load ms=761', 'click: 展望台 rank=4']
popup text ['展望台\n×']
markers 1
クリックした丸の properties(name と rank)がそのまま取れ、丸の上に「展望台」の吹き出しが出ました(「×」は閉じるボタンの文字)。.maplibregl-marker の要素は1個で、ゴールのマーカーが地図の上に重なっています。Mapbox GL JS では同じ部品が mapboxgl.Marker・mapboxgl.Popup、クラス名が .mapboxgl-marker になります。
イベントやレイヤーを足す処理は、上のように map.on('load', …) の中に書くのが基本形です。スタイルとデータを読み終えてから足すので、読み込みの順番に左右されません。
スタイル仕様(style.json)の読み方
この節では、Mapbox や MapLibre のスタイルJSONのどこに何が書いてあるかと、間違いを見つける方法が分かります。
Mapbox Studio で作ったスタイルも、MapLibre で書いたスタイルも、中身は同じ形のJSONです。読む順番は次の5つです。
- 1version:必ず 8スタイル仕様の版。無いと読み込めない
- 2sources:データの出どころvector・raster・geojson・image など。タイルの URL やファイルの場所を書く
- 3layers:描く順番(上ほど下に描かれる)背景→面→線→点→文字の順に並べるのが基本
- 4layout と paint:見た目layout は形や配置(線の端の形・文字の内容)、paint は色・太さ・透明度
- 5式(expressions):データやズームで変える["get", "rank"]・["match", …]・["interpolate", …, ["zoom"], …]
ほかに、文字を描くときのフォントの場所 glyphs、アイコン画像の sprite、初期表示の center・zoom を書けます。Mapbox のスタイルでは、ソースの URL が mapbox://mapbox.mapbox-streets-v8 のように mapbox:// で始まり、GL JS がトークンを付けた API の URL に直して読み込みます。
式は配列で書きます。この記事のスタイルでは、点の半径を ["*", 3, ["get", "rank"]](rank の3倍)、面の色を ["match", ["get", "kind"], "park", 緑, "water", 青, 灰]、線の太さをズーム12で2px・ズーム16で8pxになるよう interpolate で決めています。拡大するほど線が太くなるのは、この式のためです。
スタイルの誤りは、ブラウザで開く前に検査できます。MapLibre の依存として入る @maplibre/maplibre-gl-style-spec の gl-style-validate に、わざと4か所間違えたスタイルを渡しました。
$ node node_modules/@maplibre/maplibre-gl-style-spec/dist/gl-style-validate.mjs bad-style.json
bad-style.json:5: layers[0]: source "spot" not found
bad-style.json:6: layers[1].paint.fill-colour: unknown property "fill-colour"
bad-style.json:8: layers[3].paint.circle-radius: number expected, string found
$ echo $?
1
ソース名の綴り違い(spots を spot)、プロパティ名の綴り違い(color を colour)、数値を文字列の "5" で書いた誤りの3つが、行番号つきで見つかりました。終了コードは1なので、CI に入れて誤りのあるスタイルを止められます。4つ目に入れた「glyphs の無いスタイルで文字のレイヤーを使う」は、この検査では指摘されませんでした(次の節で、描画したときの結果を見ます)。
ベクタータイルとラスタータイルの違い(実測)
この節では、地図のタイルの2つの形がどう違い、データの量がどれくらい変わるかが分かります。
ラスタータイルは、256×256ピクセルなどに切った地図の「画像」です。ベクタータイルは、同じ範囲の道路・建物・境界などの「形と属性のデータ」で、ブラウザがスタイルに従ってその場で描きます。Mapbox Vector Tile(MVT)という形式が広く使われ、拡張子は .pbf や .mvt です。
先ほどの GeoJSON から、MapLibre の依存に入っている @maplibre/geojson-vt と @maplibre/vt-pbf でズーム10〜16のベクタータイルを作り、スタイルのソースを "type": "vector" に書き換えて表示しました。ベクタータイルのレイヤーを使うときは、どのデータ層を描くかを source-layer で指定します。
"sources": {
"local": { "type": "vector", "tiles": ["http://127.0.0.1:18123/tiles/{z}/{x}/{y}.pbf"], "minzoom": 10, "maxzoom": 16 }
},
"layers": [
{ "id": "spots-circle", "type": "circle", "source": "local", "source-layer": "spots", "paint": { "circle-radius": 6 } }
]
| 計測したもの | 結果 | メモ |
|---|---|---|
| 作ったベクタータイル | 43枚・合計 6,077 バイト | ズーム10〜16、点・線・面の3層 |
| ズーム14の表示で読み込んだタイル | 6枚・1,629 バイト | 1枚 41〜339 バイト |
| ズーム16に拡大して追加で読んだタイル | 6枚・922 バイト | 拡大しても形はなめらか |
| 同じ範囲の描画結果を PNG にした大きさ | 256×256 で 6,456 バイト | ラスタータイル1枚に相当 |
| 画面全体(800×500)の PNG | 25,348 バイト | ベクターの6枚の約16倍 |
この実験のデータは単純な図形なので差が大きく出ていますが、傾向は実際の地図でも同じです。ベクタータイルは、拡大・回転・傾けても文字や線がにじまず、色の変更もタイルを作り直さずにスタイルだけで済みます。そのぶん、描くのにブラウザの WebGL が要り、性能の低い端末では重くなることがあります。ラスタータイルは画像を並べるだけなので、どの端末でも同じ見た目で軽く表示できます。
前の節で検査を通り抜けた「glyphs の無い文字レイヤー」も、この環境で描画しました。MapLibre GL JS 6.16.0 では、glyphs を書かなくても点の横に「入口A」「展望台」「休憩所」の文字が出ました。ただし、文字の形は端末にあるフォントで変わる可能性があるため、公開する地図では glyphs にフォントの URL を書いて、どの端末でも同じ文字が出るようにするのが確実です。Mapbox のスタイルでは、Studio で選んだフォントが mapbox://fonts/… として glyphs に入ります。
Mapbox GL JSをトークンなしで動かすとどうなるか
この節では、Mapbox GL JS がトークンなしでどこまで動き、どんなエラーを出すかが分かります。
npm で入れた mapbox-gl 3.34.1 を同じページの形で読み込み、トークンを設定せずに2通りで試しました。外部への通信は遮断する設定にし、Mapbox のサーバーには何も送っていません(遮断の記録は2通りとも0件で、送る前に止まっています)。
1つ目は、style を省いて(既定の Mapbox Standard を使う形で)new mapboxgl.Map() を呼んだ場合です。地図を作る段階で例外が出ました。
An API access token is required to use Mapbox GL. See https://docs.mapbox.com/api/overview/#access-tokens-and-token-scopes
2つ目は、style に先ほどの自作の style.json(Mapbox のタイルを使わないもの)を渡した場合です。load イベントまでは進みましたが、その直後に error イベントが出ました。
['load', 'error: A valid Mapbox access token is required to use Mapbox GL JS. To create an account or a new access token, visit https://account.mapbox.com/']
自前のデータだけを描く場合でも、v2 以降の Mapbox GL JS には有効なトークンが要ります。前の節で見たライセンスの条件どおりの動きです。トークンを使わずに描きたい、または Mapbox 以外のタイルを使いたい場合は MapLibre GL JS を選びます。
ライブラリの大きさも測りました。MapLibre は本体と Worker の2ファイル、Mapbox は1ファイルにまとまっています。
| ファイル | そのまま | gzip -9 |
|---|---|---|
| maplibre-gl.mjs + maplibre-gl-worker.mjs(6.16.0) | 1,627,421 バイト | 440,885 バイト |
| mapbox-gl.js(3.34.1) | 1,916,067 バイト | 524,276 バイト |
| maplibre-gl.css/mapbox-gl.css | 71,596/48,904 バイト | 10,180/5,769 バイト |
どちらも圧縮して400〜500KB台あります。地図を出さないページでは読み込まない(地図の画面だけで動的に import する)作りにすると、ほかのページが軽くなります。
よくあるエラー・つまずき(原文つき)
この節では、Mapbox や MapLibre で地図が出ないときに見かけるエラーの原文と、原因・直し方が分かります。
次の表の原文は、この記事の環境で実際に出たものです(トークンの403は公式ドキュメントの記述)。
| 出た文言(原文) | 原因 | 直し方 |
|---|---|---|
| An API access token is required to use Mapbox GL. | Mapbox GL JS にトークンを設定していない | mapboxgl.accessToken を new Map の前に設定。環境変数が undefined でないか確かめる |
| A valid Mapbox access token is required to use Mapbox GL JS. | 自前のスタイルでもトークンは要る | 有効な pk. トークンを入れる。トークン不要にするなら MapLibre へ |
| 403: Forbidden(タイル・スタイルの取得) | トークンの URL 制限に今のページの URL が無い・スコープ不足 | Console でトークンの URL 制限とスコープを見直す |
| Access to fetch at '…/spots.geojson' from origin '…' has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested resource. | 別のオリジン(ポート違いも別)の GeoJSON・タイルを読んだ | データを返す側に Access-Control-Allow-Origin を付けるか、同じオリジンから配る |
| AJAXError: Failed to fetch (0): http://127.0.0.1:18124/spots.geojson | 上の CORS などで取得に失敗したときに地図の error イベントに届く文言 | ブラウザのコンソールとネットワークのタブで本当の原因を見る |
| WebGL2 is required to display this map. | ブラウザで WebGL2 が使えない(無効化・性能の低い端末・リモート環境) | ハードウェアアクセラレーションを有効にする。使えない端末向けに静的画像を用意 |
| The requested module './lib/maplibre-gl.mjs' does not provide an export named 'default' | ES モジュール版を import maplibregl from で読んだ |
import * as maplibregl from に直す |
CORS のエラーは、MapLibre の error イベントでは「AJAXError: Failed to fetch (0)」としか届かず、理由はブラウザのコンソールにだけ出ました。今回は同じ 127.0.0.1 でもポート(18123 と 18124)が違うだけで別のオリジンとして扱われ、そのソースの点だけが描かれず、ほかのレイヤーは表示されました。CORS の仕組みと文言別の直し方は、関連記事「CORSエラーの原因と解決方法|エラーメッセージ別に解説」で扱っています。
WebGL2 のエラーは、Chromium を --disable-webgl と --disable-3d-apis を付けて起動して再現しました。メッセージの全文は「We are sorry, but it seems that your browser does not support WebGL2, a technology for rendering 3D graphics on the web.」と続き、このとき地図の要素には何も描かれません。社内の仮想デスクトップや以前の世代のノートPCで「地図だけ真っ白」と言われたら、まずこれを疑います。
エラーにならないつまずきもあります。
- 1経度と緯度が逆GeoJSON と center は [経度, 緯度]。逆にすると海の上や別の大陸に表示される
- 2地図の要素の高さが0container に高さが無いと何も見えない。CSS で height を指定する
- 3CSS を読み込んでいないmaplibre-gl.css/mapbox-gl.css が無いと、ボタンやポップアップの位置が崩れる
- 4レイヤーを足す場所addLayer・Marker・クリックの登録は map.on('load') の中にまとめる
- 5React で地図が2つできる開発時の StrictMode で useEffect が2回動く。片付けで map.remove() を呼ぶ。Mapbox ではロード数も増える
判断表:Mapbox・Google Maps・MapLibre・Leafletのどれを選ぶか
この節では、作りたいものに合わせて、どの地図の仕組みを選べばよいかが分かります。
| 作りたいもの・条件 | 向く選択 | 理由 |
|---|---|---|
| デザインを作り込んだ地図+検索・経路をまとめて使いたい | Mapbox | Studio・GL JS・Search・Directions が1つのアカウントでそろう |
| 店舗や施設の情報(口コミ・営業時間)を出したい | Google Maps Platform | Places の施設情報と、見慣れた Google マップの見た目 |
| 月数万ロードで、地図の表示費用を抑えたい | Mapbox か MapLibre+タイル提供元 | Mapbox は月5万ロードまで無料。Google は月1万回を超えると課金 |
| トークンなし・社内ネットワークだけで地図を出したい | MapLibre GL JS+自前のタイル/GeoJSON | この記事の実物のとおり、外部への通信0件で描ける |
| ライセンスをオープンソースにそろえたい | MapLibre GL JS か Leaflet | BSD ライセンス。Mapbox GL JS v2以降は独自ライセンス |
| ピンを数個立てるだけの簡単な地図 | Leaflet+タイル提供元 | 書き方が少なく軽い。WebGL が無い端末でも動く |
| 大量の点(数万件)や3Dの建物を滑らかに描きたい | Mapbox か MapLibre | WebGL とベクタータイルで、拡大・回転してもなめらか |
迷ったら、まず MapLibre GL JS と自前の GeoJSON で画面を作り、背景地図が必要になった時点でタイルの提供元(Mapbox、MapTiler などの商用サービス、自前のタイル)を選ぶ順番にすると、書いたコードとスタイルを捨てずに済みます。Mapbox を選ぶ場合も、スタイル仕様と式の書き方はそのまま使えます。
よくある質問
この節では、Mapbox について検索でよく調べられる疑問への短い答えが分かります。
Q. Mapbox は無料で使えますか?
無料枠の範囲なら費用はかかりません。Web の地図は月50,000ロード、モバイルの地図は月25,000 MAU、Directions API は月100,000リクエストまで無料です(2026年10月29日時点)。超えた分は従量課金になり、アカウントとトークンは無料枠の範囲でも要ります。
Q. Mapbox の読み方は?
「マップボックス」です。日本法人は Mapbox Japan(マップボックス・ジャパン)です。
Q. Map Load は何をすると増えますか?
地図がページの中で初期化されるたびに1回です。拡大・移動などの操作では増えません。ページの再読み込み、別のページへの移動、React などで地図を作り直すと増えます。
Q. Mapbox と Google Maps はどちらが安いですか?
地図の表示だけを比べると、月5万ロードまでは Mapbox が0円、Google の Dynamic Maps は1万回を超えると課金されます。月10万ロードでは Mapbox が$250、Google が$630です(2026年10月29日時点の公式料金から計算)。検索や経路の API を使う場合は、使う API を並べて計算し直します。
Q. MapLibre は Mapbox の代わりになりますか?
描画ライブラリとしてはなります。スタイル仕様(version 8)、Marker・Popup・イベントの書き方はほぼ共通です。ただし MapLibre は地図データを持たないため、背景の地図はタイルの提供元を別に選びます。Mapbox Standard や Mapbox 独自の新しい機能は使えません。
Q. MapLibre から Mapbox のタイルを使えますか?
Mapbox の利用規約とライセンスの条件が関わるため、使う前に Mapbox の公式の規約を確かめます。この記事では試していません。
Q. トークンをページに書いて公開しても平気ですか?
公開スコープだけの pk. トークンは、ブラウザで使う前提のものです。ただし見られる前提で扱い、用途ごとに作る・URL 制限を付ける・漏れたら差し替える、の3つを守ります。sk. のトークンはサーバーだけで使います。
Q. 日本の住所検索や日本語の地名は使えますか?
Mapbox の公式ドキュメントには日本向けの検索ボックスの例があり、日本語の公式サイトとドキュメントもあります。精度や対応範囲は用途で変わるため、無料枠の範囲で実際の住所を試して確かめます。
Q. オフラインで地図を出せますか?
MapLibre GL JS なら、この記事のようにタイルや GeoJSON を自分のサーバーに置けば外部への通信なしで描けます。OpenStreetMap 公式のタイルサーバーからの一括ダウンロードは利用方針で禁止されているため、自前でタイルを作るか、オフライン利用を認める提供元を使います。
Q. 地図が真っ白で何も出ません。
順に、コンソールのエラー(トークン・CORS・WebGL2)、地図の要素の高さ、CSS の読み込み、座標の経度と緯度の順番を見ます。エラーが無く真っ白なら、要素の高さが0のことが多くあります。
Q. npm で入れるときのコマンドは?
Mapbox は npm install mapbox-gl、MapLibre は npm install maplibre-gl です。npm のコマンドと package.json の書き方は、関連記事「npm コマンド 一覧|package.json 書き方と実行結果・npm 12対応」で扱っています。
まとめ
この節では、この記事の要点が5つで分かります。
- Mapbox は地図・検索・経路を組み込む開発基盤で、Web の中心は Mapbox GL JS とスタイルJSON、見た目は Studio で作れる。
- 料金は製品ごとの無料枠+従量課金。Web の地図は月5万ロード無料、超過は1,000ロード$5から(2026年10月29日時点)。地図の表示だけなら、月10万ロードで Google の約4割の費用になる計算。
- Mapbox GL JS v2以降は独自ライセンスで、トークンが必須。自前のスタイルでも「A valid Mapbox access token is required」と出た。
- 互換の MapLibre GL JS なら、トークンなし・外部通信0件で地図を描ける。GeoJSON とスタイルJSON、Marker・Popup・クリックが同じ考え方で動いた。
- 地図が出ないときは、トークン・CORS・WebGL2・import の書き方・要素の高さ・経度緯度の順に見る。スタイルの誤りは gl-style-validate で行番号つきで見つかる。
参考・出典
この節では、この記事で確かめた公式の情報の出どころが分かります(確認日 2026年10月29日)。
- Mapbox「Mapbox のはじめ方」:https://docs.mapbox.com/help/ja/getting-started/
- Mapbox「Pricing」:https://www.mapbox.com/pricing
- Mapbox「Pricing(Accounts guide)」:https://docs.mapbox.com/accounts/guides/pricing/
- Mapbox「Access tokens」:https://docs.mapbox.com/accounts/guides/tokens/
- Mapbox「Mapbox GL JS installation」:https://docs.mapbox.com/mapbox-gl-js/guides/install/
- Mapbox「Display a map」(GL JS の例):https://docs.mapbox.com/mapbox-gl-js/example/simple-map/
- Mapbox「Studio manual」:https://docs.mapbox.com/studio-manual/guides/
- Mapbox GL JS「LICENSE.txt」:https://github.com/mapbox/mapbox-gl-js/blob/main/LICENSE.txt
- MapLibre GL JS(GitHub):https://github.com/maplibre/maplibre-gl-js
- Google Maps Platform「Pricing」:https://developers.google.com/maps/billing-and-pricing/pricing
- Google Maps Platform「March 2025 changes」:https://developers.google.com/maps/billing-and-pricing/march-2025
- Leaflet「Download」:https://leafletjs.com/download.html
- OpenStreetMap Foundation「Tile Usage Policy」:https://operations.osmfoundation.org/policies/tiles/
本記事の内容は、ご自由にお使いください。
ご利用の際は、出典として本ページへのリンクを記載いただけますようお願いします。
(記載例)出典:株式会社RJC「Mapboxとは?料金・使い方とGoogle Maps・MapLibreとの違い」
株式会社RJC ― SI事業・SES事業・AI駆動開発。RJCは一緒に成長を楽しめる会社です。
WE ARE HIRING
RJCで一緒に開発しながら、
成長を楽しみませんか?
RJCは、Web・モバイル・AIを活用した開発プロジェクトで、テックリードやPM・PMOも活躍するシステム開発会社です。会社を知る、待遇を確かめる、話を聞いてみる。気になるところ見てみてください!
- 127日年間休日
- 12時間平均残業時間
- 毎日ガチャ遊びココロも大切にする福利厚生。アマギフなどの賞品ラインナップ!
ほかにも、チケットレストラン、書籍読み放題、2年ごとの慰労報奨(休暇 or 金一封)、11期連続の黒字決算。