BYTETOOLS

Valhalla (OSM) API

Free routing API with no key: turn-by-turn driving, cycling, walking and truck directions on OpenStreetMap data, with distances, times and manoeuvre text. Tested example included.

No API key requiredCORS enabledHTTPSFree tier

Endpoint tested and returned HTTP 200 on 2026-08-21

What is the Valhalla (OSM) API?

Valhalla is an open-source routing engine, and the OpenStreetMap Foundation runs a free public instance with no API key. It returns turn-by-turn directions with written manoeuvre instructions, distances, travel times and an encoded route shape for driving, cycling, walking, transit and truck profiles.

Valhalla differs from most routing engines in generating spoken-instruction text rather than leaving you to build sentences from turn codes. Each manoeuvre carries several phrasings: a display instruction, a succinct spoken form, a pre-transition cue and a post-transition distance callout. If you are building anything with voice guidance, that is a substantial amount of work you do not have to do.

The request shape is unusual and trips people up. Parameters go in a single `json` query parameter containing a URL-encoded JSON object, not as separate query keys — so `?json={"locations":[...],"costing":"auto"}` after encoding. The `costing` value chooses the profile, and `auto`, `bicycle`, `pedestrian`, `truck`, `motor_scooter` and `bus` each apply genuinely different rules about turn restrictions, surfaces and access rather than just changing an average speed.

Quick facts

Base URL
https://valhalla1.openstreetmap.de
Authentication
No API key or account on the OpenStreetMap Foundation's public instance. It is community infrastructure funded by donations, not a commercial service.
Rate limit
No published quota, but the instance is shared community infrastructure. Self-host Valhalla for production volume — the engine is open source.
Pricing
Free. The routing engine and OpenStreetMap data are both open.
CORS
Enabled — callable directly from browser JavaScript
Official docs
Read the docs

How to use the Valhalla (OSM) API

Every request below was executed against the live API on 2026-08-21, and the response shown is the real body it returned — not an illustration.

1. Get driving directions between two coordinates

GET https://valhalla1.openstreetmap.de/route?json=%7B%22locations%22%3A%5B%7B%22lat%22%3A52.52%2C%22lon%22%3A13.405%7D%2C%7B%22lat%22%3A52.3759%2C%22lon%22%3A9.732%7D%5D%2C%22costing%22%3A%22auto%22%2C%22directions_options%22%3A%7B%22units%22%3A%22kilometers%22%7D%7D

curl
curl 'https://valhalla1.openstreetmap.de/route?json=%7B%22locations%22%3A%5B%7B%22lat%22%3A52.52%2C%22lon%22%3A13.405%7D%2C%7B%22lat%22%3A52.3759%2C%22lon%22%3A9.732%7D%5D%2C%22costing%22%3A%22auto%22%2C%22directions_options%22%3A%7B%22units%22%3A%22kilometers%22%7D%7D'
JavaScript (fetch)
const res = await fetch("https://valhalla1.openstreetmap.de/route?json=%7B%22locations%22%3A%5B%7B%22lat%22%3A52.52%2C%22lon%22%3A13.405%7D%2C%7B%22lat%22%3A52.3759%2C%22lon%22%3A9.732%7D%5D%2C%22costing%22%3A%22auto%22%2C%22directions_options%22%3A%7B%22units%22%3A%22kilometers%22%7D%7D");
if (!res.ok) throw new Error(`Request failed: ${res.status}`);
const data = await res.json();
console.log(data);
Python (requests)
import requests

