Google Maps data, one request away
A ready-to-use REST API for Google Maps. Search a point for its local businesses, resolve any place by its place_id into its full record, pull the complete review set, or rank a business across a local search grid, all matched by stable place id, billed only for successful calls.
Introduction
The Hexscraper API is a synchronous request/response service: you call an endpoint, you get the data back in the same HTTP response, no queue or webhook to manage. Every business is addressed by its Google place_id (a CID-backed ChIJ… id), so results are never confused between same-name look-alikes.
All responses are JSON. The base URL is https://api.hexscraper.com.
Authentication
Authenticate every request with an API key in the Authorization header as a Bearer token. Keys are issued per account, so keep them server-side and never ship one to a browser.
Authorization: Bearer sk_live_xxxxxxxxxxxxxxxxxxxxxxxxA missing or invalid key returns 401.
Billing & credits
Usage is metered in credits. Billing is reserve-then-refund: a call reserves its credits up front and refunds anything unused, so you only pay for successful results. A 4xx, a 503, or an upstream failure is never charged.
| Endpoint | Cost |
|---|---|
| GET /v1/search | 1 credit per non-empty search (~20 businesses); empty is free |
| GET /v1/places/{id} | 1 credit per lookup |
| GET /v1/places/{id}/reviews | 1 credit per 10 reviews returned (min 1) |
| GET /v1/visibility | grid_size² credits (e.g. a 5×5 grid = 25) |
A cache hit still bills (it saves you the latency, not the credit). Running out of credits returns 402.
Rate limits
Limits are per account, over a fixed one-minute window: 120/min for place lookups and the visibility grid, 60/min for reviews (each reviews call can page a lot of data). Exceeding a limit returns 429 with a Retry-After header, and is never billed.
Idempotency
Send an Idempotency-Key header on any request. A retry carrying the same key replays the stored response without re-charging or re-scraping; a concurrent duplicate gets 409 while the first is still running.
Idempotency-Key: 9f1c2b7a-restaurant-batch-042Errors
Errors use standard HTTP status codes and a JSON body { "detail": "…" }. A 503means the data was temporarily unavailable (not that the place doesn't exist). Retry after the Retry-After delay; it is never billed.
| Status | Meaning |
|---|---|
| 400 | Malformed place_id (not a CID-backed ChIJ… id) or invalid parameters. |
| 401 | Missing or invalid API key. |
| 402 | Out of credits. Top up to continue. |
| 409 | A request with the same Idempotency-Key is already in progress. |
| 429 | Rate limit exceeded. Honour the Retry-After header. Not billed. |
| 503 | Temporarily unavailable (upstream/farm). Retry after Retry-After. Not billed. |
Point search
1 credit/v1/searchQuery parameters
| Field | Type | Description |
|---|---|---|
| keywordrequired | string | The search term, e.g. "tapas" or "dentist". URL-encode spaces and accents (a space becomes %20). |
| latrequired | number | Latitude of the search centre (−90 to 90). |
| lonrequired | number | Longitude of the search centre (−180 to 180). |
| hl | string | Google Maps host language for the response, e.g. "es" or "pt-BR". Categories, attributes and price formatting come back in that language, and they are Google's own strings, not a translation. Defaults to English. |
Request
curl "https://api.hexscraper.com/v1/search?keyword=tapas&lat=36.3707&lon=-6.1809" \
-H "Authorization: Bearer $HEXSCRAPER_API_KEY"Response
{
"keyword": "tapas",
"latitude": 36.3707,
"longitude": -6.1809,
"count": 20,
"results": [
{
"place_id": "ChIJx3-pvNszDA0R837NptBLjM4",
"name": "Café bar la Almadraba",
"rating": 4.6,
"reviews_count": 1071,
"price_level": "€10-20",
"phone": null,
"website": null,
"address": "Avenida la Barrosa, 11130 Chiclana, Cádiz",
"city": "Chiclana",
"latitude": 36.3707792,
"longitude": -6.180956,
"categories": ["Restaurante", "Bar", "Pub"],
"primary_category": "Restaurante",
"business_status": "Open"
}
]
}An empty result (no businesses at that point) returns count: 0 and is not billed. For richer fields on a single business (amenities, popular times, the full review set), feed a result's place_id into the endpoints below.
Place details
1 credit/v1/places/{place_id}Path parameters
| Field | Type | Description |
|---|---|---|
| place_idrequired | string | A CID-backed Google place_id (ChIJ…). |
Query parameters
| Field | Type | Description |
|---|---|---|
| hl | string | Google Maps host language for the response, e.g. "es" or "pt-BR". Defaults to English. |
Request
curl "https://api.hexscraper.com/v1/places/ChIJx3-pvNszDA0R837NptBLjM4" \
-H "Authorization: Bearer $HEXSCRAPER_API_KEY"Response
{
"place_id": "ChIJx3-pvNszDA0R837NptBLjM4",
"name": "Café bar la Almadraba",
"rating": 4.6,
"reviews_count": 1071,
"price_level": "€10-20",
"website": null,
"phone": null,
"address": "Avenida la Barrosa, 11130 Chiclana, Cádiz",
"city": "Chiclana",
"country_code": "ES",
"latitude": 36.3707792,
"longitude": -6.180956,
"categories": ["Restaurante", "Bar", "Pub"],
"primary_category": "Restaurante",
"business_status": "Open",
"is_claimed": true,
"owner_name": "Café bar la Almadraba",
"time_spent": "People typically spend 45 min to 1.5 hr here",
"reviews_tags": [
{ "keyword": "tapas", "count": 83 },
{ "keyword": "fried fish", "count": 12 }
],
"popular_times": { "Friday": [[12, 0], [13, 54], [20, 88], [21, 71]] },
"people_also_search": [
{ "name": "EL ARBOL TAPAS", "cid": "0x0:0x9f69...", "rating": 4.7, "reviews": 6988 }
],
"rating_summary": [
{ "stars": 5, "amount": 784 },
{ "stars": 4, "amount": 199 }
],
"reviews": [
{
"review_id": "ChZ...",
"author_name": "A VG",
"review_rating": 2,
"review_text": "Overpriced for what it is.",
"review_datetime_utc": "2025-06-29T20:58:02+00:00"
}
],
"business_description": "Pollos asados y pescado frito en casa, también para llevar.",
"popular_dishes": [{ "name": "Medio Pollo Con Patatas", "photo": "https://lh3..." }],
"menu": [
{
"section": "Pizzas y pasta",
"items": [
{ "name": "Pizza Margarita", "description": "Base fina…", "price": "€10.50", "photo": "https://lh3..." }
]
}
],
"photo_categories": ["Del propietario", "Carta", "Comida y bebida", "Ambiente"],
"posts": [
{ "text": "QUESO GORGONZOLA: origen y sabor…", "date": "Aug 4, 2026", "timestamp": 1785848535, "image": "https://lh3…", "cta_label": "Book", "cta_url": "https://…" }
],
"action_links": [
{ "url": "https://www.google.com/maps/reserve/v/dine/c/…", "label": "google.com" }
]
}Reviews
1 credit / 10 reviews/v1/places/{place_id}/reviewsPath parameters
| Field | Type | Description |
|---|---|---|
| place_idrequired | string | A CID-backed Google place_id (ChIJ…). |
Query parameters
| Field | Type | Description |
|---|---|---|
| limit | integer | Max reviews to return. Default 10, no hard cap; bounded by the place's actual review count and your credit balance. |
| hl | string | Google Maps host language for the response, e.g. "es" or "pt-BR". Categories, attributes and price formatting come back in that language, and they are Google's own strings, not a translation. Defaults to English. |
Request
curl "https://api.hexscraper.com/v1/places/ChIJTzciJkUxDA0RtK7jOAlZTKo/reviews?limit=50" \
-H "Authorization: Bearer $HEXSCRAPER_API_KEY"Response
{
"place_id": "ChIJTzciJkUxDA0RtK7jOAlZTKo",
"count": 50,
"reviews": [
{
"review_id": "ChdD...",
"author_id": "1094...",
"author_name": "Pilar Pavón",
"author_link": "https://www.google.com/maps/contrib/1094...",
"review_rating": 5,
"review_text": "Absolutely phenomenal food. The garlic prawns...",
"review_timestamp": 1751803869,
"review_datetime_utc": "2025-07-06T12:11:09+00:00",
"relative_date": "2 months ago"
}
]
}Visibility grid
grid_size² credits/v1/visibilityQuery parameters
| Field | Type | Description |
|---|---|---|
| place_idrequired | string | The business to rank (a CID-backed ChIJ… id). |
| keywordrequired | string | The search term to rank for, e.g. "tapas" (URL-encode special characters). |
| grid_size | integer | Odd number 3–9. Default 5 (a 5×5 grid = 25 searches). |
| radius_m | integer | Grid half-width in metres, 1–50000. Default 1000. The response echoes it as radius_km. |
| hl | string | Google Maps host language for the response, e.g. "es" or "pt-BR". Defaults to English. |
Request
curl "https://api.hexscraper.com/v1/visibility?place_id=ChIJx3-pvNszDA0R837NptBLjM4&keyword=tapas&grid_size=5&radius_m=1000" \
-H "Authorization: Bearer $HEXSCRAPER_API_KEY"Response
{
"keyword": "tapas",
"target_place_id": "ChIJx3-pvNszDA0R837NptBLjM4",
"target_name": "Café bar la Almadraba",
"center_lat": 36.3707792,
"center_lon": -6.180956,
"grid_size": 5,
"radius_km": 1.0,
"total_points": 25,
"found_in": 18,
"average_rank": 3.4,
"grid": [
{ "row": 0, "col": 0, "lat": 36.3752, "lon": -6.1849,
"rank": 2, "top_result": "Café bar la Almadraba", "total_results": 20 }
],
"competitors": [
{ "place_id": "0x0:0x9f69...", "name": "EL ARBOL TAPAS",
"appearances": 22, "avg_rank": 1.8, "best_rank": 1, "top3_count": 20,
"total_reviews": 6988, "avg_rating": 4.7, "is_target": false }
],
"top_rankings": [ { "name": "Café bar la Almadraba", "count": 18 } ],
"degraded": false
}If the results look degraded (Google blanked review counts on a burned session), the response sets degraded: true. The data may be incomplete and is not cached.
Ready to build?
Get an API key and your first credits to start pulling Google Maps data.
