Directions, Routing & Distance Matrix API — no API key avatar

Directions, Routing & Distance Matrix API — no API key

Pricing

from $2.40 / 1,000 route computeds

Go to Apify Store
Directions, Routing & Distance Matrix API — no API key

Directions, Routing & Distance Matrix API — no API key

Directions, travel times, distance matrices, route optimization, isochrones, geocoding and elevation on OpenStreetMap: a Google Maps Directions API alternative with no API key. Driving, cycling, walking, truck. Polyline + GeoJSON geometry. MCP-ready for Claude and AI agents.

Pricing

from $2.40 / 1,000 route computeds

Rating

0.0

(0)

Developer

David Roberts

David Roberts

Maintained by Community

Actor stats

0

Bookmarked

2

Total users

1

Monthly active users

5 days ago

Last modified

Share

Directions, Routing & Distance Matrix API — turn-by-turn directions, travel times, route optimization, isochrones, geocoding and elevation on OpenStreetMap, no API key

Directions, Routing & Distance Matrix API is a keyless alternative to the Google Maps Directions API and Distance Matrix API, built on OpenStreetMap. Send an origin and a destination, as place names or coordinates, and get back driving, cycling and walking directions with distance, travel time, turn-by-turn instructions and the full route geometry as polyline (precision 6 and 5) and GeoJSON. The same Actor answers distance matrices (travel time between many origins and destinations), route optimization (the best order for delivery stops), isochrone maps (how far can I get in 30 minutes), forward and reverse geocoding and elevation profiles, plus toll/ferry/highway flags and alternative routes. There is no map-provider key to obtain, no second billing account and no terms to click through.

It is built for AI agents (through MCP), scripts and data pipelines that need a route now, and for logistics, delivery pricing, trip planners and commute or catchment analysis in bulk: up to 1000 routes, a 50×50 matrix, 10 isochrones, 1000 geocodes or 100 elevation profiles per run, one dataset row each.

What can the Directions, Routing & Distance Matrix API do?

  • 🚗 Directions for 8 travel profiles: car, bike, foot, truck (with height, weight and hazmat limits), motorcycle, scooter, bus and taxi.
  • 🧭 Multi-stop routes: up to 20 locations per route, one leg per stop, with up to 3 alternative routes on A→B trips.
  • 🗺️ Geometry that decodes correctly: polyline6, polyline5 and GeoJSON, all describing the same line. A precision-6 polyline decoded at precision 5 lands in the ocean; here each format is labelled with its precision.
  • 🔀 Optimized trips: give it the stops and it picks the visiting order for the shortest trip, first and last fixed.
  • 🔁 Time/distance matrices: up to 50 sources × 50 targets, one row per source.
  • ⏱️ Isochrones: up to 4 time (minutes) or distance (km) contours per point, as polygons or lines.
  • 📍 Place names or coordinates: text such as "Apollo Bay VIC" is geocoded for you, and the row shows what it matched.
  • 📌 Geocoding on its own: place names and addresses to coordinates, or coordinates to the nearest addresses and places, up to 10 matches each.
  • ⛰️ Elevation profiles along a route, or along any line you send (a GPX track, a hiking trail), with total climb and descent.
  • 🚫 Avoid tolls, highways, ferries, unpaved roads, your own polygons (a flooded valley) or points (a closed bridge).
  • 🚲 Route tuning: bike type, hill and main-road tolerance, walking speed, shortest instead of fastest.
  • 🕘 Depart-at / arrive-by times using typical road speeds for that time of day.

Because it runs on Apify, you also get the REST API, scheduling, webhooks, integrations (Make, Zapier, n8n) and the Apify MCP server for AI agents, with no extra setup.