res = requests.get("https://valhalla1.openstreetmap.de/route?json=%7B%22locations%22%3A%5B%7B%22lat%22%3A52.52%2C%22lon%22%3A13.405%7D%2C%7B%22lat%22%3A52.3759%2C%22lon%22%3A9.732%7D%5D%2C%22costing%22%3A%22auto%22%2C%22directions_options%22%3A%7B%22units%22%3A%22kilometers%22%7D%7D", timeout=20)
res.raise_for_status()
print(res.json())
Response — HTTP 200 (truncated)
{
  "trip": {
    "locations": [
      {
        "type": "break",
        "lat": 52.52,
        "lon": 13.405,
        "original_index": 0
      },
      {
        "type": "break",
        "lat": 52.3759,
        "lon": 9.732,
        "original_index": 1
      }
    ],
    "legs": [
      {
        "maneuvers": [
          {
            "type": 1,
            "instruction": "Drive northwest on Spandauer Straße.",
            "verbal_succinct_transition_instruction": "Drive northwest. Then Turn left onto Karl-Liebknecht-Straße.",
            "verbal_pre_transition_instruction": "Drive northwest on Spandauer Straße. Then Turn left onto Karl-Liebknecht-Straße.",
            "verbal_post_transition_instruction": "Continue for 20 meters.",
            "street_names": [
              "Spandauer Straße"
            ],
            "bearing_after": 324,
            "time": 2.769,
            "length": 0.02,
            "cost": 3.046,
            "begin_shape_index": 0,
            "end_shape_index": 3,
            "verbal_multi_cue": true,
            "travel_mode": "drive",
            "travel_type": "car"
          },
          {
            "type": 15,
            "instruction": "Turn left onto Karl-Liebknecht-Straße/B 2/B 5. Continue on B 2.",
            "verbal_transition_alert_instruction": "Turn left onto Karl-Liebknecht-Straße.",
            "verbal_succinct_transition_instruction": "Turn left.",
            "verbal_pre_transition_instruction": "Turn left onto Karl-Liebknecht-Straße, B 2.",
            "verbal_post_transition_instruction": "Continue on B 2 for 1.5 kilometer

Parameters

ParameterTypeRequiredDescription
jsonqueryRequiredURL-encoded JSON object holding the whole request. Everything else below lives inside it. {"locations":[...],"costing":"auto"}
locationsjsonRequiredArray of `{lat, lon}` waypoints. Two minimum; extra points become via stops. [{"lat":52.52,"lon":13.405}]
costingjsonRequiredRouting profile: `auto`, `bicycle`, `pedestrian`, `truck`, `motor_scooter`, `bus`, `multimodal`. auto
directions_options.unitsjsonOptional`kilometers` or `miles`. Affects both the numbers and the wording of the instructions. kilometers
costing_optionsjsonOptionalPer-profile tuning — avoid tolls or ferries, set cycling comfort, declare truck dimensions. {"auto":{"use_tolls":0}}
(other endpoints)pathOptional`/optimized_route` solves waypoint order, `/isochrone` returns reachability polygons, `/matrix` computes many-to-many times.

Response fields

trip.locationsarray
The waypoints as snapped to the road network, with `original_index` mapping back to what you sent.
trip.legsarray
One leg per pair of consecutive waypoints.
legs[].maneuversarray
The turn-by-turn steps.
maneuvers[].instructionstring
Written instruction ready to display, e.g. "Turn left onto Karl-Liebknecht-Straße/B 2/B 5."
maneuvers[].verbal_succinct_transition_instructionstring
Shortened spoken form, for voice guidance where the full text is too long.
maneuvers[].length / timefloat
Distance in the requested units and duration in seconds for that step.
maneuvers[].begin_shape_index / end_shape_indexinteger
Range into the leg's encoded polyline, so you can highlight the step on a map.
maneuvers[].travel_mode / travel_typestring
Mode for the step, which matters on multimodal routes where legs differ.

What you can build with the Valhalla (OSM) API

  • Add turn-by-turn driving or cycling directions to an app without a key
  • Generate voice guidance text without composing it from turn codes
  • Compute realistic travel times for delivery or field-service scheduling
  • Build isochrones showing what is reachable within a time budget
  • Route trucks with height, weight and hazmat restrictions applied

Common errors and how to fix them

400 with a Valhalla error code

The `json` parameter is malformed or missing a required key.

Fix: Encode the whole object once with a URL encoder and check `locations` and `costing` are both present. A raw brace in a URL is the usual culprit.

No route found

A waypoint is too far from a routable way, or the profile cannot legally get there.

Fix: Valhalla snaps to the nearest road within a radius. A point in the middle of a field, or a motorway-only destination requested with `pedestrian`, both fail this way.

Route ignores a road you expected

The routing follows OpenStreetMap tags, including access, turn and vehicle restrictions.

Fix: Check the way's tags in OSM. Barriers, `access=private` and turn restrictions are honoured, which is usually correct even when it looks wrong.

Slow responses or refusals under load

The public instance is shared community infrastructure.

Fix: Cache routes that repeat, and self-host for production volume. Valhalla ships as an open-source container.

Valhalla (OSM) API — frequently asked questions

Is the Valhalla routing API free?

Yes — the OpenStreetMap Foundation runs a public instance with no key or account. It is donation-funded community infrastructure, so production workloads belong on your own instance rather than this one.

Why are the parameters inside a json query parameter?

That is Valhalla's design: the request is one JSON object, passed URL-encoded in a single `json` parameter for GET or as the body for POST. Separate query keys are not supported.

Which travel modes are supported?

`auto`, `bicycle`, `pedestrian`, `truck`, `motor_scooter`, `bus` and `multimodal`. They apply genuinely different rules — the truck profile honours height, weight and hazmat restrictions rather than simply driving more slowly.

How does Valhalla compare with OSRM?

Both route on OpenStreetMap data. OSRM is faster for plain point-to-point queries; Valhalla produces richer output — spoken instruction variants, isochrones, time-distance matrices and per-profile costing options — which suits navigation interfaces better.

Tools that pair with this API

Valhalla (OSM) is an independent third-party service and is not affiliated with ByteTools or ByteVancer. Details on this page were verified on 2026-08-21; always check the official documentation before relying on this API in production, as terms and limits can change.