Skip to main content

Valhalla Python bindings

pyvalhalla version

This folder (src/bindings/python) contains the Python bindings for the Valhalla routing engine.

On top of the (very) high-level Python bindings, we package some data-building Valhalla executables to ease the process of graph creation or run Valhalla as a service, see below.

Installation

We publish CPython packages as binary wheels for Win (amd64), MacOS (arm64) and Linux (x86_64/aarch64) distributions with glibc>=2.28. To decrease disk footprint of the PyPI releases, we only publish a single abi3 wheel per platform, which requires Python >= 3.12. To install on Python < 3.12, make sure to install the system dependencies as described in the docs before trying a pip install pyvalhalla.

Or manually in the current Python environment with e.g.

git clone https://github.com/valhalla/valhalla
cd valhalla
pip install .

In case you need to do a source installation (from sdist), follow the build instructions for your platform to install the needed dependencies. Then a simple pip install pyvalhalla should work fine for Linux/OSX. On Windows one needs to install C++ developer tools, see also below in the developer notes for external vcpkg usage to resolve dependencies.

Typing support

We (try to) include full typing support for pyvalhalla. If you're using mypy with strict typing policies, you'll need to install pyvalhalla appropriately with pip install pyvalhalla[typing].

Usage

Bindings

Find a more extended notebook in ./examples, e.g. how to use the actor.

Before using the Python bindings you need to have access to a routable Valhalla graph. Once you installed the pyvalhalla package you can create one with

wget https://download.geofabrik.de/europe/andorra-latest.osm.pbf
python -m valhalla valhalla_build_tiles -c <valhalla.json> andorra-latest.osm.pbf

Once you have created a graph locally, you can use it like this:

from valhalla import Actor, get_config, get_help

# generate configuration
config = get_config(tile_extract='./custom_files/valhalla_tiles.tar', verbose=True)

# print the help for specific config items (has the same structure as the output of get_config()
print(get_help()["service_limits"]["auto"]["max_distance"])

# instantiate Actor to load graph and call actions
actor = Actor(config)
route = actor.route({"locations": [...]})

Error Handling

When a routing operation fails, a ValhallaError is raised (a subclass of RuntimeError) with structured fields from Valhalla's internal error codes:

from valhalla import Actor, ValhallaError, get_config

actor = Actor(get_config(tile_extract='./valhalla_tiles.tar'))

try:
    actor.route({"locations": [{"lat": 0.0, "lon": 0.0}, {"lat": 0.1, "lon": 0.1}], "costing": "auto"})
except ValhallaError as e:
    print(e.code)          # 171
    print(e.message)       # "No suitable edges near location"
    print(e.http_code)     # 400
    print(e.http_message)  # "Bad Request"

Graph Utilities

Access to low-level graph data structures for advanced use cases:

from valhalla.baldr import GraphId
from valhalla.baldr.utils import GraphUtils

# Create a GraphId from its string representation or numeric value
edge_id = GraphId("2/421920/20")  # format: "level/tileid/id"
# or
edge_id = GraphId(674464020)

# Initialize GraphUtils with config (reuse for multiple queries)
# Accepts: file path (str/Path), JSON string, or dict
config = "/path/to/valhalla.json"
# or dict config
config = {"mjolnir": {"tile_extract": "/path/to/tiles.tar"}}
graph = GraphUtils(config)

# Get the polyline geometry for an edge
shape = graph.get_edge_shape(edge_id)

# shape is a list of (lon, lat) tuples
print(f"Edge has {len(shape)} coordinate points")
for lon, lat in shape:
    print(f"  ({lon:.6f}, {lat:.6f})")

# Convert to GeoJSON LineString
geojson = {
    "type": "Feature",
    "geometry": {
        "type": "LineString",
        "coordinates": [[lon, lat] for lon, lat in shape]
    }
}

Speed Compression Utilities

