SFOLN

Catalogue / Local & maps

Google Maps Places Scraper

sfoln/google-maps-search · Lead generation, Travel, SEO tools On request

Search Google Maps by keyword and location and get one clean JSON row per place: name, category, address, phone, website, rating, review count, opening hours, coordinates and place ID. $0.80 per 1,000 places + $0.002 per search. No browser needed.

About

What it does

Google Maps Places Scraper searches Google Maps the way you would in the app — "roofing contractors Philadelphia", "dentist near Austin" — and returns one clean, normalized record per place: name, category, full address with parts, phone, website and domain, rating and review count, opening hours and open-now flag, coordinates, Google place ID and CID. Built for lead generation, local-SEO audits, market mapping and AI agents that need structured local business data in seconds, without running a browser.

Price

Price per delivered record

EventPricePer 1,000Charged for
Google Maps place
google-maps-place
$0.0008$0.80 / 1,000Charged once per Google Maps place (business) delivered as a dataset record.
Google Maps query
google-maps-query
$0.002$2 / 1,000Charged once per search query that returned at least one place, or that returned none but was billed upstream (covers the per-search upstream fee).

Apify free plan: up to 10 items per run. Paid plans have no per-run cap; set maxTotalChargeUsd to cap spend.

Run

Call it from code, an agent or the Console

This API is private on Apify for now. Email us and we will publish it for you, usually within two working days. The calls below work once it is public. contact@sfoln.com

curl · synchronous run, rows in the response
curl -X POST "https://api.apify.com/v2/actors/sfoln~google-maps-search/run-sync-get-dataset-items" \
  -H "Authorization: Bearer $APIFY_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"queries":["pizza restaurants in Brooklyn"],"location":"New York,New York,United States","maxPlacesPerQuery":5}'
mcp.json · hosted Apify MCP server
{
  "mcpServers": {
    "apify": {
      "type": "http",
      "url": "https://mcp.apify.com?tools=sfoln/google-maps-search"
    }
  }
}
asynchronous run · for large batches
POST https://api.apify.com/v2/actors/sfoln~google-maps-search/runs?maxTotalChargeUsd=1
GET  https://api.apify.com/v2/actor-runs/{runId}            # until status is SUCCEEDED
GET  https://api.apify.com/v2/datasets/{defaultDatasetId}/items?format=json

Authenticate with an Apify API token. MCP clients can instead sign in with OAuth when prompted. Example prompt for an agent: Find 20 pizza restaurants in Brooklyn on Google Maps and list their ratings, review counts, phone numbers and websites.

Input

Input fields

Enter one or more Google Maps searches. Every place found becomes one dataset record; each query also gets one summary record.

FieldTypeDefaultMeaning
queries *arrayrequiredSearch queries
What you would type into Google Maps, one per line (e.g. "roofing contractors Philadelphia"). To override the location for a single query write "query | location". Also accepts objects { "query": "...", "location": "..." }. Accounts on the Apify free plan can process up to 10 queries per run.
locationstring—Location
Where to search: a DataForSEO location name ("Philadelphia,Pennsylvania,United States"), a numeric location code (2840 = United States), or coordinates "latitude,longitude[,zoom]" (e.g. "40.6782,-73.9442,13"). Leave empty for the whole United States.
languageCodestring"en"Language code
Language of the results (ISO code such as en, de, es, fr, pt-br).
maxPlacesPerQueryinteger20Max places per query
How many places to return (and pay for) per query. Google Maps returns at most about 100 places per search. Range 1–100.
depthinteger—Search depth (advanced)
Number of results requested from Google per query (defaults to Max places per query, capped at 100 so each query stays one upstream search; values below Max places per query are raised to it). Places beyond Max places per query are discarded and never charged; raise it only if sponsored results crowd out regular places. Range 1–100.
devicestring"desktop"Device
Emulated device for the search. One of "desktop", "mobile".
maxQueriesinteger100Max queries
Safety cap on the number of queries processed in this run. Range 1–10000.
concurrencyinteger3Concurrency
How many queries run in parallel. Kept low because the upstream concurrency limit is shared by all runs of this Actor. Range 1–6.
includeRawbooleanfalseInclude raw upstream response
Attach the unmodified provider item to each place record (larger output).
Example input
{
  "queries": [
    "pizza restaurants in Brooklyn"
  ],
  "location": "New York,New York,United States",
  "maxPlacesPerQuery": 5
}

Output

One record per input item

Records land in the run's dataset; a synchronous call returns them directly. Each has a status (ok is charged; everything else is free) and a charged flag. The run's OUTPUT record totals items and charges.

