osrmroute
Official Python SDK for the OSRMRoute Maps, Routing & Geocoding API.
- Zero dependencies — standard library only, so it never conflicts with your existing HTTP stack
- Type-hinted — full annotations for every method
- Routing and geospatial APIs — routing, matrix, isochrones, geocoding, VRP, elevation, geofencing…
(lat, lon)for point helpers — these helpers convert to OSRMlon,lat; raw VRP arrays are the exception described below- Automatic retries with exponential backoff, honouring
Retry-After
python3 -m pip install ./osrmroute-python-1.1.0
Download and extract the source archive from OSRMRoute, then run the command above from its parent directory. This package is not published on PyPI.
Requires Python 3.8+.
Quick start
from osrmroute import OSRMRoute
maps = OSRMRoute(api_key="your-key", auth_mode="bearer", retries=0)
r = maps.route([(40.4093, 49.8671), (40.3777, 49.8920)])
route = r["routes"][0]
print(f"{route['distance'] / 1000:.1f} km, {round(route['duration'] / 60)} min")
Get a free key at osrmroute.com — no card required.
Retry policy
The source client retains its existing default of two automatic retries. Set
retries=0 for paid calls, as shown above: a network timeout can leave the
execution outcome unknown. Use X-Request-Id to investigate and use the async
job API with a durable Idempotency-Key for deduplicated submissions.
Configuration
maps = OSRMRoute(
api_key="your-key", # required
base_url="https://osrmroute.com", # self-hosted / staging
timeout=30.0, # seconds per request
retries=0, # do not replay a paid request with an unknown outcome
auth_mode="query", # or "bearer"
headers={}, # extra headers
)
Routing
maps.route([a, b, c], profile="car", geometries="geojson", steps=True)
maps.matrix([a, b, c]) # {"durations": ..., "distances": ...}
maps.directions([a, b], alternatives=True, lang="az")
maps.trip([a, b, c]) # travelling-salesman order
maps.match(gps_trace) # snap a noisy trace to roads
maps.nearest(a, number=3)
maps.snap([a, b])
maps.isochrone(a, time_limit=900) # 15-min reachability polygon
Profiles: car (global), bike, foot. Aliases driving / cycling / walking also work.
Geocoding
maps.geocode("Nizami küçəsi, Bakı") # -> {"hits": [...]}
maps.reverse((40.4093, 49.8671)) # coordinates -> address
maps.autocomplete("Berl", limit=5) # -> {"suggestions": [...]}
maps.geocode_batch(["Baku", "Tbilisi", "Yerevan"])
maps.places((40.4093, 49.8671), radius=1000, category="restaurant")
Bias results toward a location with near=(lat, lon), restrict with bbox or city.
Fleet optimisation
plan = maps.optimize(
vehicles=[{"id": 1, "start": [49.8671, 40.4093], "end": [49.8671, 40.4093]}],
services=[{"id": 1, "location": [49.8920, 40.3777]}],
)
maps.cluster(customers) # group nearby stops into delivery zones
Note: VRP
vehicles/servicestake raw[lon, lat](upstream VROOM format).
Geo utilities
maps.timezone((40.4093, 49.8671))
maps.elevation([(40.4093, 49.8671), (40.3777, 49.8920)])
maps.elevation_profile(points=route_points)
maps.boundary((40.4093, 49.8671), polygon=True)
maps.geofence(fences, points)
maps.solar((40.4093, 49.8671), date="2026-07-18")
maps.geometry("distance", from_=[40.4093, 49.8671], to=[40.3777, 49.8920])
maps.convert(point=(40.4093, 49.8671))
maps.country("AZ")
Error handling
Every non-2xx response raises OSRMRouteError:
from osrmroute import OSRMRoute, OSRMRouteError
try:
maps.route([a, b])
except OSRMRouteError as err:
if err.is_rate_limited: # 429 — plan limit reached
...
if err.is_out_of_coverage: # 422 — outside routable coverage
...
print(err.status, err.code, err.message)
GET requests and job creation with an explicit stable idempotency key retry transient failures. Other POSTs and cancellation are sent once; a lost response may have an unknown outcome. Never create a fresh job key merely because a response was lost. Retries are limited to 0–5.
Coverage
Availability depends on coordinates, profile and the current dataset. Missing coverage remains explicit; no driving fallback is used for unsupported profiles. Reverse results distinguish detailed addresses from nearby place fallback. Isochrone geometry may be absent when sampling is insufficient. See service status and source metadata; neither implies every road or address is covered.
Version 1.1.0 platform methods
Unknown routing profiles now fail before transport instead of becoming driving.
VRP accepts shipments and a top-level profile; raw VRP location arrays remain
[lon, lat], unlike point helpers. Constraints are verified; global optimality
is not promised. Check unassigned and result quality.
queued = maps.create_job('matrix', {
'from_points': [[40.4093, 49.8671]], 'to_points': [[40.3777, 49.8920]], 'profile': 'car',
}, idempotency_key='delivery-batch-20261015-001')
maps.list_jobs()
status = maps.get_job(queued['job']['id'], result=True)
maps.cancel_job(queued['job']['id']) # only a queued job can be cancelled
sources = maps.source_metadata() # requires info scope
fixture = sandbox_maps.sandbox('geocode', {'q': 'Baku'}) # separate sandbox key
Job states include unknown and expired; these methods never automatically
resubmit an unknown operation. Result retrieval is explicit. Sandbox results are
deterministic fixtures with zero billing, never navigation data. Preserve your
idempotency key across process restarts for the same operation/payload.
License
MIT © MAMMADOFF LLC
Metadata
Release files for osrmroute 1.1.0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| osrmroute-1.1.0.tar.gz | 12.1 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| osrmroute-1.1.0-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 22.3 kB
Release files / osrmroute-1.1.0.tar.gz
| Download URL | osrmroute-1.1.0.tar.gz |
|---|---|
| Size | 12.1 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
090f9bc32a76d4a93b0a1a6c94949fbd6e855d4fba5a5a828bb16db2374c8f05
|
|
BLAKE2b-256 checksum How to use checksums |
88bb1efc7955c018edbb0d3a11646c513ee1ceace07aada8c590f369ae6f6618
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
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 15, 2026.
Transparency logRelease files / osrmroute-1.1.0-py3-none-any.whl
| Download URL | osrmroute-1.1.0-py3-none-any.whl |
|---|---|
| Size | 10.2 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
24eebc90479ded18b55d5f715ed4ab07d979476b24cb6f5dfe1bc13b84aaf0bc
|
|
BLAKE2b-256 checksum How to use checksums |
a8e2a86eb08c9347a125723aeb7c89205ccd892eac5a014d66994b68ad4f2288
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
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 15, 2026.
Transparency log