Valhalla uses DCT-2 (Discrete Cosine Transform) to compress historical speed profiles. These utilities allow you to work with compressed speed data:

import numpy as np
from valhalla.baldr.utils import (
    compress_speed_buckets,
    decompress_speed_bucket,
    encode_compressed_speeds,
    decode_compressed_speeds,
    BUCKETS_PER_WEEK,
    COEFFICIENT_COUNT,
)

# Compress 2016 speed buckets (7 days × 288 five-minute intervals)
speeds = np.full(BUCKETS_PER_WEEK, 50.0, dtype=np.float32)  # 50 KPH constant
coefficients = compress_speed_buckets(speeds)

# Decompress a specific bucket (e.g., Monday 10:00 AM)
bucket_idx = 120  # (24 hours × 12 buckets/hour) × 0 days + 10 × 12
speed = decompress_speed_bucket(coefficients, bucket_idx)

# Encode coefficients for storage/transmission
encoded = encode_compressed_speeds(coefficients)
print(f"Compressed to {len(encoded)} characters")

# Decode from string
coefficients_restored = decode_compressed_speeds(encoded)

Valhalla executables

C++ executables

To access the C++ (native) executables, there are 2 options:

  • (recommended) execute the module, e.g. python -m valhalla valhalla_build_tiles -h
  • execute the Python wrapper scripts directly, e.g. valhalla_build_tiles -h

Executing the scripts directly might also not work properly if there's a system-wide Valhalla installation, unless the Python environment's bin/ folder has higher priority than system folders in $PATH. The module execution uses an explicit Python executable which should be preferred.

There are also some additional commands we added:

  • --help: print the help for python -m valhalla explicitly
  • --quiet: redirect stdout of the C++ executables to /dev/null; can be added once anywhere in the command, will not be forwarded to a C++ executable
  • print_bin_path: simply prints the absolute path to the package-internal bin/ directory where the C++ executables are; useful if the executables should be accessed directly in some script

To find out which Valhalla executables are currently included, run python -m valhalla --help. We limit the number of executables to control the wheel size. However, we're open to include any other executable if there's a good reason.

Pure Python scripts

The following tools are implemented in pure Python and installed as console scripts:

  • valhalla_build_config: Generate or merge Valhalla configuration JSON files
  • valhalla_build_elevation: Download elevation (DEM) tiles for a given region
  • valhalla_build_extract: Create tar extracts from routing tiles

These are invoked directly, e.g. valhalla_build_config -h or valhalla_build_extract -h. They do not go through the python -m valhalla module mechanism.

Building from source

Note, building the bindings from source is usually best done by building Valhalla with cmake -B build -DENABLE_PYTHON_BINDING=ON .... However, if you want to package your own pyvalhalla bindings for some reason (e.g. fork in a bigger team), you can follow the below instructions, which are also executed by our CI.

The Python build respects a few CMake configuration variables:

  • VALHALLA_VERSION_MODIFIER (optional): Will append a string to the actual Valhalla version string, e.g. $(git rev-parse --short HEAD) will append the current branch's commit hash.

Type stubs (.pyi)

The .pyi files alongside each compiled module are auto-generated by nanobind_add_stub from the C++ bindings — do not edit by hand. They refresh on every build with -DENABLE_PYTHON_BINDINGS=On; a CI guard fails if the committed stubs drift from the live bindings. To regenerate manually: ./scripts/regenerate_python_stubs.sh <build-dir>.

Docstring placement: prose for a class/method that has a Python wrapper (e.g. Actor, Actor.route) lives as a string literal in the Python wrapper file — intellisense tools don't work well with that level of abstraction. Prose for things without a Python wrapper (e.g. ValhallaError, free functions in _graph_utils and predicted_speeds) stays in the C++ .def(...) / nb::class_(...) arg, where stubgen picks it up for the .pyi.

cibuildwheel

