PMTiles: Cloud-Native Tile Format for Modern Maps
Traditional tile servers require a constantly running backend: nginx or a specialized tile server distributes tiles from a directory or database. PMTiles changes this paradigm — one file, static hosting, no servers needed.
What is PMTiles
PMTiles (Protomaps Tiles) is a cloud-native format for storing map tiles in a single file. The key idea is HTTP Range Requests. The client requests only the needed bytes from the file rather than downloading it entirely. This means a PMTiles file can be hosted on any static server: Amazon S3, Cloudflare R2, GitHub Pages, or plain nginx.
The format supports both raster tiles (PNG, JPEG, WebP) and vector tiles (MVT — Mapbox Vector Tiles). Inside the file is a binary tree of indices that locates any tile in O(log n) operations.
Technical specifications:
- Header size: 127 bytes fixed + variable-length directory.
- Compression: gzip or brotli for directory and tiles.
- Zoom levels: from z0 (entire world) to z22 (individual buildings).
- Maximum size: no theoretical limit (practically tens of GB).
PMTiles vs MBTiles: Comparison
MBTiles is a SQLite database containing tiles. The format appeared earlier and is widely supported, but it has limitations:
| Criterion | PMTiles | MBTiles |
|---|---|---|
| Hosting | Static (S3, CDN) | Requires tile server |
| Protocol | HTTP Range Requests | Local SQLite reads |
| Header size | 127 bytes | SQLite overhead (~100 KB) |
| Streaming | Yes, any HTTP server | No, needs tileserver-gl |
| Browser support | Native (JS library) | Only via proxy |
| Offline on device | Limited | Good (SQLite is native) |
If your goal is offline maps on a mobile device, MBTiles is still more convenient. If you need to serve maps via CDN for a web application, PMTiles wins.
Using with MapLibre GL JS
MapLibre GL JS supports PMTiles through the official plugin:
import { Protocol } from 'pmtiles';
import maplibregl from 'maplibre-gl';
const protocol = new Protocol();
maplibregl.addProtocol('pmtiles', protocol.tile);
const map = new maplibregl.Map({
container: 'map',
style: {
version: 8,
sources: {
osm: {
type: 'vector',
url: 'pmtiles://https://example.com/map.pmtiles'
}
},
layers: [
{
id: 'buildings',
source: 'osm',
'source-layer': 'buildings',
type: 'fill',
paint: { 'fill-color': '#ccc' }
}
]
}
});
For Leaflet, the protomaps-leaflet plugin renders vector tiles directly to Canvas.
Exporting PMTiles from OSM
On osm2cdr.ru, select the desired area on the map, choose the PMTiles format, and specify zoom levels. The service will generate a file with vector tiles containing roads, buildings, water bodies, green areas, and other OpenStreetMap layers.
The resulting file can be hosted anywhere:
# Upload to S3
aws s3 cp moscow.pmtiles s3://my-bucket/tiles/ \
--content-type application/vnd.pmtiles
# Or to Cloudflare R2
wrangler r2 object put tiles/moscow.pmtiles \
--file moscow.pmtiles
For local viewing, use pmtiles serve:
npx pmtiles serve moscow.pmtiles --port 8080
Conclusion
PMTiles is the future of tile-based maps. One file instead of a tile server, CDN instead of infrastructure, Range Requests instead of millions of small files. Export your OpenStreetMap data to PMTiles at osm2cdr.ru and deploy your own map in 5 minutes.