Skip to content

Tile Serving

Yoro Maps can download and serve map tiles offline, stored in MBTiles format inside the .yoromaps database.

How tiles work

Map tiles are small PNG images that cover the world at different zoom levels. At zoom 0, the entire world is one tile. At zoom 12, there are millions of tiles. Yoro Maps downloads only the tiles within a country's bounding box and stores them in the tiles table.

The tiles table uses the MBTiles specification with TMS (flipped Y) coordinate scheme.

Download tiles during build

CLI

# Build with tiles (default zoom 6-12)
yoromaps download ML --output mali.yoromaps --tiles

# Custom zoom range
yoromaps download ML --output mali.yoromaps --tiles --zoom-min 8 --zoom-max 14

Python

import yoromaps

yoromaps.build("ML", "mali.yoromaps", include_tiles=True, zoom_max=14)

Tile download size

Higher zoom levels = exponentially more tiles. Zoom 14 for a large country like Mali can be 500+ MB and take hours to download. Start with zoom 12 and increase if needed.

Download tiles separately

You can add tiles to an existing .yoromaps database:

from yoromaps.db import open_db
from yoromaps.tiles import download_tiles
from yoromaps.countries import COUNTRIES

conn = open_db("mali.yoromaps")
country = COUNTRIES["ML"]

n = download_tiles(
    conn,
    bbox=country.bbox,
    zoom_min=6,
    zoom_max=12,
    tile_url="https://tile.openstreetmap.org/{z}/{x}/{y}.png",
    progress=lambda msg, cur, tot: print(f"{msg}: {cur}/{tot}"),
)
print(f"Downloaded {n} tiles")

Custom tile providers

The default tile source is OpenStreetMap. You can use any XYZ tile server by changing the URL template:

from yoromaps.tiles import download_tiles

# OpenStreetMap (default)
download_tiles(conn, bbox, tile_url="https://tile.openstreetmap.org/{z}/{x}/{y}.png")

# OpenTopoMap
download_tiles(conn, bbox, tile_url="https://tile.opentopomap.org/{z}/{x}/{y}.png")

# Stamen Terrain (Stadia Maps)
download_tiles(conn, bbox, tile_url="https://tiles.stadiamaps.com/tiles/stamen_terrain/{z}/{x}/{y}.png")

Note

Respect tile server usage policies. OpenStreetMap requires a valid User-Agent header (yoromaps sets one automatically) and limits bulk downloads. For large-scale use, consider running your own tile server.

Serve tiles from Django

With the Django integration configured, tiles are served at:

GET /maps/tiles/{z}/{x}/{y}.png

See the Django Integration guide for setup details.

Serve tiles from Python

You can retrieve tiles directly from the database:

from yoromaps.db import open_db
from yoromaps.tiles import get_tile

conn = open_db("mali.yoromaps")

# Get a tile (XYZ scheme — the function handles TMS conversion internally)
tile_data = get_tile(conn, z=10, x=512, y=512)

if tile_data:
    with open("tile.png", "wb") as f:
        f.write(tile_data)

Check tile count

from yoromaps.db import open_db
from yoromaps.tiles import tile_count

conn = open_db("mali.yoromaps")
print(f"Tiles in database: {tile_count(conn)}")

Or from the CLI:

yoromaps info mali.yoromaps

Rate limiting

The tile downloader includes built-in rate limiting (50ms between requests) and sets a proper User-Agent header. Tiles that already exist in the database are skipped, so you can safely re-run the download to fill in missing tiles.

Zoom level guide

Zoom Coverage Tiles per country Use case
6 Region overview ~50 Country-level view
8 City overview ~500 Regional navigation
10 Neighborhood ~5,000 City navigation
12 Street level ~50,000 Street-level detail
14 Building level ~500,000 High detail

Exact counts depend on the country's geographic area.