Use cases

  • Delivery ETA and pricing: distance and drive time from the depot to each customer, priced per kilometre or per minute.
  • Logistics and fleet planning: a travel-time matrix from every depot to every drop, for assigning jobs to the nearest vehicle.
  • Multi-stop delivery route optimization: give it the stops and it returns the shortest visiting order (the travelling-salesman problem for up to 20 locations), with the route in that order.
  • Trip planners and itineraries: a day's drive through named towns, with legs, drive times and turn-by-turn directions.
  • Commute and travel-time analysis: drive, cycle or walk times from a property or site to work, schools and stations, for property search or site selection.
  • Catchment and service-area maps: isochrones showing everything within 15, 30 or 60 minutes of a store, clinic or depot.
  • Bulk geocoding: CRM, event or store-locator addresses to coordinates, and coordinates back to the nearest address.
  • Elevation for cycling, hiking and EV range: climb, descent and a profile along a route or any GPX track.
  • Truck routing: routes that respect height, weight and hazmat limits.
  • AI agents: an assistant connected to the Apify MCP server can answer "how long is the drive from A to B" with one call and cite the distance and time from the row.

Compared with the Google Maps Directions and Distance Matrix APIs

This ActorGoogle Maps PlatformGoogle Maps scraper Actors on Apify
Price per route$0.003$0.005 (Compute Routes Essentials), $0.010 (Routes Pro)$0.015 + $0.01 setup, or $0.0025 + $0.007 per start
Price per matrix element$0.0005$0.005—
Free usageApify free plan: car routes and matrices from coordinates10,000 calls a month per SKUApify free plan credit
API key / billing accountNone; your Apify accountGoogle Cloud project, API key and billing accountNone; your Apify account
Full route geometryYes: polyline6, polyline5 and GeoJSONYes: encoded polylineNot on most
Alternative routesUp to 3, $0.003 eachYesVaries
Multi-stop routesUp to 20 locationsYesVaries
Route optimizationYes, 4–20 stops, same price as a routeWaypoint reordering at the Pro priceNo
IsochronesYesNoNo
GeocodingYes, $0.001 per resultSeparate Geocoding APISeparate Actors
ElevationYes, along a route or any lineSeparate Elevation APINo
ProfilesCar, truck (dimensions, hazmat), bike, foot, motorcycle, scooter, bus, taxiDrive, bicycle, walk, two-wheeler; no truckWhat the Google Maps website offers
Live trafficNo: typical speeds for the time of dayYesWhat the Google Maps website shows
Public transitNoYesWhat the Google Maps website shows
DataOpenStreetMapGoogleGoogle Maps website

Google prices are from its March 2025 price sheet; scraper prices are two Store Actors' listed prices on 2026-09-28. Choose Google when you need live traffic or public transport. Choose this Actor for isochrones, route optimization, elevation and full geometry in one call, no key, and a lower price per route. Road coverage is OpenStreetMap's: excellent in cities, variable on remote tracks.

What data do you get?

FieldRow kindMeaning
statusallok, no_route, geocode_failed, unsupported or unknown (see Statuses).
route.distanceM, route.durationSrouteTotal distance (metres) and travel time (seconds).
route.geometryroutepolyline6, polyline5 and/or geojson ([lng, lat] pairs), per the geometry option.
route.legs[].maneuvers[]routeTurn-by-turn steps: name (turn_right…), instruction, street names, distance, time.
route.hasToll, hasFerry, hasHighwayrouteWhether the route uses a toll road, a ferry or a motorway.
route.bboxroute[minLng, minLat, maxLng, maxLat].
route.elevationroute{intervalM, m[]}: metres above sea level every intervalM metres along the route.
alternates[]routeAlternative routes, same shape as route.
locations[].geocodedrouteFor text locations: the matched label, coordinates, confidence and match type.
targets[]matrixPer target: distanceM, durationS (null = unreachable) and via (matrix/route).
geojsonisochroneGeoJSON FeatureCollection, one Feature per contour.
optimizedOrderrouteWith optimize: the input indices in visiting order.
results[]geocodeMatches, best first: label, lat, lng, confidence, layer, matchType.
samples[], summaryelevationPer sample distanceM and elevationM; min, max, climb, descent and length of the line.
sourceallengine, attribution (display it — see below), backendId, retrievedAt, durationMs.

How to get directions from OpenStreetMap in 4 steps

  1. Open the Actor's Input tab and fill Origin and Destination, for example Torquay VIC and Apollo Bay VIC. For many trips at once, use Routes instead.
  2. Choose the profile (car by default) and, under Output, the geometry format and step detail you want.
  3. Click Start. A handful of routes finish in a few seconds.
  4. Download the dataset as JSON, CSV or Excel, or read it from the API. The Overview view shows distance, time, tolls and ferries per row.

