Skip to content

Download & Build

This guide covers how to download OSM data and build .yoromaps files.

How it works

The build process:

  1. Download — Fetches the latest .osm.pbf file from Geofabrik for the chosen country.
  2. Extract — Parses the PBF in two passes using pyosmium: first collecting highway ways and node references, then resolving node coordinates.
  3. Build graph — Inserts nodes (intersections) and edges (road segments) into the SQLite database, with distance and estimated travel time.
  4. Points of interest — Reads the PBF again for named places (nodes and ways alike), assigns each one a Yoro code and writes it under source='osm'. On by default; --no-pois skips it. See Points of Interest.
  5. Tiles (optional) — Downloads map tiles from OpenStreetMap tile servers and stores them in MBTiles format.

CLI usage

Basic build

yoromaps download ML --output mali.yoromaps

With tiles

yoromaps download ML --output mali.yoromaps --tiles --zoom-max 14

Road graph only

yoromaps download ML --output mali.yoromaps --no-pois

Custom zoom range

yoromaps download BF --output bf.yoromaps --tiles --zoom-min 8 --zoom-max 12

Using an existing PBF file

If you already have a PBF file (e.g., downloaded manually from Geofabrik):

yoromaps download ML --output mali.yoromaps --pbf /data/mali-latest.osm.pbf

List available countries

yoromaps countries

Python API

Basic build

from yoromaps.download import build

build("ML", "mali.yoromaps")

With tiles and progress

from yoromaps.download import build


def on_progress(message, current, total):
    if total > 0:
        print(f"{message}: {current / total * 100:.0f}%")
    else:
        print(message)


build(
    "ML",
    "mali.yoromaps",
    include_tiles=True,
    zoom_min=6,
    zoom_max=14,
    progress=on_progress,
)

Using an existing PBF

from yoromaps.download import build

build("ML", "mali.yoromaps", pbf_path="/data/mali-latest.osm.pbf")

Download PBF only

from yoromaps.download import download_pbf

pbf_path = download_pbf("ML", "/tmp/downloads")
print(f"Downloaded to: {pbf_path}")

Road types

The extractor recognizes these OSM highway types, with estimated speeds used for routing duration:

Highway type Speed (km/h)
motorway 110
motorway_link 60
trunk 90
trunk_link 50
primary 70
primary_link 40
secondary 60
secondary_link 35
tertiary 50
tertiary_link 30
residential 30
unclassified 40
living_street 20
service 20
track 15
path 5

Three more tags change who may use a road, and how fast:

  • One-way (oneway=yes/-1, roundabouts, motorways): both directions are written, and the one against the flow is closed to cars, motorcycles and bicycles. Walking is never bound by it; a bicycle is let through where oneway:bicycle=no or a contraflow lane says so.
  • Access (access, vehicle, motor_vehicle, motorcar, motorcycle, bicycle, foot, motorroad): the most specific tag present decides for each mode. no, private, agricultural, forestry, emergency, psv, customers and delivery close the way to that mode.
  • Surface: caps the speed per mode at query time (OSRM's values), so a dirt primary is not costed like asphalt. An untagged road is not assumed to be dirt.

Updating an existing database

After the initial download, use update to refresh the road graph with the latest OSM data. Only re-downloads if Geofabrik has published a newer PBF file.

CLI

# First time: re-downloads (no previous date stored)
yoromaps update mali.yoromaps

# Second time: skips if nothing changed
yoromaps update mali.yoromaps
# → "Already up to date" — instant, no download

# Custom PBF cache directory
yoromaps update mali.yoromaps --cache-dir /data/pbf-cache

Python API

import yoromaps

result = yoromaps.update("mali.yoromaps")

if result["updated"]:
    print(f"Updated: {result['nodes']:,} nodes, {result['edges']:,} edges")
    print(f"Previous: {result['previous_date']}")
    print(f"New:      {result['new_date']}")
else:
    print(f"Already up to date (since {result['previous_date']})")

What happens during an update

  1. Checks osm_update_date in the database metadata
  2. Sends HTTP If-Modified-Since to Geofabrik — if the PBF hasn't changed, stops immediately (no download)
  3. If newer data exists, downloads the new PBF
  4. Clears the road graph (nodes + edges tables)
  5. Re-extracts from the new PBF
  6. Preserves all POI data and tiles — only the road graph is rebuilt

Automate updates

Set up a cron job or Django management command to run yoromaps.update() weekly:

# management/commands/update_maps.py
from django.core.management.base import BaseCommand
import yoromaps


class Command(BaseCommand):
    def handle(self, **options):
        result = yoromaps.update("/data/mali.yoromaps")
        if result["updated"]:
            self.stdout.write(f"Updated: {result['nodes']:,} nodes")
        else:
            self.stdout.write("Already up to date")

File sizes

Tested file sizes (road graph only, no tiles):

Country PBF size Nodes Edges .yoromaps size Build time
Togo 59 MB 2.2M 2.3M 436 MB ~55s
Mali 163 MB 6.4M 6.7M 1.3 GB ~145s

Adding tiles at zoom 6-14 adds 200-500 MB depending on the country area.

Note

File sizes depend on OSM data completeness. Countries with more mapped roads produce larger databases.