FieldTypeMeaning
recordTypestringRecord type
place = one Google Maps place (charged google-maps-place); query = per-query summary (charged google-maps-query when ok). e.g. "place"
querystringQuery
Search query this record belongs to. e.g. "pizza restaurants in Brooklyn"
locationstringLocation
Location used for the search.
inputstring | object | nullInput
The query as entered ({ query, location? }).
rankinteger | nullRank
Position in the Google Maps results (1 = first).
titlestring | nullName
Business / place name.
originalTitlestring | nullOriginal name
Name in the original language, when Google shows a translated one.
descriptionstring | nullDescription
Owner description, when shown.
categorystring | nullCategory
Primary Google category.
additionalCategoriesarrayAdditional categories
Secondary Google categories.
categoryIdsarrayCategory ids
Google category ids, e.g. pizza_restaurant.
addressstring | nullAddress
Full formatted address.
addressInfoobject | nullAddress parts
street, borough, city, zip, region, countryCode.
phonestring | nullPhone
Phone number as shown on Google Maps.
urlstring | nullWebsite
Website URL.
domainstring | nullDomain
Website domain without www.
placeIdstring | nullPlace ID
Google place_id (ChIJ…).
cidstring | nullCID
Google customer id (maps.google.com/?cid=…).
featureIdstring | nullFeature ID
Google feature id.
latitudenumber | nullLatitude
WGS84 latitude.
longitudenumber | nullLongitude
WGS84 longitude.
ratingobject | nullRating
{ value, votesCount }
ratingDistributionobject | nullRating distribution
Number of reviews per star (1–5).
priceLevelstring | nullPrice level
inexpensive | moderate | expensive | very_expensive
hotelRatingnumber | nullHotel stars
Hotel class (stars), for hotels.
isClaimedboolean | nullClaimed
Whether the owner has verified the listing.
currentStatusstring | nullCurrent status
open | closed | temporarily_closed | closed_forever
openNowboolean | nullOpen now
True when open at crawl time.
workHoursSummarystring | nullOpening hours
Compact weekly hours, e.g. "Mon 09:00-17:00; …; Sun closed".
workHoursobject | nullOpening hours (structured)
Day → list of "HH:MM-HH:MM" ranges; null = closed.
mainImagestring | nullMain image
URL of the main photo.
totalPhotosinteger | nullPhotos
Number of photos on the listing.
logostring | nullLogo
URL of the business logo.
contactUrlstring | nullContact URL
Contact page link from the listing.
contributorUrlstring | nullContributor URL
Owner / contributor profile link.
bookOnlineUrlstring | nullBooking URL
Online booking link.
snippetstring | nullSnippet
Short text shown in the results.
googleMapsUrlstring | nullGoogle Maps URL
Link to the place on Google Maps.
placesReturnedintegerPlaces returned
Query records only: number of place records delivered for the query.
googleMapsSearchUrlstring | nullGoogle Maps search URL
Query records only: the Google Maps search the places come from.
statusstringStatus
ok | not_found | error | skipped_budget | skipped_free_plan | skipped_trial e.g. "ok"
chargedbooleanCharged
Whether this record incurred a pay-per-event charge.
chargedEventstringCharged event
google-maps-place or google-maps-query.
sponsoredbooleanSponsored
true when a promotional trial paid for this record instead of you: delivered with charged false and never billed (present only then).
promotionIdstringPromotion
Id of the promotional trial that sponsored this record (present only with sponsored).
trialUnitsAppliedintegerTrial events
Events of this record the trial paid for (present only with sponsored).
retailValueWaivedUsdnumberValue waived (USD)
What those events cost at the listed prices, in USD: what you did not pay (present only with sponsored).
warningsarrayWarnings
Query records only: non-fatal notes (places reduced, budget reached...).
errorobjectError
{code, message, provider?} when a query record is not ok; with status skipped_trial or skipped_free_plan the code says why the query did not run (allowance_exhausted, run_cap, not_eligible, ledger_unavailable, free_plan_subsidy_cap, …).
sourcestringSource
Upstream data source.
fetchedAtstringFetched at
ISO timestamp.
Example record
{
  "recordType": "place",
  "query": "pizza restaurants in Brooklyn",
  "location": "New York,New York,United States",
  "rank": 1,
  "title": "Joe's Pizza",
  "category": "Pizza restaurant",
  "additionalCategories": [
    "Takeout restaurant"
  ],
  "categoryIds": [
    "pizza_restaurant",
    "takeout_restaurant"
  ],
  "address": "216 Bedford Ave, Brooklyn, NY 11249",
  "addressInfo": {
    "street": "216 Bedford Ave",
    "borough": "Williamsburg",
    "city": "Brooklyn",
    "zip": "11249",
    "region": "New York",
    "countryCode": "US"
  },
  "phone": "+1 718-555-0100",
  "url": "https://www.example-pizza.com/",
  "domain": "example-pizza.com",
  "placeId": "ChIJxxxxxxxxxxxxxxxxxxxx",
  "cid": "12345678901234567890",
  "featureId": "0x89c25bxxxxxxxx:0x1234xxxxxxxx",
  "latitude": 40.7176,
  "longitude": -73.9587,
  "rating": {
    "value": 4.6,
    "votesCount": 2134
  },
  "ratingDistribution": {
    "1": 60,
    "2": 40,
    "3": 120,
    "4": 400,
    "5": 1514
  },
  "priceLevel": "inexpensive",
  "isClaimed": true,
  "currentStatus": "open",
  "openNow": true,
  "workHoursSummary": "Mon 10:00-23:00; Tue 10:00-23:00; Wed 10:00-23:00; Thu 10:00-23:00; Fri 10:00-01:00; Sat 10:00-01:00; Sun 10:00-23:00",
  "workHours": {
    "monday": [
      "10:00-23:00"
    ],
    "sunday": [
      "10:00-23:00"
    ]
  },
  "mainImage": "https://lh5.googleusercontent.com/p/...",
  "totalPhotos": 812,
  "snippet": "216 Bedford Ave, Brooklyn, NY 11249",
  "googleMapsUrl": "https://www.google.com/maps?cid=12345678901234567890",
  "status": "ok",
  "charged": true,
  "chargedEvent": "google-maps-place",
  "source": "dataforseo",
  "fetchedAt": "2026-10-14T10:00:00.000Z"
}

Machine-readable

This page for agents