serpix

google-maps-api

Google Maps API

Google Maps place search as JSON. Twenty places a page, each with its coordinates, rating, address, opening hours and the identifiers you need to look it up again, searched from a point on the map you choose.

Endpoint

One credit per request. Coordinates are the search origin, not a refinement: send lat and lon together and Google searches outward from that point. Leave them off and it centres wherever the request appears to come from, which is not a place you chose.

GET/v1/maps
bash
curl -G "https://api.serpix.io/v1/maps" \
  --data-urlencode "q=coffee" \
  --data-urlencode "lat=30.2672" \
  --data-urlencode "lon=-97.7431" \
  -H "Authorization: Bearer $SERPIX_API_KEY"

The same parameters are accepted as a JSON body on POST /v1/maps:

post variant
curl -X POST "https://api.serpix.io/v1/maps" \
  -H "Authorization: Bearer $SERPIX_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"q": "coffee", "lat": 30.2672, "lon": -97.7431, "zoom": 14}'

Parameters

Query and origin
fieldtypedescription
qrequiredstringWhat to search for, like coffee or hardware store.
latnumberLatitude of the map centre. Send with lon; one without the other is a 422.
lonnumberLongitude of the map centre. Send with lat.
zoomintegerHow much map to cover, 3 for a continent and 21 for a street corner. Defaults to 14, which is roughly a neighbourhood.

Results

Results
fieldtypedescription
glstringCountry, two-letter code. Defaults to us.
hlstringLanguage of the results, two-letter code.
pageinteger1-based page, twenty places each. Pages do not overlap: page 2 is twenty different places, not the same list shifted along. One credit per page.

Rejected parameters

Unknown parameters are never silently ignored. A request carrying one is rejected with 422 before any search runs, so a typo can't bill you for results you didn't ask for. Common parameters from raw Google URLs and other SERP APIs get a pointed message naming the equivalent here:

Rejected aliases
fieldtypedescription
location422This vertical needs real coordinates, so send lat and lon. The geotarget dataset carries names and countries but no coordinates, so a city name has no centre to resolve to here.
ll422Use lat, lon and zoom. The @lat,lng,zoom encoding is handled for you.
pb422Not needed. The Maps protobuf is compiled from lat, lon and zoom.
num422Google serves twenty places a page. Paginate with page.
start422Use page, a 1-based page number, instead of a result offset.
place_id / data_cid / type422This endpoint is the place search. Single-place lookup by id is not wired yet; search by q and every result carries its own ids.
data422Not supported.
google_domain422Not supported on this vertical.
tbm422Not needed. This endpoint is Google Maps.
engine422Not needed. This endpoint is Google Maps.
api_key422Authenticate with the Authorization header, never the query string.
422 · rejected parameter
HTTP/2 422
content-type: application/json

{
  "detail": [
    {
      "type": "value_error",
      "loc": ["query"],
      "msg": "Value error, `location` is not supported: this vertical needs real coordinates: send `lat`/`lon`. The geotarget dataset has no coordinates, so a city name cannot be resolved to a map centre here",
      "input": { "q": "coffee", "location": "Austin", ... }
    }
  ]
}

Response

A search returns one JSON object: two envelope objects that are always present (search_metadata, search_parameters), the places as local_results, and pagination. A field that wasn't served is omitted entirely, never null, never [], so a presence check is all you need before reading one.

200 · trimmed
{
  "search_metadata": {
    "id": "srx_q1-fNfV_VuwbwvsA",
    "status": "success",
    "created_at": "2026-07-28T19:24:51Z",
    "took_ms": 5195,
    "parser_version": "2026.07.1",
    "google_url": "https://www.google.com/search?tbm=map&hl=en&gl=us&q=coffee&pb=!1scoffee!4m8!1m3!1d27567.5...",
    "html_url": "https://api.serpix.io/searches/srx_q1-fNfV_VuwbwvsA/GG8owWxcUIMZluIr.html",
    "json_url": "https://api.serpix.io/searches/srx_q1-fNfV_VuwbwvsA/GG8owWxcUIMZluIr.json"
  },
  "search_parameters": {
    "q": "coffee",
    "gl": "us",
    "hl": "en",
    "page": 1,
    "zoom": 14,
    "latitude": 30.2672,
    "longitude": -97.7431
  },
  "local_results": [
    {
      "position": 1,
      "title": "UFO Coffee & Tea",
      "place_id": "ChIJ0S8AJAC1RIYRLIa71SkPRXc",
      "data_id": "0x8644b50024002fd1:0x77450f29d5bb862c",
      "gps_coordinates": { "latitude": 30.2844171, "longitude": -97.71734699999999 },
      "rating": 4.9,
      "reviews": 40,
      "type": "Coffee shop",
      "types": ["Coffee shop"],
      "type_id": "coffee_shop",
      "address": "2307 1/2 Manor Rd, Austin, TX 78722",
      "neighborhood": "East Austin",
      "country": "US",
      "timezone": "America/Chicago",
      "phone": "(512) 850-5150",
      "phone_e164": "+15128505150",
      "website": "http://ufo-coffee.com/",
      "provider_id": "/g/11yr_2ytl2",
      "reviews_link": "https://search.google.com/local/reviews?placeid=ChIJ0S8AJAC1RIYRLI...",
      "operating_hours": {
        "Monday": "7 AM–4 PM",
        "Tuesday": "7 AM–4 PM",
        ...
      }
    },
    ...
  ],
  "pagination": {
    "current": 1,
    "next": "https://www.google.com/search?tbm=map&hl=en&gl=us&q=coffee&pb=!1scoffee!4m8...!8i20!..."
  }
}