On our CI, this orchestrates the packaging of all pyvalhalla wheels for every supported, minor Python version and every platform. It can also be run locally (obviously only being able to build wheels for your platform), e.g.

python -m pip install cibuildwheel
cibuildwheel --print-build-identifiers
cibuildwheel --only cp313-manylinux_x86_64

# for windows you'll have to set an env var to the vcpkg win root
VCPKG_ARCH_ROOT="build/vcpkg_installed/custom-x64-windows" cibuildwheel --only cp313-win_amd64

The build looks at a few environment variables:

  • VCPKG_ARCH_ROOT (required for Win): The relative/absolute directory of the vcpkg root.

In the end, you'll find the wheel in ./wheelhouse.

Linux

To package arch-dependent Linux bindings we use a manylinux fork, where we install all dependencies into the manylinux_2_28 image, based on AlmaLinux 8. This is necessary to have a broad glibc compatibility with many semi-recent Linux distros.

Either pull the manylinux image, or build it locally for testing:

docker pull ghcr.io/valhalla/manylinux:2_28_valhalla_python

# or pull the image from ghcr.io
git clone https://github.com/valhalla/manylinux
cd manylinux
POLICY=manylinux_2_28 PLATFORM=x86_64 COMMIT_SHA=$(git rev-parse --verify HEAD) BUILDX_BUILDER=builder-docker-container ./build.sh
docker tag quay.io/pypa/manylinux_2_28_x86_64:$(git rev-parse --verify HEAD) ghcr.io/valhalla/manylinux:2_28_valhalla_python

Once built, start a container to actually build Valhalla using AlmaLinux 8:

cd valhalla
docker run -dt -v $PWD:/valhalla-py --name valhalla-py --workdir /valhalla-py ghcr.io/valhalla/manylinux:2_28_valhalla_python
docker exec -t valhalla-py /valhalla-py/src/bindings/python/scripts/build_manylinux.sh build_manylinux 3.13

This will also build & install libvalhalla before building the bindings. At this point there should be a wheelhouse folder with the fixed python wheel, ready to be installed or distributed to arbitrary python 3.13 installations.

Testing

Test wheel (linux only)

We have a small test script which makes sure that all the executables are working properly. If run locally for some reason, install a pyvalhalla wheel first. We run this in CI in a fresh Docker container with no dependencies installed, mostly to verify dynamic linking of the vendored dependencies.

Running the unit tests locally

The binding tests live in test/bindings/python/. The tile-dependent ones read test/bindings/python/valhalla.json, whose tile_dir points at test/data/utrecht_tiles, so one needs to execute the tests in the build directory:

# build the tile fixture once (needs ENABLE_DATA_TOOLS=ON)
cmake --build build/Release --target utrecht_tiles -j$(nproc)

# run from the build dir so test/data/utrecht_tiles/* resolves there
( cd <build_dir> && python -m unittest discover -s ../../test/bindings/python -v )

The CMake target run-python_valhalla is the canonical entry point.

Metadata

Release files for pyvalhalla 3.9.1

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for pyvalhalla 3.9.1
File Size Uploaded
pyvalhalla-3.9.1.tar.gz 36.5 MB Details

Built distributions (wheels)

Table of built distributions (wheels) for pyvalhalla 3.9.1
File
pyvalhalla-3.9.1-cp312-abi3-win_amd64.whl CPython 3.12 abi3 Windows x86-64 Details
pyvalhalla-3.9.1-cp312-abi3-manylinux_2_28_x86_64.whl CPython 3.12 abi3 Linux glibc 2.28+ x86-64 Details
pyvalhalla-3.9.1-cp312-abi3-manylinux_2_28_aarch64.whl CPython 3.12 abi3 Linux glibc 2.28+ ARM64 Details
pyvalhalla-3.9.1-cp312-abi3-macosx_14_0_arm64.whl CPython 3.12 abi3 macOS 14.0+ ARM64 Details

Total release size: 157.4 MB