For a matrix, isochrones, geocoding or elevation, fill Matrix, Isochrones, Geocode or Elevation profiles instead. mode is optional: the Actor runs whichever of routes (or origin + destination), matrix, isochrones, geocode or elevation you send. Send only one of them per run, or set mode to choose.

Input

Quick route: origin, destination, waypoints

For one trip, skip routes and send the trip at the top level:

{ "origin": "Torquay VIC", "destination": "Apollo Bay VIC", "profile": "car" }

waypoints adds stops in order (up to 18, so 20 locations with the ends), and any of the three can be a "lat,lng" string instead of a place name:

{
"origin": "-38.3385,144.3255",
"destination": "Apollo Bay VIC",
"waypoints": ["Lorne VIC"],
"profile": "car"
}

This is exactly one route {"id": "route", "locations": [origin, ...waypoints, destination], "profile": profile}: same row, same price. profile takes the same values as in routes. origin without destination, or the other way round, is an input error. If you also send routes, routes wins and the quick fields are ignored with a warning.

Routes: turn-by-turn directions

routes is the batch form, for several trips or per-trip options:

{
"routes": [
{
"id": "great-ocean-road",
"locations": ["Torquay VIC", "Apollo Bay VIC"],
"profile": "car",
"alternates": 1
}
],
"steps": "instructions",
"elevationIntervalM": 100
}

routes holds up to 1000 requests. Each takes:

KeyNotes
idOptional, echoed in input.id.
locations2–20 locations: origin, stops in order, destination. Each stop starts a new leg. Routes with more than 20 are skipped with a warning.
profilecar (default), bike, foot, truck, motorcycle, scooter, bus, taxi.
alternates0–3. Only for a two-location route without departAt/arriveAt; otherwise set to 0 with a warning. The engine may return fewer than asked, or none. Each alternate returned is charged as one more route_computed.
avoidAny of tolls, highways, ferries, unpaved. bike and foot support only ferries; other values are dropped for those profiles with a warning on the row.
departAt / arriveAtOne of the two, YYYY-MM-DDTHH:MM, local time at the origin, no time zone. Uses typical speeds for that time, not live traffic.
excludePolygonsArray of rings, each at least 3 [lng, lat] pairs (GeoJSON order). Roads crossing a ring are avoided.
truckheight, width, length (metres), weight, axleLoad (tonnes), hazmat (true/false). Used only with profile: "truck"; ignored with a warning on other profiles.
optimizetrue reorders the stops for the shortest trip; see Optimized routes.
avoidLocationsPoints whose nearest road is avoided (coordinates only, any format below). For a closed bridge or a blocked street.
tuningPer-profile preferences; see Route tuning.

Matrix: travel time and distance between many points

{
"matrix": {
"sources": [
[-37.8183, 144.9671],
[-38.1499, 144.3617],
[-37.5622, 143.8503]
],
"targets": [
[-38.3385, 144.3255],
[-38.54, 143.978],
[-38.758, 143.6706]
],
"profile": "car",
"longPairs": "reject"
}
}

matrix is one object: sources and targets (each 1–50 locations), profile, optional departAt, id and longPairs. The result is one row per source, each with a targets array.

The default routing engine caps a single matrix pair at 400 km of road, so pairs more than 380 km apart as the crow flies are handled before the matrix request (an engine without a per-pair cap answers them as ordinary matrix elements):

  • longPairs: "reject" (default): if both ends are coordinates, the input is refused before anything runs. If a long pair only shows up after geocoding place names, the matrix rows come back no_route with the pairs listed in error.
  • longPairs: "route": each long pair is computed as an individual route. Those targets carry via: "route" and are charged as route_computed, not as a matrix element.

Isochrones: how far can I get

{
"isochrones": [
{
"id": "roma-st-cycling",
"location": [-27.4648, 153.019],
"profile": "bike",
"minutes": [15, 30],
"polygons": true
}
]
}

isochrones holds up to 10 requests: location, profile, and either minutes (up to 4 contours, each ≤ 120) or km (up to 4, each ≤ 200). polygons: true returns filled polygons; the default false returns boundary lines. denoise (0–1) drops small islands and generalize (metres) simplifies the outline.