Every response also reports its cost in the X-Serpix-Credits-Charged and X-Serpix-Credits-Remaining headers.

search_metadata

search_metadata fields
fieldtypedescription
idstringUnique id of this search, srx_ prefixed.
statusstringsuccess on every 200.
created_atstringWhen the search ran, ISO 8601 UTC.
took_msintegerEnd-to-end time to serve this response, in milliseconds.
parser_versionstringDated version of the maps parser that produced this response, so any response can be tied to the parsing behaviour that made it. Each vertical carries its own.
google_urlstringThe exact Maps URL fetched, protobuf and all, so a response can be traced back to the map window it came from.
html_urlstringArchived copy of the payload exactly as served. Included when available.
json_urlstringArchived copy of this JSON response. Included when available.

search_parameters

The parameters the search actually ran with, defaults filled in.

search_parameters fields
fieldtypedescription
qstringThe query as received.
glstringCountry the search ran from.
hlstringLanguage used.
pageintegerPage served.
zoomintegerZoom level used.
latitudenumberLatitude of the map centre. Present when sent.
longitudenumberLongitude of the map centre. Present when sent.

Three identifiers

Google keeps three ids for a place and they are not interchangeable, so each keeps its own name here rather than being flattened into one:

place identifiers
fieldtypedescription
place_idstringThe Places reference, like ChIJ0S8AJAC1RIYRLIa71SkPRXc. This is the id most Google tooling means by “place id”.
data_idstringThe legacy hex pair, like 0x8644b50024002fd1:0x77450f29d5bb862c.
data_cidstringThe decimal customer id. Confusingly, this is the value other Google surfaces call place_id, including the local pack on a web search.

local_results

local_results entry fields
fieldtypedescription
positionintegerRank in the results, starting at 1.
titlestringThe place's name.
place_idstringPlaces reference. See above.
data_idstringLegacy hex identifier. See above.
data_cidstringDecimal customer id. See above.
gps_coordinatesobjectThe place's own latitude and longitude.
ratingnumberAverage rating out of 5.
reviewsintegerNumber of reviews behind that rating.
typestringPrimary category as displayed, like Coffee shop.
typeslistEvery category Google lists for the place.
type_idstringMachine-readable category, like coffee_shop.
addressstringStreet address on one line.
neighborhoodstringNeighbourhood, where Google names one.
countrystringTwo-letter country code.
timezonestringIANA timezone, like America/Chicago.
phonestringPhone number as displayed, like (512) 850-5150.
phone_e164stringThe same number in dialable E.164 form.
websitestringThe business's own site, when it lists one.
provider_idstringGoogle knowledge identifier, like /g/11njyz2l2k.
thumbnailstringPlace photo.
reviews_linkstringGoogle's reviews page for the place.
operating_hoursobjectOpening hours by day, as displayed.
gps_coordinates object
fieldtypedescription
latitudenumberLatitude in decimal degrees.
longitudenumberLongitude in decimal degrees.

Which fields a place carries follows the listing rather than the parser: on the sample request every place carried opening hours, and nine of the twenty carried a phone number, because the rest publish none.

pagination

Ask for the next page with page. pagination.next is present while another page exists, so its absence is how you know the results ran out.

pagination fields
fieldtypedescription
currentintegerThe page this response is.
nextstringURL for the next page. Absent once the results run out.

Errors

A rejected request answers with detail, naming the parameter and what to send in its place. A search that could not be completed answers with error and a search_id you can quote. No error is ever charged.

Status codes
fieldtypedescription
401unauthorizedMissing, malformed, or revoked key. See Authentication.
402payment requiredThe balance can't cover a search. See Credits & billing.
422invalid requestUnknown or invalid parameter, or lat without lon. The detail says what to send instead.
502search_failedThe search could not be completed, which on this vertical also covers a payload whose shape drifted. Retry it; you were not charged.
503search_unavailableGoogle did not serve a usable payload. Retry it; you were not charged.
502 · search failed
HTTP/2 502
content-type: application/json
x-serpix-credits-charged: 0

{ "error": { "code": "search_failed", "search_id": "srx_kq3v9tR2xLw8mA1c" } }