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.

Release files for pyvalhalla 3.9.0

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.0
File Size Uploaded
pyvalhalla-3.9.0.tar.gz 36.5 MB Details

Built distributions (wheels)

Table of built distributions (wheels) for pyvalhalla 3.9.0
File
pyvalhalla-3.9.0-cp312-abi3-win_amd64.whl CPython 3.12 abi3 Windows x86-64 Details
pyvalhalla-3.9.0-cp312-abi3-manylinux_2_28_x86_64.whl CPython 3.12 abi3 Linux glibc 2.28+ x86-64 Details
pyvalhalla-3.9.0-cp312-abi3-manylinux_2_28_aarch64.whl CPython 3.12 abi3 Linux glibc 2.28+ ARM64 Details
pyvalhalla-3.9.0-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.0.tar.gz

Download URL pyvalhalla-3.9.0.tar.gz
Size 36.5 MB
Tags Source
SHA-256 checksum
How to use checksums
ee57273e850e4ba8ccea3ef2e0925967414c61bcfbab2a5f338d3ea7acbb4673
BLAKE2b-256 checksum
How to use checksums
b07129e3f23c457ad4cc9ae3d2f7b1ce0b90cbd72ba063e4c11346ca21eaf587
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 Sep 19, 2026.

Transparency log

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

Download URL pyvalhalla-3.9.0-cp312-abi3-win_amd64.whl
Size 22.2 MB
Tags CPython 3.12 Windows x86-64 abi3
SHA-256 checksum
How to use checksums
f41ef11f1fde16271786d0ff1cf978b4dea6770c6d541f55eaafd63a2d058bb3
BLAKE2b-256 checksum
How to use checksums
5e264f2477aa5f8a6e4d259a5183740e24e13222937815782f92e7f3d8f91982
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 Sep 19, 2026.

Transparency log

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

Download URL pyvalhalla-3.9.0-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
6d027f88f8e0d8055d1a4df8c45e6d78bfdaf319d4ce69f7eecd3940b77dc6b3
BLAKE2b-256 checksum
How to use checksums
0286ba439b603fcb7e7976949b34e939069f2b93995bfbc539b7384e028e20a9
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 Sep 19, 2026.

Transparency log

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

Download URL pyvalhalla-3.9.0-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
efc9a8f7098cc9d128b065a59cec386a0c6507c7eb690ef91421fbe5e57ed212
BLAKE2b-256 checksum
How to use checksums
3fd360d87a4f502d3e7e15fa2c2dd51074d518b401f47266dbe826526df58d4e
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 Sep 19, 2026.

Transparency log

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

Download URL pyvalhalla-3.9.0-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
e4ed269fc0ffd2d3e69460ca9ba0443309845b2bfdf582d8975af88c6933cd97
BLAKE2b-256 checksum
How to use checksums
09cec50b9f692bc4eaccbe7e0d2d2df2fb541607dedaa1b47920ed7a2c5a0326
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 Sep 19, 2026.

Transparency log

Release history Release notifications | RSS feed

This release

3.9.0 This release

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