Introduction: What is the MBTiles format?
The MBTiles format is a file format for storing map tiles (raster or vector) in a SQLite database, a lightweight, stand-alone database engine.
Initially designed by Mapbox, this format has been widely adopted in the GIS, cartographic and web mapping communities for its portability, ease of use and compatibility with numerous tools.
In practical terms, an .mbtiles file is a single database that can contain thousands, even millions of geographic tiles organized by zoom levels, columns and rows. This avoids the need for a complex tree structure of files on disk, while facilitating distribution (on the web, via USB, or in disconnected mode).
The MBTiles format can contain :
- Raster tiles (usually PNG or JPEG),
- Or vector tiles (in MVT – Mapbox Vector Tiles – format),
- And metadata (description, attribution, format, etc.).
Thanks to its SQLite format, MBTiles can be easily read with tools such as sqlite3, DB Browser for SQLite, or operated via lightweight servers (such as Flask or TileServer-PHP), making it highly suitable for training, demonstrations or off-line use.
Internal structure of an MBTiles file
An MBTiles file is a SQLite database structured according to a simple, standardized schema, which allows you to efficiently store map tiles in raster (PNG, JPEG) or vector (PBF) format.
1. The main tables
According to the official specification (https://github.com/mapbox/mbtiles-spec), an .mbtiles file contains at least :
a) tiles
This is the central table. It contains the encoded tiles, each identified by its zoom coordinates, column (x) and line (y):
CREATE TABLE tiles (
zoom_level INTEGER,
tile_column INTEGER,
tile_row INTEGER,
tile_data BLOB
);
Note: MBTiles use the TMS (Tile Map Service) coordinate system, which means that the vertical axis (Y) is inverted in relation to the XYZ scheme used by Leaflet. Some servers or viewers correct this automatically.
b) metadata
This table contains general information about the file and the tiles it contains, such as :
CREATE TABLE metadata (
name TEXT,
value TEXT
);
Some common fields :
- name: name of tile set;
- format: tile format (png, jpg, pbf);
- minzoom, maxzoom: zoom levels available;
- bounds: geographic extent (minlon,minlat,maxlon,maxlat) ;
- center: map center coordinates (lon,lat,zoom) ;
- type: map type (baselayer, overlay);
- description: explanatory text.
2.Indexing
MBTiles files can include indexes to speed up tile access, but this is not mandatory.
3.Other views and variants
Some tools (such as MapTiler or TileMill) generate additional views or alternative schemas, such as the map view associated with an image table in an optimized format (tile deduplication).
Example:
CREATE TABLE images (
tile_id TEXT,
tile_data BLOB
);
CREATE TABLE map (
zoom_level INTEGER,
tile_column INTEGER,
tile_row INTEGER,
tile_id TEXT
);
This allows each image to be stored only once, even if it is used at several coordinates.
Here’s a clear comparative section between the two types of content that the MBTiles format can store:
Raster vs. Vector: Two types of tiles in MBTiles files
The MBTiles format is versatile: it can contain raster tiles (images) or vector tiles (encoded geographic data). Each approach has its advantages and is suitable for different use cases.
1.MBTiles Raster
- Content: PNG or JPEG images (rarely WebP).
- Use: pre-rendered backgrounds, static maps, historical maps, orthophotos, etc.
- Declared format: format field = png or jpg in metadata table.
- Display: directly compatible with most libraries such as Leaflet, OpenLayers or MapLibre, via a tile server (local or remote).
- Advantages:
- Very simple to implement.
- Consistent rendering on all platforms.
- No client-side processing.
- Limitations:
- No native interactivity (no click on entity).
- Higher weight: one image per tile.
- Less flexible in case of style changes.
2.Vector MBTiles (VectorTiles)
- Contents: vector data encoded in Mapbox Vector Tile (MVT, .pbf) format.
- Use: dynamic, interactive, multi-style maps (OpenStreetMap, custom maps).
- Declared format: format = pbf field in metadata table.
- Display: requires a library supporting vector rendering (MapLibre GL, Mapbox GL JS, etc.).
- Advantages :
- Lightweight: a single file can contain several styles.
- Very fast to load with the right rendering engine.
- Interactive: entities can be queried on the fly.
- Limitations:
- Requires a client-side renderer or a server such as tileserver-gl.
- More complex to generate.
- Not yet supported by all platforms (e.g. Leaflet does not support them directly).
In a nutshell
Features | Raster | Vector |
---|---|---|
Tile format | PNG, JPEG | PBF (MVT) |
Rendering | Pre-rendered, fixed | Dynamic, stylable |
Interactivity | No | Yes |
Compatibility | Very wide | More restricted |
Size | Heavier | Lighter on large scale |
Styling requirements | None (rendering included) | Requires JSON styling |
Generating MBTiles files: tools and workflows
1.MBTiles Raster (images)
Raster tiles are generally generated from a map displayed in GIS software or a cartographic rendering engine. Here are the main tools:
Tool | Description | Type |
---|---|---|
QGIS | Plugin « Export as tiles » (or Processing → Generate XYZ tiles ) |
Graphical interface |
GDAL | gdal2tiles.py with option --mbtiles (since GDAL 3.1) |
Command line |
TileMill (old) | Creation of PNG tiles via Mapnik | Graphical interface |
MapTiler Desktop | Full interface for creating MBTiles (limited free version) | Graphical interface |
tippecanoe + rasterize | Hybrid workflow: rasterize upstream if required | Command line |
MapProxy | Generates dynamically and can export to MBTile | Server/cache |
Typical use case: tourist map, orthophoto, scanned map.
MBTiles (Vector Tiles)
Vector tiles require encoding in PBF and cutting into tiles according to the MVT (Mapbox Vector Tile) standard. This requires specialized tools:
Tool | Description | Format MBTiles |
---|---|---|
tippecanoe (Mapbox) | Reference tool for converting GeoJSON to PBF tiles in an MBTiles | Yes |
tilemaker | Generates vector tiles directly from an OSM PBF | Yes |
PostGIS + ST_AsMVT | Export tiles manually with SQL scripts → storage in MBTiles via mb-util | With script |
OpenMapTiles | Complete chain with Docker, based on PostgreSQL/PostGIS + imposm3 + tippecanoe | Yes |
MapTiler Desktop | Also allows vector export with integrated styles (Pro version) | Yes |
Typical applications: interactive city maps, customizable backgrounds, highly interactive projects.
Internal structure of an MBTiles file
An .mbtiles file is a SQLite database containing geographic tiles organized according to a standardized schema, which varies slightly between raster and vector formats.
1.Main tables
tiles (or map + images for multi-part vectors)
Field | Type | Description |
---|---|---|
zoom_level |
INTEGER | zoom level of tile |
tile_column |
INTEGER | column (x) of tile |
tile_row |
INTEGER | line (y) of tile (inverted TMS ↔ XYZ) |
tile_data |
BLOB | Binary image data or PBF |
Note: in vector format, some implementations such as tilemaker separate image metadata (images) and positions (map). In this case, a tiles view is created to combine them.
metadata
Key-value table (key = text, value = text) containing information essential for interpreting the file.
Key | Example value | Utility |
---|---|---|
name |
"Rodrigues Map" |
Readable name |
format |
"png" , "jpg" , "pbf" |
Tile type |
minzoom |
5 |
Minimum zoom level |
maxzoom |
14 |
Maximum zoom level |
bounds |
63.35,-19.9,63.5,-19.7 |
BBox (WGS84) |
center |
63.42,-19.8,12 |
Map center (lon, lat, z) |
type |
"baselayer" ou "overlay" |
Tile set role |
json |
JSON Mapbox (if vector) | Style, layers, fields |
attribution |
HTML text | Source to display |
(optional) grids
, grid_data
, keymap
Used for UTFGrid format, an obsolete form of interactivity in raster backgrounds.
Important notes
- The tile_row coordinates are often inverted, depending on the tile system:
- TMS (Tile Map Service): origin is bottom left.
- XYZ (Web standard): origin is top left.
- Most modern servers and viewers use XYZ.
- The tile_data field contains :
- A compressed image (png, jpg) for raster.
- A zlib-compressed PBF object for vector tiles.
- For vector tiles, the json field in metadata can contain:
- { “vector_layers”: [ { “id”: “buildings”, “description”: “”, “minzoom”: 12, “maxzoom”: 16, “fields”: { “name”: “String”, “height”: “Number” } } ] }
Using MBTiles with Leaflet
Leaflet is a popular JavaScript library for creating interactive maps. It supports the integration of many types of map backgrounds, including MBTiles. Here are typical steps and use cases for integrating MBTiles into a Leaflet map.
Prerequisites: A tile server
Before using MBTiles with Leaflet, you need to set up a tile server, as Leaflet does not load local MBTiles directly. This server will serve the tiles as images or in vector format, accessible via a URL.
There are various options for hosting MBTiles:
- TileStache
- Tileserver-GL
- Flask + Flask-tile (for lightweight installation)
- Tileserver-php
Once the server has been configured, it can distribute the tiles via HTTP, which Leaflet can call up to display them on the map.
MBTiles integration with Leaflet
Here’s a simple example of using a tile server with Leaflet to display data from an .mbtiles file:
Example with raster tiles
a)Launch the tile server
Go to the directory containing the raster tiles.
php.exe -S localhost:8081
launch the tile server

