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:

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

running localhost tileserver.php

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: '&copy; OpenStreetMap contributors'
    }).addTo(map);
</script>
</body>
</html>

The result is as follows:

map example mbtiles leaflet

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.

Si cet article vous a intéressé et que vous pensez qu'il pourrait bénéficier à d'autres personnes, n'hésitez pas à le partager sur vos réseaux sociaux en utilisant les boutons ci-dessous. Votre partage est apprécié !

Leave a Reply

Your email address will not be published. Required fields are marked *