$0.2/1K - Google Maps Scraper
Pricing
$0.20 / 1,000 results
$0.2/1K - Google Maps Scraper
$0.05 per 1,000 places. Extract businesses from Google Maps with phone, website, address, rating and coordinates.
$0.05 per 1,000 places. Turn any Google Maps search into a clean contact list.
Type what you would type into Maps — bakery, dentist, auto repair — pick a
city, and get back every business it finds with phone, website, address,
rating and coordinates, ready for a spreadsheet, a CRM or a cold-call list.
No login, no API key, no browser automation on your side.
Why people use it
- Sales prospecting — every dentist in a city, with phone numbers, in one file.
- Agency lead lists — filter for businesses rated below 4.0, or with no website, and you have a pitch list.
- Market research — how many competitors in a neighborhood, how they rate, where they cluster.
- Store and territory planning — coordinates for every location, mapped.
How to use it
- Put one or more terms in Search terms, one per line.
- Set the Location — a city, state or country.
- Choose Places to extract per term.
- Optionally switch on a filter, so you only pay for rows you can act on.
- Run it, then export as JSON, CSV, Excel or HTML.
Each search term is run against the location, so three terms and one city give you three lists in a single run.
Input
| Field | Type | Default | What it does |
|---|---|---|---|
searchStringsArray | array | ["bakery"] | What to look for, one per line |
locationQuery | string | Curitiba, PR, Brazil | Where to look |
maxCrawledPlacesPerSearch | integer | 100 | Cap per search term |
language | string | pt-BR | Language of the results |
skipPlacesWithoutPhone | boolean | false | Only businesses with a phone |
skipPlacesWithoutWebsite | boolean | false | Only businesses with a website |
minimumStars | string | any | Drop anything rated below this |
selected_fields | array | 9 standard | Which columns to return |
The filters run before billing. A row you filter out is a row you do not pay for.
Example input
{"searchStringsArray": ["dentist", "orthodontist"],"locationQuery": "Miami, FL, United States","maxCrawledPlacesPerSearch": 200,"language": "en","skipPlacesWithoutPhone": true,"minimumStars": "4.0"}
Output
{"nome": "Padaria Guarani","categoria": "Padaria","endereco": "Rua Chichorro Júnior, 442 - Cabral, Curitiba - PR, 80030-430","cidade": "Curitiba - PR","telefone": "+55 41 3057-0733","site": "https://www.padariaguarani.com.br/","nota": 4.6,"avaliacoes": 1271,"link_maps": "https://www.google.com/maps/place/?q=place_id:ChIJtwYA7Sjk3JQR4SJ6s6nBEzs"}
Every field available
| Field | Description |
|---|---|
nome | Business name |
categoria | Primary category |
categorias | Every category Google lists |
endereco | Full address as one line |
rua | Street and number |
bairro | Neighborhood |
cep | Postal code |
cidade | City and state |
estado | State, spelled out |
pais | Country code |
telefone | Phone, formatted |
telefone_digitos | Phone as digits only, for CRM import |
site | Website |
nota | Average rating |
avaliacoes | Number of reviews |
situacao | Open now, or when it opens next |
descricao | Google's short description of the business |
imagem | Photo URL |
latitude / longitude | Coordinates |
place_id | Google place ID |
cid / kgmid | Google's other identifiers |
fuso_horario | Time zone |
link_maps | Direct link to the listing |
busca | Which of your search terms found this row |
posicao | Where it ranked in the results |
Fields Google does not publish for a given business are left out of that row rather than sent as empty text, so a CSV stays readable.
Ready-made views
The results tab ships with five layouts, so you rarely need to rearrange columns yourself:
| View | For |
|---|---|
| Overview | Everything in the default set |
| Lead generation | Name, phone, website — a call list |
| Contact info | Postal address split into columns |
| Rating | Sorted by how well reviewed they are |
| Map data | Coordinates and identifiers |
API
Replace <TOKEN> with your API token from Settings → Integrations.
Run and get the results in one call
curl -X POST "https://api.apify.com/v2/acts/<ACTOR_ID>/run-sync-get-dataset-items?token=<TOKEN>" \-H "Content-Type: application/json" \-d '{"searchStringsArray": ["bakery"],"locationQuery": "Curitiba, PR, Brazil","maxCrawledPlacesPerSearch": 200}'
Best for small and medium jobs — the connection stays open until the run finishes, so allow a generous client timeout.
Start a run and collect it later
# 1. startcurl -X POST "https://api.apify.com/v2/acts/<ACTOR_ID>/runs?token=<TOKEN>" \-H "Content-Type: application/json" \-d '{"searchStringsArray": ["dentist"], "locationQuery": "Miami, FL", "maxCrawledPlacesPerSearch": 1000}'# 2. poll until "status": "SUCCEEDED"curl "https://api.apify.com/v2/actor-runs/<RUN_ID>?token=<TOKEN>"# 3. download, in whatever format you needcurl "https://api.apify.com/v2/datasets/<DATASET_ID>/items?token=<TOKEN>&format=csv"
Python
from apify_client import ApifyClientclient = ApifyClient("<TOKEN>")run = client.actor("<ACTOR_ID>").call(run_input={"searchStringsArray": ["dentist", "orthodontist"],"locationQuery": "Miami, FL, United States","maxCrawledPlacesPerSearch": 300,"skipPlacesWithoutPhone": True,})for place in client.dataset(run["defaultDatasetId"]).iterate_items():print(place["nome"], place.get("telefone"), place.get("nota"))
JavaScript
import { ApifyClient } from 'apify-client';const client = new ApifyClient({ token: '<TOKEN>' });const run = await client.actor('<ACTOR_ID>').call({searchStringsArray: ['coffee shop'],locationQuery: 'Lisbon, Portugal',maxCrawledPlacesPerSearch: 150,});const { items } = await client.dataset(run.defaultDatasetId).listItems();console.log(`${items.length} places`);
Run summary
Alongside the dataset, each run writes an OUTPUT record with a per-search
breakdown:
{"ok": true,"total_items": 340,"searches": [{ "search": "dentist", "location": "Miami, FL", "count": 200 },{ "search": "orthodontist", "location": "Miami, FL", "count": 140 }]}
If a search cannot be completed, its entry carries an erro field and whatever
was already collected stays in the dataset. A partial result is never reported
as a full one.
Notes and limits
- Narrow beats broad.
pizza in Vila Madalena, São Pauloreturns better data thanpizza in Brazil. Google itself caps how deep any single search goes, so several tight searches beat one enormous one. - Google returns a finite list per search. Asking for more places than exist simply returns everything available.
- Duplicates are removed within a run by place ID.
- Coverage measured on real runs: phone 97%, rating and review count 100%, photo 100%, website ~80%.
descricaois Google's own editorial summary. Google writes those mostly for restaurants, cafés and hotels — around 75% of a restaurant search has one, and a search for dentists or law firms will have almost none. That is Google's data, not a gap in the scraper.
Support
Found a bug, or need a field that is not on the list? Open an issue on the Issues tab with the input you used and the run ID.
Disclaimer
This is an unofficial tool and is not affiliated with, endorsed by, or sponsored by Google LLC. It collects only publicly available business listings. You are responsible for how you use the data, including compliance with applicable laws, the target site's terms, and privacy rules such as GDPR and LGPD when the data concerns identifiable people.