The following html page displays the contents of the tiles in the countries.mbtiles file located in the tiles/ subfolder. In the browser, enter the address localhost:8081/page_name.html
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title>Carte Mondiale</title>
<link rel="stylesheet" href="https://unpkg.com/leaflet/dist/leaflet.css" />
<style>
html, body, #map { height: 100%; margin: 0; }
</style>
</head>
<body>
<div id="map"></div>
<script src="https://unpkg.com/leaflet/dist/leaflet.js"></script>
<script>
var map = L.map('map').setView([45, 2], 5);
L.tileLayer('tileserver.php?file=tiles/countries.mbtiles&z={z}&x={x}&y={y}', {
tileSize: 256,
minZoom: 0,
maxZoom: 6,
attribution: '© OpenStreetMap contributors'
}).addTo(map);
</script>
</body>
</html>
The result is as follows:

Vector tiles (MBTiles PBF)
If you’re using a vector MBTiles file (e.g. generated by MapTiler or Mapbox), you’ll need to configure Leaflet with a plugin that can interpret vector tiles. Leaflet.VectorGrid is one of the plugins that can handle vector tiles in Leaflet.
Example with vector tiles (PBF)
<!DOCTYPE html>
<html lang="fr">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Carte Vectorielle MBTiles avec Leaflet</title>
<link rel="stylesheet" href="https://unpkg.com/leaflet@1.7.1/dist/leaflet.css" />
<script src="https://unpkg.com/leaflet@1.7.1/dist/leaflet.js"></script>
<script src="https://unpkg.com/leaflet.vectorgrid@1.1.0/dist/Leaflet.VectorGrid.js"></script>
</head>
<body>
<div id="map" style="height: 600px;"></div>
<script>
var map = L.map('map').setView([ -19.7, 63.35], 12); // Centré sur Rodrigues
// Charger les tuiles vectorielles MBTiles
L.vectorGrid.protobuf("http://localhost:8081/tileserver.php?file=tiles/map.mbtiles&z={z}&x={x}&y={y}", {
vectorTileLayerStyles: {
// Styles pour les tuiles vectorielles
building: {
fillColor: 'blue',
weight: 1,
fillOpacity: 0.6
},
park: {
fillColor: 'green',
weight: 1,
fillOpacity: 0.6
}
}
}).addTo(map);
</script>
</body>
</html>
In this example, the Flask or Tileserver-GL server is used to supply vector tiles, which Leaflet renders as vectors using L.vectorGrid.
However, this is not as simple as with raster tiles.
Symbology
The first difference is that vector tiles, unlike raster tiles, have no associated symbology at server level. You are therefore obliged to define the symbology at the html client level. You can see this in the example code above:
vectorTileLayerStyles: {
// Styles pour les tuiles vectorielles
building: {
fillColor: 'blue',
weight: 1,
fillOpacity: 0.6
},
park: {
fillColor: 'green',
weight: 1,
fillOpacity: 0.6
}
}
What’s also important to know is that there is no default symbology. If a layer has no symbology definition in vectorTileLayerStyles, it will not be displayed. In our example, only buildings and parks will be displayed, all other layers (roads, etc.) will be ignored.
Dependencies
Leaflet.VectorGrid has several dependencies that can complicate the operation of the local tile server. When we display an .mbtiles file converted to .pbf via tileserver.php (for example), we’re calling up raw vector tiles from a local PHP server, without the right headers or encodings. But :
- These tiles require pbf.js (which you can add: src=“https://unpkg.com/pbf@3.2.1/dist/pbf.js”)
- but also @mapbox/vector-tile to decode .pbf content.
However, the latter is not available as a .js file for direct use in an HTML page: it is written for Node.js or for a modern bundler (Webpack, Vite, etc.).
Encoding
The default PHP code in tileserver.php is configured to handle raster tiles (PNG images), but not vector tiles (.pbf).
You’ll need to adjust tileserver.php to serve vector tiles (PBF):
Modification of the Content-Type header:
For vector tiles, you need to specify a Content-Type header: application/x-protobuf, as vector tiles are Protobuf format files (.pbf), not PNG images.
Example of PHP code modified to serve vector tiles (PBF) :
<?php
// Ouverture de la base de données SQLite
$db = new SQLite3($_GET['file']);
// Extraction des coordonnées de la tuile
$z = (int) $_GET['z'];
$x = (int) $_GET['x'];
$y = (int) $_GET['y'];
// Conversion du système de coordonnées TMS vers XYZ
$y = (1 << $z) - 1 - $y; // TMS flip
// Préparation de la requête pour extraire la tuile correspondante
$stmt = $db->prepare("SELECT tile_data FROM tiles WHERE zoom_level = :z AND tile_column = :x AND tile_row = :y");
$stmt->bindValue(':z', $z, SQLITE3_INTEGER);
$stmt->bindValue(':x', $x, SQLITE3_INTEGER);
$stmt->bindValue(':y', $y, SQLITE3_INTEGER);
$res = $stmt->execute();
// Si une tuile est trouvée
if ($row = $res->fetchArray()) {
// Définir l'en-tête approprié pour les tuiles vectorielles Protobuf
header('Content-Type: application/x-protobuf');
// Retourner les données de la tuile
echo $row['tile_data'];
} else {
// Si aucune tuile n'est trouvée, renvoyer une erreur 404
http_response_code(404);
}
?>
Scalability and other uses
MBTiles are particularly useful in scenarios where :
- Performance is an important issue, as tiles can be distributed efficiently thanks to an optimized tile server.
- You want to distribute a large number of tiles offline, or in an environment with no Internet connection (pre-generated tiles stored in a single file).
- Tiles are generated from frequently changing data, and you can update or replace them with minimum disruption to end-users.
Conclusion
The MBTiles format is very well suited to Leaflet applications, offering a simple and efficient solution for serving geospatial tiles, whether raster or vector. With a lightweight installation and a well-configured tile server, it’s easy to display high-performance maps and manage large quantities of geospatial data.