Google Maps Directions Scraper
Pricing
from $0.90 / 1,000 route chargeds
Google Maps Directions Scraper
Get driving/walking/transit routes from Google Maps. Talks directly to Google Maps' internal mobile API, no login needed. Split from the mature, published google-maps-all-in-one-api for a focused, single-purpose workflow.
What does Google Maps Directions Scraper do?
Google Maps Directions Scraper fetches routes (driving, walking, transit, motorcycle) to one or more destinations and pushes one dataset row per route — duration, distance, tolls/advisories, and, for DRIVE/WALK/MOTORCYCLE, a linestring of [lng, lat] points; TRANSIT routes instead return per-leg detail (line, stops, schedule).
It talks directly to the same internal gRPC API the official Google Maps Android app uses (mobilemaps-pa-gz.googleapis.com, MobileMapsDirectionsService/GetDirections), reverse-engineered by live capture against a real device. No Google account, no API key, no browser automation. This is the /directions slice of Google Maps API (the "all-in-one" Standby REST API), split out as its own focused, batch-run Actor.
Why use Google Maps Directions Scraper?
- Real, live route data — actual server-computed durations, distances, tolls/advisories, and turn-by-turn/transit detail, not a scrape of the maps.google.com web page
- All four travel modes — DRIVE, WALK, TRANSIT, MOTORCYCLE, each parsed into a typed shape
- Batch input — pass an array of destinations in one run, get one dataset row per resulting route
- No account needed — every request works fully anonymously
- Use cases: trip-planning tools, delivery/logistics ETA checks, transit-time comparison across candidate locations, real-estate "commute time" enrichment
Known limitations
- The origin is fixed and NOT configurable. Every request starts from a stub location baked into the captured request template that this Actor replays — only the destination is configurable. This is a limitation inherited directly from the parent Actor's own documented note: "Directions always starts from a fixed stub location baked into the request template — only the destination is configurable. A proper origin parameter would need a wider capture of the request shape." In practice this means the routes returned are not true point-A-to-point-B directions between two addresses you choose — treat the output as "routes from the fixed stub origin to your destination," not a general-purpose router. Confirmed live: the baked-in origin resolves to a real-world point in the Jakarta, Indonesia area — DRIVE/WALK/MOTORCYCLE requests for a destination outside that region (e.g. another continent) will correctly come back with zero routes for that mode, since no drivable/walkable route exists; this is expected, not a bug.
- Route parsing is heuristic, based on empirically reverse-engineered
.protofield numbers (no official schema exists from Google). A handful of fields (e.g.durationTextRaw) are typed as raw bytes rather than validated UTF-8 strings for this reason, and travel-mode inference for ambiguous alternatives falls back to a heuristic (duration/via-text based) when a mode isn't explicitly forced. - Coordinate extraction (
linestring) only covers DRIVE/WALK/MOTORCYCLE routes and only the coordinates present in walk-step detail — it is not a dense, full-resolution polyline of the entire route. - Only DRIVE, WALK, TRANSIT, and MOTORCYCLE modes are supported (the modes the reverse-engineered request templates cover).
Input
| Field | Type | Description |
|---|---|---|
destinations | array | Required, non-empty. One entry per destination to fetch routes to. |
destinations[].destName | string | Required. Human-readable destination name. |
destinations[].destFeatureId | string | Required. Google place feature id, e.g. from a search/geocode result (0x...:0x...). |
destinations[].destLat | number | Required. Destination latitude. |
destinations[].destLng | number | Required. Destination longitude. |
destinations[].modes | string[] | Optional. Any of DRIVE, WALK, TRANSIT, MOTORCYCLE. Default ["DRIVE"]. |
destinations[].maxRoutes | integer | Optional. Max routes returned per requested mode. Default 3. |
Origin is not part of the input schema — it cannot be set. See Known limitations above.
Example:
{"destinations": [{"destName": "Grand Indonesia","destFeatureId": "0x2e69f421c2ebd463:0xccfcc89b95aaf1ae","destLat": -6.1953681,"destLng": 106.8204181,"modes": ["DRIVE", "WALK"],"maxRoutes": 2}]}
Output
One dataset row per route:
{"destName": "Grand Indonesia","destFeatureId": "0x2e69f421c2ebd463:0xccfcc89b95aaf1ae","travelMode": "DRIVE","routeIndex": 0,"via": "I-95 N","durationText": "1 hr 4 min","durationS": 3849,"distanceM": 122000,"hasTolls": true,"isRecommended": true,"linestring": [[-77.5, 39.1],[-77.4, 39.05]]}
TRANSIT routes instead carry a legs array (per-leg line/stop/schedule detail) rather than a single linestring.
Pricing
Pay per event, via the route event — charged once per route pushed to the dataset (one event per dataset row, regardless of how many destinations/modes you request), starting at $0.001 (FREE tier). See the Actor's Pricing tab for current rates.