Google Maps Directions API Alternative: Routes as JSON
If you need Google Maps routes as JSON without a Google Cloud billing setup, call GET /v1/google-maps/directions with an origin and a destination. Every successful call costs 1 credit, whatever the mode, and failed calls cost nothing. A recorded New York to Boston call returns two routes with distance, duration and a duration_in_traffic figure. This guide shows that response trimmed, the parameters, a delivery-batch cost example and the gaps that make Google's own API the better choice.
How do you request a route and what comes back?
Send a GET request with your key in the X-API-Key header, and pass origin and destination as strings of up to 500 characters each. The endpoint returns the route as JSON, using Google Maps data collected from publicly available sources and returned as found at the time of the call. This is the recorded request, New York to Boston:
curl "https://api.perceptlayer.com/v1/google-maps/directions?origin=New+York%2C+NY&destination=Boston%2C+MA" \
-H "X-API-Key: $API_KEY"
Keys start with sk_live_. If a header isn't possible, the api_key query parameter works too. The authentication docs cover both, and Get a free API key takes an email address and no credit card.
Here is the recorded response, trimmed with …. It has two entries in directions:
{
"search_parameters": {
"start_addr": "New York, NY",
"end_addr": "Boston, MA",
"travel_mode": "driving"
},
"places_info": [
{
"address": "New York, NY",
"data_id": "",
"gps_coordinates": { "latitude": 0, "longitude": 0 }
},
…
],
"directions": [
{
"travel_mode": "Driving",
"via": "I-90 E",
"distance": 346882,
"duration": 13584,
"formatted_distance": "216 miles",
"formatted_duration": "3 hr 46 min",
"extensions": ["This route has tolls."],
"trips": [
{
"distance": 346882,
"duration": 13584,
"formatted_distance": "346.9 km",
"formatted_duration": "3 hr 46 min",
"details": ["…", "…"]
}
],
"duration_in_traffic": 12969,
"formatted_duration_in_traffic": "3 hr 36 min",
"typical_duration_range": "3 hr 24 min to 4 hr 13 min"
},
{
"travel_mode": "Driving",
"via": "I-95 N",
"distance": 377053,
"duration": 15084,
"formatted_distance": "234 miles",
"formatted_duration": "4 hr 11 min",
"duration_in_traffic": 14025,
"typical_duration_range": "3 hr 39 min to 4 hr 30 min",
…
}
],
"status": "OK",
"routes_count": 3
}
Each entry in directions is one route option. via names the road, duration is the base time and duration_in_traffic is the figure with traffic, so the first route shows 13584 against 12969. typical_duration_range gives the usual spread as a string.
Three things to check before you build on it:
- Units.
distanceis a number (346882) anddurationis a number (13584). The docs don't state units, but the formatted strings beside them (346.9 km, 3 hr 46 min) are consistent with metres and seconds. - Formatted distance varies. In the recording,
formatted_distanceon the route says "216 miles" while the same route'stripsentry says "346.9 km". Parse the numericdistanceand format it yourself. - Coordinates and IDs. In
places_info, the recordedlatitudeandlongitudeare 0 anddata_idis empty. Don't rely on them for geocoding or joins.
Also, routes_count was 3 in this recording while directions held two entries, so don't assume the two match.
Which parameters does the Directions endpoint take?
Two are required and three are optional. Nothing else is documented for this endpoint, so there are no waypoint, departure-time or avoid options to rely on.
| Parameter | Type | Required | Notes |
|---|---|---|---|
origin |
string | yes | Up to 500 characters, for example New York, NY |
destination |
string | yes | Up to 500 characters, for example Boston, MA |
mode |
string | no | One of driving, walking, bicycling, transit |
hl |
string | no | string, optional |
gl |
string | no | string, optional |
One call is one origin and one destination. A route with stops in between is a series of calls, one per leg, which is how the cost example below counts it.
What does a delivery batch cost?
A dispatch tool that plans 500 routes a day for 30 days makes 15,000 calls. At 1 credit each, that's 15,000 calls × 1 credit = 15,000 credits a month. The 1,000 free credits you get each month after verifying an email cover the first two days of that batch; the rest comes from a prepaid pack.
Packs start at 10,000 credits (Starter) and 50,000 (Build). Purchased credits last 12 months, and there's no subscription. Pricing has what each pack costs. We state costs in credits only because prices change.
Rate matters for a batch too. Free accounts get 1 request a second, so 500 routes take about 500 seconds if you send them one after another. Paying accounts run at least 5 requests a second (300 a minute), which brings the same 500 routes down to about 100 seconds. Limits are per account and shared by all its keys; see the rate limits docs.
How does that compare with Google's per-request pricing?
Google bills Directions per 1,000 requests, with a monthly free cap per SKU. Google's pricing page (checked October 2026) lists the legacy Directions SKU (Essentials) at $5.00 per 1,000 requests with 10,000 free events a month, and Directions Advanced (Pro) at $10.00 with 5,000 free. The current Routes API is the same: Compute Routes Essentials is $5.00 with 10,000 free, Pro $10.00 with 5,000 free, and Enterprise $15.00 with 1,000 free.
Which SKU you hit depends on the request. Per Google's Directions usage and billing page, Essentials covers 1 to 10 waypoints, and Pro covers 11 to 25 waypoints, traffic data or waypoint optimization.
Here's the same 15,000-route month, worked through with Google's published first-tier rates:
| Option | Calls | Free cap | Billable | Cost at first-tier rate |
|---|---|---|---|---|
| Google Directions Essentials | 15,000 | 10,000 | 5,000 | 5 × $5.00 = $25.00 |
| Google Directions Advanced (Pro) | 15,000 | 5,000 | 10,000 | 10 × $10.00 = $100.00 |
/v1/google-maps/directions |
15,000 | 1,000 credits (monthly free tier) | 14,000 credits | 14,000 credits, priced on pricing |
Verdict: at 15,000 calls a month, Google's Essentials row is cheap once its free cap is used, and we won't claim credits beat it on price. The dollar figures in that table are Google's; our side is 15,000 credits, or 14,000 after the free tier's 1,000, and pricing shows what those cost. The credit side has no per-SKU tiers: 1 credit a call, whatever the mode, and the recorded response already includes duration_in_traffic and a second route. It also suits you if you'd rather skip a Google Cloud billing setup. Check what credits cost on pricing and compare it with your own call count and SKU. The same logic applies to place data, which we covered in the Places API alternative.
When should you use Google's API instead?
Use Google's official API when your product draws routes on a Google map, when you need stops along the way, a departure time or route restrictions, or when your legal team requires Google's own terms of service. This endpoint documents none of waypoints, departure time or avoid options, so you can't ask for them. Google publishes its own rules in the Google Maps Platform terms of service, so read them before you display Google's results. Perceptlayer's data is collected from publicly available sources, and restricted endpoints need the restricted-endpoint terms accepted in the dashboard.
There's also a timing point. As of October 2026, the Directions API (Legacy) can't be enabled on new Google Cloud projects, and existing projects stay supported (Google, Directions API usage and billing). For new projects, Google's Routes API documentation is the place to start, and its migration section covers moving over from Directions.
The per-call endpoint fits when you want route data as JSON in a back-end job, an analytics pipeline or an agent tool, with one key and one cost per route.
How do you run a batch from Python?
Loop over your origin and destination pairs, pause on rate-limit responses and save the raw JSON. This script runs as written once API_KEY is set. It writes each body to a file and prints the via and duration_in_traffic of each returned route.
import json
import os
import time
import requests
BASE = "https://api.perceptlayer.com/v1/google-maps/directions"
HEADERS = {"X-API-Key": os.environ["API_KEY"]}
pairs = [
("New York, NY", "Boston, MA"),
("Boston, MA", "New York, NY"),
]
results = []
for origin, destination in pairs:
for attempt in range(3):
r = requests.get(
BASE,
headers=HEADERS,
params={"origin": origin, "destination": destination, "mode": "driving"},
timeout=30,
)
if r.status_code in (429, 503):
time.sleep(int(r.headers.get("Retry-After", "1")))
continue
break
print(r.status_code, r.headers.get("X-Credits-Used"), r.headers.get("X-Credits-Remaining"))
if r.ok:
body = r.json()
for route in body.get("directions", []):
print(route.get("via"), route.get("duration_in_traffic"))
results.append({"origin": origin, "destination": destination, "route": body})
with open("routes.json", "w") as f:
json.dump(results, f, indent=2)
Rate-limited (429) and temporarily unavailable (503) replies carry a Retry-After header with the seconds to wait, and the script honours it. Retries on a rate limit are safe because the rejected call wasn't billed. A client timeout is different: the request may have succeeded and been billed, because requests have no idempotency key. For error codes and bodies, read the errors docs.
Check X-Credits-Remaining on each response. The service is prepaid, so when the balance runs out calls return insufficient_credits (402) and nothing more is debited.
Can an AI agent call it as a tool?
Yes. The same key works through the MCP server at https://api.perceptlayer.com/mcp. Its search_endpoints and get_endpoint tools only look up the catalogue and cost nothing, and call_endpoint takes the endpoint ID plus origin and destination and spends 1 credit on success. The AI agents docs show the setup, and MCP vs function calling explains which to pick.
A routing question in an agent is then one tool call. Cap the number of calls per run, because each route is a credit.
Next step
Run the cURL call above with your own key, or try your own pair in the playground on the Directions endpoint page, and check X-Credits-Used for the 1-credit cost. For the other Google Maps endpoints, see the business data guide and the credits docs.
APIs in this post
Frequently asked questions
Does the Directions endpoint support waypoints?
Not as a documented parameter. The endpoint takes origin, destination, mode, hl and gl, and nothing else is documented. For a route with stops, call it once per leg, which costs 1 credit per leg. The same goes for departure time and avoid options, which aren't documented. If you depend on waypoint optimization, Google's official API supports up to 25 waypoints per request.
How much does one route cost?
One successful call costs 1 credit, shown on the endpoint page. A failed call costs 0 credits and returns X-Credits-Used: 0. So 15,000 routes cost 15,000 credits. The pricing page lists what credits cost, and the free tier gives 1,000 credits every month after email verification.
Which travel modes can I request?
Set mode to driving, walking, bicycling or transit. Those are the four documented values. Each call returns one mode, so comparing driving with transit for the same trip takes two calls, or 2 credits. The recorded call omitted mode and returned driving in travel_mode, but the default isn't documented, so set it explicitly.
What happens when I hit the rate limit?
You get a 429 with a Retry-After header holding the seconds to wait. Free accounts get 1 request a second; paying accounts run at least 5 a second. Rate-limited calls aren't billed. Wait the stated time, then retry, as the Python script above does. Details are in the rate limits docs.
Is Google's Directions API being retired?
Google says the Directions API (Legacy) can no longer be enabled for new Cloud projects as of October 2026, while existing projects remain fully supported (Google, Directions API usage and billing, 2026). New projects use the Routes API instead.