Optimized routes

{
"routes": [
{
"id": "coast-run",
"locations": [
[-38.1499, 144.3617],
[-38.758, 143.6706],
[-38.3385, 144.3255],
[-38.54, 143.978],
[-38.1499, 144.3617]
],
"optimize": true
}
]
}

With optimize: true the first and last locations stay put and the stops between them are visited in whatever order makes the trip shortest (4–20 locations; make first and last the same for a round trip). The row's optimizedOrder lists the input indices in visiting order — for this coast run you would expect [0, 2, 3, 1, 4] (Geelong, Torquay, Lorne, Apollo Bay, back to Geelong) — and locations and legs follow that order: legs[i] runs from locations[i] to locations[i + 1], and optimizedOrder[i] is the input index of locations[i]. With fewer than 4 locations there is nothing to reorder, so optimize is ignored with a warning and the trip is routed (and charged) as a plain route; it cannot be combined with departAt/arriveAt, and alternates are not available. An optimized route is charged as one route_computed ($0.003), the same as a plain route.

Route tuning

tuning passes preferences to the engine for the route's profile. Keys that don't apply to the profile, and unknown keys, are ignored with a warning; an out-of-range value is an input error.

KeyProfilesNotes
bicycleTypebikeroad, hybrid, cross or mountain: sets typical speed and which surfaces suit.
useRoadsbike0 (stick to bike paths) … 1 (roads are fine).
useHillsbike, foot0 (avoid hills, even at a detour) … 1 (don't care).
walkingSpeedKmhfoot0.5–25 km/h (engine default 5.1).
shortestalltrue minimises distance instead of time.
roundaboutExitsallfalse drops the separate "take the 2nd exit" maneuvers.

Geocoding: place names ↔ coordinates

{
"geocode": [
{ "id": "lorne", "text": "Lorne VIC" },
{ "id": "flinders-st", "text": "Flinders Street Station, Melbourne", "size": 3 },
{ "id": "near-apollo-bay", "lat": -38.758, "lng": 143.6706, "layers": ["address", "street"], "size": 5 }
],
"geocodeCountry": "AU"
}

Each query is forward (text: a place name or address) or reverse (lat and lng: the addresses and places nearest that point). size asks for up to 10 matches (default 1), best first; layers restricts them to kinds of place — address, street, venue (or poi), locality, localadmin, neighbourhood, county, region, postalcode, country, or coarse for any administrative area. Forward queries are bounded to geocodeCountry. A backend that returns only one reverse result unless layers names a single kind of place says so in the row's warnings when it reduced your size.

Forward results go through the same word-match check as place names in routes: a match is kept only when at least half of your significant words appear in it (see the FAQ), and the row is geocode_failed only when no match passes; looseGeocoding: true turns the check off. Reverse results are not checked.

One row per query: query (as parsed) and results[]. Each result returned is one geocoded_location ("Lookup") event ($0.001), so size: 5 can cost up to $0.005; a query with no match is geocode_failed and free.

Elevation profiles

{
"elevation": [
{ "id": "great-ocean-road", "polyline": "…", "polylinePrecision": 5, "intervalM": 500 },
{
"id": "three-points",
"coordinates": [
[144.3255, -38.3385],
[143.978, -38.54],
[143.6706, -38.758]
]
}
]
}

Send a line as an encoded polyline (set polylinePrecision to how it was encoded: 5, the default, for most tools; 6 for this Actor's polyline6) or as coordinates ([lng, lat] pairs in GeoJSON order, or {"lat", "lng"} objects), up to 5000 points. intervalM: 0 (default) gives the elevation at your points only; 10–5000 resamples the line every that many metres. A line may resample to at most 5000 samples (about 50 km at 10 m, 2,500 km at 500 m); a longer one is skipped with a warning naming the smallest intervalM that fits, or split it.

The row has samples[] (lat, lng, distanceM along the line, elevationM, null where there is no data, such as over the sea) and summary (minM, maxM, gainM total climb, lossM total descent, lengthM). One geocoded_location ("Lookup") event ($0.001) per answered line, however many samples. A line with no elevation data at any sample comes back no_route ("no elevation data along this line") and is not charged. To profile a route, pass its route.geometry.polyline6 with precision 6, or set elevationIntervalM on the route request itself.

Output options (all modes)

FieldDefaultNotes
geometryallpolyline6, polyline5, geojson, all or none.
stepsinstructionsinstructions (maneuvers with text), maneuvers (no text), none (legs only).
unitskmkm or mi, for instruction text only. Numeric fields are always metres and seconds.
languageen-GBInstruction language, 28 locales from bg-BG to uk-UA. There is no en-AU; en-GB is the closest.
elevationIntervalM00 = off, or 10–1000: an elevation in metres every that many metres along each route. 30 is a good choice.
geocodeCountryAUTwo-letter country code that bounds and biases place-name lookups. Empty string = worldwide.
looseGeocodingfalseAccept any geocoder hit, even one sharing few words with your query (see the FAQ on geocode_failed).
concurrency41–8 requests in parallel. Requests to the routing engine are capped per host, so values above 4 rarely help.

Location formats

Any location, in any mode, can be:

  • an object: {"lat": -37.8183, "lng": 144.9671}, with lon or latitude/longitude also accepted;
  • a pair: [-37.8183, 144.9671] in [lat, lng] order, unlike GeoJSON and excludePolygons;
  • a "lat,lng" string: "-37.8183,144.9671", latitude first. A string whose first number is outside ±90 but would be valid swapped is refused with looks like lng,lat — give latitude first;
  • place text: "Lorne VIC", "Geelong", "Ballarat railway station".

Text is geocoded against OpenStreetMap and other open address data, bounded to geocodeCountry, and the best match is used when at least half of your significant words appear in it (otherwise geocode_failed, naming the closest match — see the FAQ). A town name resolves to the town centre: fine between towns, wrong for the last mile. Use an address or coordinates when the exact door matters.

Output example

A trimmed route row from a real run of the Torquay → Apollo Bay drive, requested with coordinates:

{
"kind": "route",
"input": { "id": "great-ocean-road", "index": 0 },
"status": "ok",
"profile": "car",
"locations": [
{ "lat": -38.3385, "lng": 144.3255, "snapped": { "lat": -38.3385, "lng": 144.3255, "sideOfStreet": "right" } },
{ "lat": -38.758, "lng": 143.6706, "snapped": { "lat": -38.758, "lng": 143.6706, "sideOfStreet": "left" } }
],
"route": {
"distanceM": 91330,
"durationS": 4756,
"hasToll": false,
"hasFerry": false,
"hasHighway": false,
"bbox": [143.66897, -38.758124, 144.325383, -38.336874],
"geometry": {
"polyline6": "``_chAmo|grGmYf[e@p@[|@G…",
"polyline5": "…",
"geojson": { "type": "LineString", "coordinates": [[144.325383, -38.338577], "… 3,310 vertices …"] }
},
"legs": [
{
"distanceM": 91330,
"durationS": 4756,
"maneuvers": [
{
"type": 10,
"name": "turn_right",
"instruction": "Turn right onto The Esplanade.",
"streetNames": ["The Esplanade"],
"distanceM": 85,
"durationS": 15,
"beginShapeIndex": 24,
"endShapeIndex": 28
},
"… 21 maneuvers in all"
]
}
]
},
"alternates": [{ "distanceM": 118168, "durationS": 5322, "…": "same shape as route" }],
"source": {
"engine": "Valhalla",
"attribution": "© OpenStreetMap contributors (ODbL)",
"backendId": "a",
"retrievedAt": "2026-09-26T05:12:40.118Z",
"durationMs": 2400
}
}

With place names instead of coordinates, each location also carries what the geocoder matched:

{
"geocoded": {
"query": "Apollo Bay VIC",
"label": "Apollo Bay, VIC, Australia",
"lat": -38.753405,
"lng": 143.665293,
"confidence": 1,
"matchType": "exact",
"layer": "locality"
}
}

beginShapeIndex / endShapeIndex index into the decoded route geometry, so each maneuver can be drawn on its own stretch of road. Maneuver type is the engine's numeric code; name is the readable form.

Matrix rows (kind: "matrix"): one per source, with sourceIndex, origin, and targets[] of {index, location, distanceM, durationS, via}. Isochrone rows (kind: "isochrone"): location, contours[] as requested, and geojson.

Snapping. On route rows, locations[].snapped echoes your input point plus the side of the street the engine started on. On matrix rows, origin.snapped and targets[].location.snapped are the points actually snapped onto the road network.

The run summary is saved to the key-value store as OUTPUT: jobs and rows, counts by status, charged events, total kilometres and hours of ok routes, whether the run was on the free tier, and warnings.

Statuses

statusMeaningCharged
okAnswered.yes
no_routeThe engine found no path (an island without a ferry, a point with no road nearby), or a rejected long matrix pair.no
geocode_failedA text location matched nothing.no
unsupportedNo configured routing engine can serve this profile, size or feature. The reason is in error.no
unknownThe engine or geocoder did not answer (timeout or outage), or your spending limit was reached. Retry later. Never read it as "no route".no

How much does routing cost?

Pay-per-event: you pay for answers, not for compute.

EventPriceWhen
route_computed$0.003Each route row with status: ok, optimized routes included, plus one per alternative route returned (the engine prices an alternate as a full route). Also each long matrix pair routed separately.
matrix_element$0.0005Each source→target element of an answered matrix, unreachable (null) elements included.
isochrone_computed$0.002Each answered isochrone, all its contours included.
geocoded_location — Lookup (geocode or elevation profile)$0.001Each text location resolved to coordinates; in geocode mode, each result returned; each elevation line answered.
apify-actor-start$0.00005Once per run, per GB of memory.

Higher Apify plans get a discount:

EventFree and BronzeSilverGold
route_computed$0.003$0.0027$0.0024
matrix_element$0.0005$0.0005$0.00045
isochrone_computed$0.002$0.0018$0.0016
geocoded_location$0.001$0.001$0.0009

Coordinates you supply are free, and so are no_route, geocode_failed, unsupported and unknown rows. Geocodes are charged when a place name resolves — a resolved name is an answer in its own right and the row carries its coordinates whatever happens next; a geocode_failed job and a job lost to a backend outage (unknown) are not charged.

Examples: the Torquay → Apollo Bay drive above, from place names with one alternate returned, is two routes and two geocodes, $0.008; without the alternate it is $0.005. A 10×10 depot matrix from coordinates is 100 elements, $0.05. The optimized coast run above, from coordinates, is one route, $0.003. A thousand routes between coordinates cost $3. Geocoding 100 addresses (one result each) is $0.10; the Great Ocean Road elevation profile every 500 m is one lookup, $0.001.

Free Apify plan: served by the community OpenStreetMap routing server rather than the paid engine, so you get exactly what that server offers and nothing less: car profile, coordinates only (it has no geocoder — place names come back unsupported, pass coordinates, for example "lat,lng" strings in origin and destination), routes and matrices, alternates when it has them, no isochrones, no geocoding, no elevation, no optimized routes and no toll/motorway flags. The only limit of ours is politeness towards that shared server: 100 jobs per run, one request at a time. Results can differ slightly from the paid engine.

Data & attribution

Routes are computed by a hosted routing engine on OpenStreetMap data. Travel times use typical road speeds; there is no live traffic, and roadworks or closures count only once OpenStreetMap has them. Road coverage is OpenStreetMap's: excellent in cities, variable on remote tracks.

Each row names the engine that answered in source.engine (for example Valhalla, or none on a row no engine was asked for, such as unsupported) and the notice that engine's data licence requires in source.attribution. Wherever you show the results — a map, an app, a report — display the source.attribution text of the rows you show. For OpenStreetMap-based results it is "© OpenStreetMap contributors (ODbL)"; OpenStreetMap data is licensed under the Open Database License. Geocoding also draws on other open datasets (Who's On First, OpenAddresses — for Australian addresses, G-NAF — GeoNames, Foursquare Open Source Places); a row carrying a result from one of them has that dataset's notice appended to source.attribution, so showing source.attribution covers geocoded places too. Read the attribution from the rows rather than hard-coding it. source.backendId is an opaque identifier for the operator's debugging and carries no meaning for users.

Limits

  • Per run: 1000 routes, 20 locations per route, a 50×50 matrix, 10 isochrones with 4 contours each, 3 alternates per route, 1000 geocode queries with up to 10 results each, 100 elevation lines of up to 5000 points and 5000 samples after resampling (every 10–5000 m). One mode per run.
  • Matrix pairs over 400 km of road exceed the default engine's limit; see longPairs.
  • Isochrones: each contour ≤ 120 minutes or ≤ 200 km.
  • Elevation is in metres whatever units says.
  • No en-AU instructions. en-GB gives metric units and British spelling.
  • Snapping: a point off the road network is snapped to the nearest road the profile can use. A point with no road within reach is no_route.

FAQ

Do I need a routing or maps API key?

No. The Actor calls the routing engine for you and bills through your Apify account. You need only an Apify account.

How do I decode the polyline?

polyline6 uses 6 decimal places, polyline5 uses 5 (the precision most decoders assume by default). Pass the matching precision to your decoder, for example polyline.decode(s, 6) with the Python polyline package, or skip decoding and use geojson, which is [lng, lat] pairs.

Does it include live traffic?

No. departAt / arriveAt apply typical speeds for that time of day, not live conditions.

How do I use it from an AI agent (MCP), n8n, Make or my own code?

Through the Apify MCP server (mcp.apify.com) an agent can search for this Actor, read this README and call it with just origin and destination. From code, call the Actor through the Apify API, the Python or JavaScript client, or the Make, Zapier and n8n integrations. For agents:

  • Join rows on input.id (echoed) or input.index (0-based position). Matrix rows also carry sourceIndex, and each target its index.
  • Check status before reading route; route is absent on non-ok rows.
  • geometry: "none" plus steps: "none" keeps rows tiny when only distance and time matter. A long drive's polyline is tens of kilobytes.
  • Fetch full items rather than projected fields: some dataset clients silently drop arrays of objects (legs, targets) from field projections.
  • Read the row count from the dataset (totalItemCount), not the run summary, which can lag by a few rows right after SUCCEEDED.

What does unknown mean, and should I retry?

unknown means the engine did not answer in time or returned a server error. It is not charged and is safe to retry. It never means there is no route.

Why did a place name come back geocode_failed when the geocoder found something?

Geocoders match on words: "Nowhereville XYZ" resolves, with full confidence, to a business called "XYZ Finance" 900 km away. To stop that turning into a routed, billed 1,900 km trip, a hit is accepted only when at least half of your significant words appear in the matched place name (state names, country and abbreviations such as St or Rd don't count). Otherwise the row is geocode_failed and error names the closest match. If you really do mean that place, pass its coordinates, or set looseGeocoding: true to accept any hit.

Why is a geocode result I expected missing?

In geocode mode each forward result passes the word-match check separately, so with size: 5 you may get fewer than five. Set looseGeocoding: true to see everything the geocoder returned, or narrow with layers.

Can I optimize the order and get alternative routes?

No: an optimized route is one route in the chosen order. Route the reordered stops again without optimize if you need alternates for a particular leg.

Why does a row say unsupported, or carry a warning about elevation or departure time?

The actor can be configured with more than one routing backend, and not every backend has every feature. A job goes to the first backend that can serve it; when none can, the row is unsupported and error says why: text locations need geocoding, which no routing backend serving this run supports — pass coordinates instead, departAt is not supported by the backend, or a profile that no backend offers. Elevation is never a reason to refuse a job: if the backend that answered has no elevation data, the route is returned without it and the row warns elevationIntervalM ignored: elevation is not available on the backend that answered. Some backends also cannot say whether a route uses tolls or motorways; those rows carry hasToll / hasHighway as null with a warning, never false.

Why did my free-plan run stop, drop routes, or say unsupported?

Free Apify plans are served by the community routing server, which has no geocoder, no isochrones and only a car profile; jobs it cannot serve come back unsupported with the reason. Runs are capped at 100 jobs to stay polite to that shared server. Everything else — long routes, alternates, matrices — works as it does for paying users. See pricing.

Other Actors by the same author

  • AU Mobile Coverage grades a route against Telstra, Optus and TPG predicted coverage. Feed it route.geometry.polyline6 with polylinePrecision: 6.
  • AU Address Enrichment adds planning, flood, bushfire, NBN, transport, school-zone and electorate data to Australian addresses.

Found a problem or need a custom routing workflow? Open an issue on the Actor's Issues tab.