Skip to main content

Overview

Python client for the JustRouting API — routing, distance matrices, geocoding, map matching, trips, nearest-road lookup, and vehicle routing optimization across Southeast Asia. No dependencies outside the standard library. Requires Python 3.9+.

Install

Or install from a clone of the repository:

Quickstart

The coordinates above are in Singapore. See Coordinates must share a country.

Services

A Client exposes eight services.

Routes

Routes.get returns the best route. Routes.get_all additionally returns alternatives and the snapped input waypoints.
route.geometry holds whichever encoding you asked for:

Matrix

Travel time and distance between many points at once.
The accessors return None for unreachable pairs. The API reports those as null, which is deliberately kept distinct from a genuine zero.

Geocode

Turn addresses into coordinates, free-form or structured:
structured (an address as typed fields) is mutually exclusive with text; bias steers results toward a location. An empty results list means nothing matched — it is a valid answer, not an error.

Map Matching

Snap a noisy GPS trace onto the road network:
Match extends Route, so distance, duration, geometry, and legs are all available. get_all also returns tracepoints aligned with the input coordinates — None entries mark points that could not be matched. Use gaps="ignore", tidy=True, waypoints=[0, 5], or snapping="any" to shape the matching.

Trip

The fastest order to visit a set of coordinates:
source="first" / destination="last" pin where the trip starts and ends.

Nearest

The road segment closest to a coordinate:

Optimization

Assign tasks to a fleet and order each vehicle’s stops.
Use Shipments instead of Jobs for pickup-and-delivery pairs that must be served in order by the same vehicle.

Health

The only call that works without an API key, which makes it a useful connectivity check.

Error handling

Every failure raises a subclass of justrouting.Error. Classify it with except clauses rather than matching on message text:
When the engine finds nothing — an empty matchings, trips, or waypoints list on an “Ok” response — map matching, trip, and nearest raise Error with status_code == 200 and osrm_code "NoMatch", "NoTrip", or "NoSegment" (no dedicated subclass; check e.osrm_code). Catch justrouting.Error itself when you need the status code, engine code, or raw body:
Failures that never produced an API response raise TransportError (network-level, retried like a 5xx) or DecodeError (unparseable success response) instead; neither is a subclass of Error.

Configuration

Invalid options raise ValueError immediately. (The Go client defers them to the first request because its constructor cannot fail; Python constructors can.)

Timeouts and retries

Rate limits (429), server errors (5xx), and transport failures are retried with exponential backoff and jitter; a Retry-After header takes precedence when present. Other 4xx responses are returned immediately — they would fail identically on a retry and would still consume quota. Client(timeout=...) covers a single HTTP attempt, like http.Client.Timeout in Go. Pass the per-call timeout argument to bound the whole retry sequence:
Proxy configuration follows the standard HTTP_PROXY / HTTPS_PROXY environment variables.

Things to know

Coordinates are [longitude, latitude]

This is the GeoJSON order, and the reverse of the “lat, lng” used by most map UIs. Swapped coordinates are usually caught locally — a longitude in the latitude slot fails the [-90, 90] check before a request is sent — but a swap that stays in range will silently route somewhere unexpected. Point is a list subclass, so both of these work:

Coordinates must share a country

Every coordinate in a single request must fall within one country; the API routes each request to a per-country engine. A Singapore → Kuala Lumpur request fails with CrossCountryError. Supported countries: Brunei, Cambodia, Indonesia, Laos, Malaysia, Myanmar, the Philippines, Singapore, Thailand, and Vietnam.

Plan limits

Exceeding a size limit raises PlanLimitExceededError; exhausting the daily allowance raises QuotaExceededError.

Examples

Runnable scripts live in examples/:

Development

The default suite runs entirely against local http.server instances — no network access and no API key. Integration tests hit a live API and are behind a marker, so they never run by accident:

Differences from the Go client

  • Exceptions replace sentinel errors and errors.Is; QuotaExceededError subclasses RateLimitedError.
  • Constructor options are keyword arguments; invalid ones raise ValueError immediately instead of being deferred to the first request.
  • There is no context.Context; the per-call timeout argument plays the role of a context deadline.
  • Matrix accessors return float | None instead of (float, ok).
  • There is no custom-HTTP-client option; use base_url, timeout, and the standard proxy environment variables instead.

License

MIT