google-places-api
Google Places API
Google's local business results as JSON, searched from the city you name. Twenty places a page, each with its rating, category, address, coordinates and Google's own place id.
Endpoint
One credit per request. A page carries twenty places, the same twenty Google ranks for that query in that city.
curl -G "https://api.serpix.io/v1/places" \
--data-urlencode "q=personal injury lawyer" \
--data-urlencode "location=New York, New York, United States" \
-H "Authorization: Bearer $SERPIX_API_KEY"The same parameters are accepted as a JSON body on POST /v1/places:
curl -X POST "https://api.serpix.io/v1/places" \
-H "Authorization: Bearer $SERPIX_API_KEY" \
-H "Content-Type: application/json" \
-d '{"q": "personal injury lawyer", "location": "New York"}'Parameters
A local query answered from the wrong city is worse than no answer, so the origin is the parameter that matters here. Give location a city name and Serpix resolves it against Google's own geotarget list, echoing the canonical match back as location_used. A name that cannot be resolved fails the request instead of quietly searching somewhere else, and costs nothing.
| field | type | default | description |
|---|---|---|---|
| qrequired | string | – | The search query. |
| gl | string | – | Country, as a two-letter code. Defaults to the country of location when you set one, else us. |
| hl | string | en | Language of the results page, two-letter code. |
Search origin
A place name covers most work; coordinates are there for when a city is too coarse, and Google measures distance from them. They are two ways to write one thing, so a request carries one or the other.
| field | type | default | description |
|---|---|---|---|
| location | string | – | City to search from, such as New York, New York, United States. Cannot be combined with lat/lon. |
| lat | number | – | Latitude of a precise origin, for when a city is too coarse. Send with lon. |
| lon | number | – | Longitude of a precise origin. Send with lat. |
Results
| field | type | default | description |
|---|---|---|---|
| device | desktop | mobile | tablet | desktop | Results as Google serves them to a desktop browser or a phone. |
| page | integer | 1 | 1-based page. Each page is a fresh twenty places. One credit per page. |
| autocorrect | boolean | true | Set false to search the query exactly as typed, excluding results Google returns for its spell-corrected guess. |
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:
| field | type | default | description |
|---|---|---|---|
| uule | 422 | – | Use location with a city name, or lat/lon. The geo encoding is handled for you. |
| num | 422 | – | Google serves twenty places a page. Paginate with page. |
| start | 422 | – | Use page, a 1-based page number, instead of a result offset. |
| ludocid | 422 | – | Single-place lookup by CID is not wired yet. Search by q; every result carries its own place_id. |
| lsig | 422 | – | Not supported. |
| tbs / lr | 422 | – | Not supported on this vertical. |
| google_domain | 422 | – | Not supported on this vertical. |
| nfpr | 422 | – | Use autocorrect. |
| udm / tbm | 422 | – | Not needed. This endpoint is the local vertical, which is where Google now sends the legacy tbm=lcl itself. |
| engine | 422 | – | Not needed. This endpoint is Google Places. |
| api_key | 422 | – | Authenticate with the Authorization header, never the query string. |
HTTP/2 422
content-type: application/json
{
"detail": [
{
"type": "value_error",
"loc": ["query"],
"msg": "Value error, `uule` is not supported: use `location` with a city name, or `lat`/`lon` — the uule encoding is handled for you",
"input": { "q": "plumber", "uule": "w+CAIQICIfTmV3...", ... }
}
]
}Response
A search returns one JSON object: two envelope objects that are always present (search_metadata, search_parameters) and the ranking as place_results. A field that wasn't served is omitted entirely, never null, never [], so a presence check is all you need before reading one.
{
"search_metadata": {
"id": "srx_t9z8wvsWh1PbBHOd",
"status": "success",
"created_at": "2026-07-28T18:19:33Z",
"took_ms": 1391,
"parser_version": "2026.07.1",
"google_url": "https://www.google.com/search?q=personal+injury+lawyer&udm=1&hl=en&gl=us&uule=w+CAIQICIfTmV3...",
"html_url": "https://api.serpix.io/searches/srx_t9z8wvsWh1PbBHOd/ACWNx0EG7LL4-Xzw.html",
"json_url": "https://api.serpix.io/searches/srx_t9z8wvsWh1PbBHOd/ACWNx0EG7LL4-Xzw.json"
},
"search_parameters": {
"q": "personal injury lawyer",
"gl": "us",
"hl": "en",
"device": "desktop",
"page": 1,
"location_used": "New York,New York,United States"
},
"place_results": [
{
"position": 1,
"title": "NYC Injury Attorneys P.C.",
"rating": 4.9,
"reviews": 88,
"type": "Personal injury attorney",
"years_in_business": "5+ years in business",
"address": "New York, NY",
"phone": "(646) 452-3663",
"hours": "Open 24 hours",
"description": "\"Their expertise and knowledge of personal injury law are unparalleled.\"",
"place_id": "7374717274750031334",
"provider_id": "/g/11q7b8804c",
"gps_coordinates": { "latitude": 40.711964, "longitude": -74.00853 },
"link": "https://nyc-injury-attorneys.com/"
},
...
],
"pagination": {
"current": 1,
"next": "https://www.google.com/search?q=personal+injury+lawyer&udm=1&hl=en&gl=us&start=20&..."
}
}Every response also reports its cost in the X-Serpix-Credits-Charged and X-Serpix-Credits-Remaining headers.
search_metadata
| field | type | default | description |
|---|---|---|---|
| id | string | – | Unique id of this search, srx_ prefixed. |
| status | string | – | success on every 200. |
| created_at | string | – | When the search ran, ISO 8601 UTC. |
| took_ms | integer | – | End-to-end time to serve this response, in milliseconds. |
| parser_version | string | – | Dated version of the places parser that produced this response, so any response can be tied to the parsing behaviour that made it. Each vertical carries its own. |
| google_url | string | – | The exact Google URL fetched. |
| html_url | string | – | Archived copy of the results page exactly as served. Included when available. |
| json_url | string | – | Archived copy of this JSON response. Included when available. |
search_parameters
The parameters the search actually ran with, defaults filled in.
| field | type | default | description |
|---|---|---|---|
| q | string | – | The query as received. |
| gl | string | – | Country the search ran from. |
| hl | string | – | Language used. |
| device | string | – | Device profile used. |
| page | integer | – | Page served. |
| location_used | string | – | The canonical geotarget your location resolved to. Present when sent. |
| lat | number | – | Latitude the search ran from. Present when sent. |
| lon | number | – | Longitude the search ran from. Present when sent. |
place_results
| field | type | default | description |
|---|---|---|---|
| position | integer | – | Rank on the page, starting at 1. Sponsored cards are not counted here. |
| title | string | – | The business name. |
| rating | number | – | Star rating out of five. |
| reviews | integer | – | Number of Google reviews behind that rating, as a number: 1.2K comes back as 1200. |
| price | string | – | Price band as displayed, either a range like $1–10 or a symbol run. |
| type | string | – | Business category Google prints, such as Coffee shop. |
| years_in_business | string | – | Tenure chip on trade listings, as displayed (3+ years in business). |
| address | string | – | Street address, or the service area on trades that list one. |
| phone | string | – | Phone number as displayed. |
| hours | string | – | Opening state as displayed, such as Open · Closes 8 PM. |
| description | string | – | The review quote Google surfaces on the card, quotes kept. |
| place_id | string | – | Google's CID for the business, stable across searches and the field to key your own records on. |
| provider_id | string | – | Google's knowledge-graph id for the same business. |
| gps_coordinates | object | – | Latitude and longitude of the listing. |
| thumbnail | string | – | Place photo, when the card shows one. |
| link | string | – | The business's own website. Never a Google viewer or maps link, so it is safe to follow. |
Which fields a card carries follows the query rather than the parser: cafés print a price band and a photo, trades print a phone number, opening hours and a website.
pagination
Ask for the next page with page. pagination.next is read off Google's own forward control, so its absence is how you know you have reached the last page.
| field | type | default | description |
|---|---|---|---|
| current | integer | – | The page this response is. |
| next | string | – | Google URL for the next page. Absent on the last one. |
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.
| field | type | default | description |
|---|---|---|---|
| 401 | unauthorized | −0 | Missing, malformed, or revoked key. See Authentication. |
| 402 | payment required | −0 | The balance can't cover a search. See Credits & billing. |
| 422 | invalid request | −0 | Unknown or invalid parameter, or a location that could not be resolved. The detail says what to fix, with close matches for a near-miss city. |
| 502 | search_failed | −0 | The search could not be completed. Retry it; you were not charged. |
| 503 | search_unavailable | −0 | Google did not serve a usable results page. Retry it; you were not charged. |
HTTP/2 502
content-type: application/json
x-serpix-credits-charged: 0
{ "error": { "code": "search_failed", "search_id": "srx_kq3v9tR2xLw8mA1c" } }