Release files / pyvalhalla-3.9.1.tar.gz

Download URL pyvalhalla-3.9.1.tar.gz
Size 36.5 MB
Tags Source
SHA-256 checksum
How to use checksums
a0037952a956d7f0212453e7a7195fd3b27c9b357a183f5d33a3ebebaaf5e957
BLAKE2b-256 checksum
How to use checksums
b371bc3d87dd132694b38186ab5fe6cebff18b5b34e6a1852ced24ea79033ffe
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/6.1.0 CPython/3.13.7

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Oct 6, 2026.

Transparency log

Release files / pyvalhalla-3.9.1-cp312-abi3-win_amd64.whl

Download URL pyvalhalla-3.9.1-cp312-abi3-win_amd64.whl
Size 22.3 MB
Tags CPython 3.12 Windows x86-64 abi3
SHA-256 checksum
How to use checksums
542ea3e11da281c63f2043fa69a2f426c5b309cb1e3b0032028f7034847d1c13
BLAKE2b-256 checksum
How to use checksums
89563f3087dff7e1057a007a82044d5f957485d093c6e9ca08b7cf485612fa51
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/6.1.0 CPython/3.13.7

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Oct 6, 2026.

Transparency log

Release files / pyvalhalla-3.9.1-cp312-abi3-manylinux_2_28_x86_64.whl

Download URL pyvalhalla-3.9.1-cp312-abi3-manylinux_2_28_x86_64.whl
Size 37.5 MB
Tags CPython 3.12 Linux glibc 2.28+ x86-64 abi3
SHA-256 checksum
How to use checksums
7b49c5e5f86cefd555b473aaaf34df3305889d30aa889b8abd3b4c2acc622271
BLAKE2b-256 checksum
How to use checksums
df4722bf3a1dcc911bc149b854892812e04f42e30c8c34ade8320141b1f3ba32
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/6.1.0 CPython/3.13.7

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Oct 6, 2026.

Transparency log

Release files / pyvalhalla-3.9.1-cp312-abi3-manylinux_2_28_aarch64.whl

Download URL pyvalhalla-3.9.1-cp312-abi3-manylinux_2_28_aarch64.whl
Size 34.7 MB
Tags CPython 3.12 Linux glibc 2.28+ ARM64 abi3
SHA-256 checksum
How to use checksums
6ebe5f9dd6ce3b16413f939a271d68e64a4addd44df8a802a8eda0b9ca0bf16f
BLAKE2b-256 checksum
How to use checksums
e53a087f21f1d3551ed30fed4a8945f631482482183ca9bb69a2fddc9454402a
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/6.1.0 CPython/3.13.7

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Oct 6, 2026.

Transparency log

Release files / pyvalhalla-3.9.1-cp312-abi3-macosx_14_0_arm64.whl

Download URL pyvalhalla-3.9.1-cp312-abi3-macosx_14_0_arm64.whl
Size 26.4 MB
Tags CPython 3.12 abi3 macOS 14.0+ ARM64
SHA-256 checksum
How to use checksums
1780e2a586391a14028ac134f4335eee73dd88df66bf22adbe2d318493b4d053
BLAKE2b-256 checksum
How to use checksums
5c3dd27b849a66f2c30e030bdbf2b76470766c10d2037d61cb9906fd2df46b33
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/6.1.0 CPython/3.13.7

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Oct 6, 2026.

Transparency log

Release history Release notifications | RSS feed

This release

3.9.1 This release

5 release files

3.9.0

5 release files

3.8.3

5 release files

3.8.2

5 release files

3.8.1

5 release files

3.7.0

5 release files

3.6.3

5 release files

3.6.2

5 release files

3.6.1

5 release files

3.6.0

1 release file

3.2.0

15 release files

3.1.1

15 release files

3.1.0

15 release files

3.0.4

12 release files

3.0.3

12 release files

3.0.2

12 release files

0.0.3

8 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page