Google Maps Scraper — Places, Emails, Phones & Reviews
Pricing
from $1.70 / 1,000 results
Google Maps Scraper — Places, Emails, Phones & Reviews
Google Maps scraper: export businesses from any city, state or country with phone, website, address, rating, reviews, categories, opening hours, coordinates and plus code, plus e-mails and social profiles from their websites. No 120-result limit, no login. Not affiliated with Google.
Pricing
from $1.70 / 1,000 results
Rating
0.0
(0)
Developer
Logiover
Maintained by CommunityActor stats
0
Bookmarked
2
Total users
1
Monthly active users
6 days ago
Last modified
Categories
Share
Google Maps Scraper
Export every business Google Maps knows in a city, a state or a whole country — name, address, phone, website, rating, reviews, opening hours, coordinates — with e-mails and social profiles from each business's own website included.
Google Maps Scraper is a Google Maps data extractor that turns any Google Maps search into a clean spreadsheet: type what you are looking for ("dentist", "plumber", "restaurant", "coffee shop", "car dealer") and where ("Austin, TX", "Texas", "Berlin", "Netherlands"), and the Actor scrapes Google Maps for every matching place — not just the first 120 results a single Google Maps search shows. Each place comes with its Google place ID, CID, address split into street / city / postal code / state / country, latitude and longitude, plus code, phone number in local and international (E.164) format, website and domain, star rating and number of reviews, categories, opening hours for the whole week, photo, booking and reservation links, and a "claimed by owner" flag. It works as a Google Maps API alternative and Google Places API alternative with no API key, no login, no cookies and no browser on your side, and you can export Google Maps to CSV, Excel, JSON, HTML or XML, or pull the data straight into your CRM, Google Sheets or database.
For Google Maps lead generation, the Actor also works as a Google Maps email extractor: for every place with a website it reads the homepage (and one contact or imprint page when needed) and adds the e-mail addresses, extra phone numbers and Facebook, Instagram, LinkedIn, X (Twitter), YouTube, TikTok and Pinterest profiles it finds — included in the price, no add-on fees. Big areas are split automatically into a grid of map views that is refined wherever Google's answer is full, so you can scrape Google Maps for a whole state (20,000 Texas restaurants in 129 seconds, measured) and still get places from the quietest suburb. Use it to extract phone numbers and websites from Google Maps, build local B2B lead lists, audit local SEO, map competitors, plan franchise expansion, enrich a CRM with place IDs, or feed structured place data to an AI agent.
All numbers on this page were measured on the Apify platform on 2026-10-18 (see How much data can I get).
Table of contents
- At a glance
- What you get
- Who uses this Google Maps scraper
- Cookbook: 18 ready-to-run inputs
- Tutorial: scrape Google Maps in the Apify Console
- Tutorial: scrape Google Maps with the API
- Input reference
- Output data dictionary
- Real output sample
- How the area splitting works
- How much data can I get from Google Maps
- E-mails and social profiles: the contact enrichment
- What you pay
- Integrations
- Performance tips
- Troubleshooting: every status message explained
- Honest limits
- Comparison: Places API, manual copying, this Actor
- FAQ
- Glossary
- Is it legal to scrape Google Maps?
- Changelog
- Support
At a glance
| What you type | Search terms ("dentist", "restaurant", "plumber") × locations (city, district, postal code, state, region, country) — or a center point + radius, a bounding box, Google Maps links, place IDs / CIDs |
| What you get | One row per place: place ID, CID, name, categories, description, full address + street / city / postal code / state / country, lat/lng, plus code, time zone, phone (local + E.164), website, domain, rating, reviews count, reviews link, opening hours (7 days), permanently-closed flag, claimed flag, hotel stars, main photo + photo count, reservation / appointment / order-online links, accessibility attributes |
| Contacts (included) | E-mails, extra phones and Facebook / Instagram / LinkedIn / X / YouTube / TikTok / Pinterest from each business's own website — on by default |
| Scale | No 120-result cap: areas are split into map views until each view is complete. Measured: 20,000 Texas restaurants in one run (0 duplicates); 89,013 restaurants = all of Texas in one run |
| Speed | First rows after ~4 s; 1,000 places with e-mails in 39–44 s; 20,000 places (Google data only) in 129 s |
| Quality | Every field checked by hand against the live Google Maps page and a second Google request on 26 places in 7 countries; ads skipped; de-duplicated by place ID |
| Formats | JSON, CSV, Excel, XML, HTML table, RSS; API, webhooks, Make, Zapier, n8n, Google Sheets |
| Price | Pay per place: $2.50 per 1,000 on the Free plan, down to $1.70 per 1,000 — compute, proxies and the website visits for e-mails included |
| Needs | Nothing: no Google account, no API key, no proxy setup |
What you get: the Google Maps data fields
Every place is one flat row. Fields Google has no value for are null (never an empty string, never a guessed 0). The full dictionary with types and measured fill rates is further down; this is the overview with real example values.
Identity and links
| Field | Example | |
|---|---|---|
placeId | ChIJ3aKC18JZwokRV_edM73h9UI | Google place ID — the key the Google Places API, Google Ads and most tools use |
cid | 4825010778528413527 | Customer ID — the number in maps.google.com/?cid=…; a stable link to the listing |
fid | 0x89c259c2d782a2dd:0x42f5e1bd339df757 | Feature ID — Google's internal id (the CID is its second half in decimal) |
kgmid | /g/11tbbv9zl7 | Knowledge Graph id of the business |
url | https://www.google.com/maps/search/?api=1&query=Mitr%20Thai%20Restaurant&query_place_id=ChIJ3aKC18JZwokRV_edM73h9UI | Opens the place on Google Maps (official Maps URL format) |
cidUrl | https://maps.google.com/?cid=… | Short permanent link to the listing |
Business
| Field | Example |
|---|---|
name | Mitr Thai Restaurant |
category | Thai restaurant (Google's primary category) |
categories | ["Thai restaurant"], ["Plumber", "Water heater installation service"] |
description | Enormous steaks & signature mutton chops served in a maze of clubby, wood-paneled rooms. (Google's editorial summary, when it has one) |
claimed | true = the business has claimed its profile; false = Google shows "Claim this business" |
permanentlyClosed | false (closed businesses are skipped unless you turn that off) |
hotelStars | 3 (hotels only) |
attributes | ["Accessibility: Wheelchair accessible entrance", "Accessibility: No wheelchair accessible parking lot"] |
Address and location
| Field | Example |
|---|---|
address | 37 W 46th St, New York, NY 10036 |
street | 37 W 46th St |
neighborhood | Manhattan (or the shopping center / building the place is in) |
city | New York |
postalCode | 10036 |
state | New York |
countryCode | US |
lat, lng | 40.7568769, -73.9804147 |
plusCode | 87G8Q227+8C (full Open Location Code — works without an address) |
timeZone | America/New_York |
Contact (from Google Maps)
| Field | Example |
|---|---|
phone | (212) 466-6699 — as Google shows it in the country |
phoneE164 | +12124666699 — international format for dialers and CRMs |
website | http://mitrthainyc.com/ |
domain | mitrthainyc.com |
Reviews and reputation
| Field | Example |
|---|---|
rating | 4.9 |
reviewsCount | 10622 |
reviewsUrl | https://search.google.com/local/reviews?placeid=… |
Opening hours, photos, bookings
| Field | Example |
|---|---|
openingHours | [{"day":"Monday","hours":"11:30 AM–3:45 PM, 5–10:15 PM"}, … 7 days] |
imageUrl | Main photo, 1024 × 768 (https://lh3.googleusercontent.com/…=w1024-h768-k-no) |
photosCount | 8236 |
reservationUrl | https://resy.com/cities/new-york-ny/venues/mitr-thai… |
appointmentUrl | https://book.housecallpro.com/book/… (service businesses) |
orderOnlineUrl | https://www.doordash.com/store/… |
Contacts from the business's website (enrichment, on by default)
| Field | Example |
|---|---|
email | info@nw1dentalcare.co.uk (best address: the business's own domain first) |
emails | ["praxis-oranien@meindentist.de", "praxis-franzehrlich@meindentist.de"] |
websitePhones | ["02074854626"] — numbers on the website that differ from the Google Maps phone |
facebook, instagram, linkedin, twitter, youtube, tiktok, pinterest | https://www.linkedin.com/company/nw1-dental-care |
contactPageUrl | http://www.victoriadental.biz/contactingus.php (when the e-mail came from a contact page) |
contactsStatus | ok, no website, no contacts found on website, website not readable (HTTP 403) |
Search context
| Field | Example |
|---|---|
searchTerm | dentist |
searchLocation | Berlin, Germany |
rank | 7 — position in Google's own answer for the whole city view (city-sized searches) |
scrapedAt | 2026-10-18T20:19:51.006Z |
Who uses this Google Maps scraper
Google Maps is the largest directory of local businesses in the world, kept current by the businesses themselves and by millions of reviewers. These are the teams that turn it into data, and the workflow each one runs.
1. Web design and digital marketing agencies — "no website" leads
Search your service area for trades and shops ("restaurant", "hair salon", "roofing contractor") with Website → Only places without a website. You get businesses that are open, reviewed and reachable by phone but have no site: the warmest possible list for a website or Google Business Profile offer. Sort by reviewsCount to call the busiest ones first.
2. B2B sales teams and SDRs — local prospect lists with e-mails
Pick the verticals you sell to ("dentist", "veterinarian", "law firm", "car dealer") and the territories you cover. Keep contact enrichment on: each row carries the Google Maps phone, the website, the e-mail found on the website and the company's LinkedIn page. Import the CSV into your CRM or sequencing tool and use placeId as the external id so the next refresh updates instead of duplicating.
3. Local SEO consultants — audits and rank tracking
For a keyword like "emergency plumber" in a city, rank is the position of each business in Google's own answer for the whole city view, next to its rating, review count, categories and claimed status. Find unclaimed listings (claimed: false), missing hours, missing websites and weak categories — then pitch the fix. Re-run monthly to track movement.
4. Franchise development and retail expansion — white-space maps
Scrape every competitor location in a state ("pizza", "gym", "car wash") with coordinates and ratings, then plot lat / lng against population data to see under-served towns. Area splitting matters here: a state-wide search returns every location, not the 120 most prominent.
5. Commercial real estate brokers and landlords — tenant prospecting
List every tenant type that fits a vacant unit within a radius (lat, lng, radiusKm), with the parent brand recoverable from the name and the shopping center from neighborhood. Call the businesses that are growing (high review velocity) and pitch the space.
6. Recruiters and staffing agencies — employers by location
Build lists of employers that hire the roles you place ("hospital", "warehouse", "restaurant", "dental clinic") in a metro area, with phone, website and LinkedIn page for the decision-maker search.
7. Investors, private equity and M&A analysts — market maps
Count and rate every business in a fragmented service industry (HVAC, dental, veterinary, car wash, landscaping) across a region before a roll-up. reviewsCount approximates customer volume; claimed, website and photosCount show how professionalised each target is.
8. Market researchers and consultants — density and saturation studies
Compare categories across cities or countries in one run (several search terms × several locations). The SUMMARY record reports, per search, how many map views were needed and how many places were found, so coverage is auditable.
9. Data teams and data vendors — refreshable place databases
Keep a place table keyed by placeId / cid. Re-run on a schedule, upsert by key, and flag rows whose permanentlyClosed, phone, website or hours changed. Look up known places directly with Place IDs / CIDs to refresh them without searching again.
10. AI and RAG builders — grounded local knowledge
Feed structured places (name, categories, description, hours, address, rating) into a vector store so an assistant can answer "which vegan restaurants near the office are open after 10 pm?" from real data. Through the Apify MCP server, an agent can call the scraper as a tool.
11. Travel and hospitality platforms — POI catalogues
Collect hotels (with hotelStars), restaurants, museums and attractions for a destination, with coordinates, photos, opening hours and reservation links (reservationUrl) to build or update a points-of-interest catalogue.
12. Delivery, logistics and field-service companies — territory planning
Get every restaurant, pharmacy or retailer in a delivery zone with exact coordinates and plus codes (which work even where street addresses are poor) to plan routes, onboard merchants and size territories.
13. Manufacturers and distributors — finding resellers and installers
Search for the trades that install or resell your product ("solar installer", "tile store", "bike shop") across all the states you serve, then segment by rating and review count to recruit the best dealers.
14. Insurance, lending and fintech — merchant verification and leads
Check that a business exists at the address it claims, how long it has been reviewed, and whether it is still open; build merchant lead lists for card terminals, loans or insurance by category and area.
15. Public sector, NGOs and academics — service accessibility research
Measure how far residents are from pharmacies, clinics, grocery stores or childcare, with attributes such as wheelchair-accessible entrances, in any country Google covers.
16. Event organisers and sponsorship sellers — local partners
Find venues, caterers, florists and photographers around an event location with phone, e-mail and Instagram, ready for outreach.
17. Reputation management agencies — prospects with low ratings
Filter a vertical to places with many reviews but a rating under 4.0 (filter the dataset after the run) — businesses that need review management — and contact them by phone or e-mail.
18. App and directory builders — seeding a niche directory
Seed a vertical directory (vegan restaurants, EV-friendly hotels, pet-friendly cafés) with real places, photos, hours and links, then let owners claim and update their listings.
Cookbook: 18 ready-to-run inputs
Paste any of these into the JSON tab of the input form (or send them to the API). Every input here was run on the platform while this page was written; the result described is what came back.
1. One category in one city (the classic)
{"searchTerms": ["dentist"],"locations": ["Los Angeles, CA"],"maxItems": 1000}
Returns: 1,000 dentists inside the Los Angeles city boundary with phones, websites, hours and — contact enrichment is on by default — e-mails and social profiles. Measured: 43.9 s, 0 duplicates, 28 map views.
2. Every place of one kind in a city (no limit)
{"searchTerms": ["plumber"],"locations": ["Austin, TX"],"maxItems": 0}
Returns: every place Google Maps answers for "plumber" inside Austin's city boundary — 368 places from 28 map views in 27.6 s, e-mails included (151 of the 300 websites had one). maxItems: 0 means "everything".
3. A whole state
{"searchTerms": ["restaurant"],"locations": ["Texas"],"maxItems": 0,"scrapeContacts": false}
Returns: every restaurant in Texas Google Maps returns for the search — 89,013 places in 2,345 s (39 min) (measured). Turn scrapeContacts on to add e-mails; it takes longer because every website is visited.
4. A whole country
{"searchTerms": ["dentist"],"locations": ["Netherlands"],"maxItems": 0,"language": "en"}
Returns: dentists across the Netherlands, the country boundary from OpenStreetMap, split into map views automatically. Measured: 8,681 dentists in 510 s (742 map views, up to 12 split levels), 4,812 of the 6,533 websites (74 %) with an e-mail. The boundary is OpenStreetMap's: "Netherlands" includes the Caribbean parts of the Kingdom, so 110 of those places are on Aruba, Curaçao, Sint Maarten and the Caribbean Netherlands — filter countryCode if you only want NL.
5. Several categories in several cities in one run
{"searchTerms": ["dentist", "orthodontist", "dental clinic"],"locations": ["Berlin, Germany", "London, UK", "Istanbul, Turkey"],"maxItems": 3000,"maxItemsPerSearch": 200}
Returns: 200 places for each of the 9 combinations — 1,800 places in 102 s; a place found by two terms is saved once (de-duplicated by place ID), under the first term that found it. 1,087 of the 1,575 websites (69 %) gave an e-mail.
6. A circle around a point (lat / lng + radius)
{"searchTerms": ["coffee shop"],"lat": "47.6062","lng": "-122.3321","radiusKm": 3,"maxItems": 500}
Returns: every coffee shop within 3 km of downtown Seattle — 328 places from 21 map views in 26 s; places outside the circle are dropped.
7. A bounding box
{"searchTerms": ["pharmacy"],"boundingBox": "48.85,2.33,48.87,2.36","language": "fr","maxItems": 0}
Returns: every pharmacy in that rectangle of central Paris — 45 in 11 s — with categories and opening hours in French ("lundi", "09:45–19:00", "Fermé").
8. A Google Maps search link you already have
{"startUrls": [{ "url": "https://www.google.com/maps/search/car+repair/@-33.8688,151.2093,13z" }],"maxItems": 500}
Returns: car repair shops in the map area that link shows (Sydney at zoom 13) — 500 in 20 s (12 map views), with Australian phone and address formats.
9. Look up places you already know (place IDs, CIDs, links)
{"placeIds": ["ChIJ5804KalZwokRzGll2Rm7nag", "12150073089411344844", "0x8644cbf98cf77c3b:0xd9fd1d041b132575"],"startUrls": [{ "url": "https://www.google.com/maps/place/Mitr+Thai+Restaurant/@40.7568769,-73.9804147,17z/data=!4m6!3m5!1s0x89c259c2d782a2dd:0x42f5e1bd339df757" },{ "url": "https://maps.google.com/?cid=6706319325865468614" }],"scrapeContacts": false}
Returns: one fresh row per place — 4 rows in 1.6 s (the ChIJ id and the CID above are the same restaurant, so it is saved once). Use it to refresh a list on a schedule.
10. Businesses without a website (web-design leads)
{"searchTerms": ["hair salon", "nail salon", "barber shop"],"locations": ["Phoenix, AZ"],"website": "withoutWebsite","minReviews": 10,"maxItems": 2000}
Returns: 506 salons and barbers with at least 10 reviews and no website, in 97 s (the SUMMARY shows 1,113 places dropped for having a website and 896 for fewer reviews).
11. Only well-rated businesses
{"searchTerms": ["plumber"],"locations": ["Austin, TX"],"minRating": "4.5","minReviews": 20,"maxItems": 0}
Returns: 171 places rated 4.5+ with at least 20 reviews, in 25 s. The SUMMARY record tells you how many places each filter removed (111 by rating, 85 by reviews).
12. Only the exact category (drop Google's neighbours)
{"searchTerms": ["plumber"],"locations": ["Denver, CO"],"categoryFilter": ["plumber"],"maxItems": 0}
Returns: 230 places in 23 s, every one with "plumber" among its categories — Google also mixes handymen, roofers, HVAC companies and supply stores into a plumber search (21 such places were dropped here).
13. Google Maps data only, as fast as possible
{"searchTerms": ["restaurant"],"locations": ["Texas"],"maxItems": 20000,"scrapeContacts": false}
Returns: 20,000 Texas restaurants in 129 s (measured), all Google Maps fields, no website visits.
14. Local language and country
{"searchTerms": ["Zahnarzt"],"locations": ["München"],"language": "de","countryCode": "de","maxItems": 500}
Returns: 500 dentists in Munich in 23 s, with German categories ("Zahnarzt", "Zahnästhetische Praxis", "Endodontologe") and hours ("Montag", "09:00–18:00"). 373 of the 452 websites (83 %) gave an e-mail — German sites carry an Impressum. Search terms work in any language; leaving countryCode empty uses the country of the location automatically.
15. Hotels with star class
{"searchTerms": ["hotel"],"locations": ["Shinjuku, Tokyo, Japan"],"maxItems": 300}
Returns: 300 hotels in 22 s; 178 of them with hotelStars (1–5), photos and photo counts, phones in local and E.164 format (03-3360-1533 / +81333601533).
16. Monitor new businesses every week
Save an input like this as a Task, schedule it weekly, and add a webhook (or a Make / Zapier / n8n scenario) that compares placeId against your table: new IDs are new businesses, permanentlyClosed: true (with skipClosed: false) marks closures. Measured on this input: 9,040 places in 305 s, 184 of them marked permanently closed, 1,432 unclaimed.
{"searchTerms": ["restaurant", "cafe", "bar"],"locations": ["Brooklyn, NY"],"maxItems": 0,"skipClosed": false,"scrapeContacts": false}
17. Rank tracking for one keyword in one city
{"searchTerms": ["emergency plumber"],"locations": ["Chicago, IL"],"maxItems": 200,"scrapeContacts": false}
Returns: the first 200 places in Google's own order for the whole city view (9.2 s), each with rank — the order a user sees when searching that keyword over the city.
18. Free-text search without a location
{"searchTerms": ["pizza near Times Square"],"maxItems": 100}
Returns: 100 places in 8.4 s for a query that already contains the place (Google decides the area; at most ~200). For complete coverage, put the place in locations instead so the area can be split.
Tutorial: scrape Google Maps in the Apify Console
No code needed. A free Apify account is enough to try it.
- Open the Actor and click Try for free (or Start if you are signed in). The input form opens with an example already filled in:
restaurantinNew York, NY, 50 places. - Search terms — type what you would type into Google Maps, one per line:
dentist,dental clinic,orthodontist. Use the words people use in the country you search (Zahnarztfor Germany works too). - Locations — one per line: a city (
Austin, TX), a district (Kreuzberg, Berlin), a postal code with country (10001, USA), a state (Texas) or a country (Netherlands). Each search term is combined with each location. The boundary comes from OpenStreetMap; the log shows which place was understood and its size in km². - Max places — how many unique places you want in total.
0means every place Google Maps has for your searches. Start with a few hundred to see the data. - Add e-mails & social profiles from websites — leave it on for lead lists; turn it off when you only need Google Maps data and want maximum speed.
- Optional filters: Minimum rating, Minimum number of reviews, Website (only with / only without), Skip permanently closed places, Category must contain.
- Click Start. Rows appear in the Output tab within seconds; the status line shows
Saved 1,234/5,000 places · 87 map requests · 41 swhile it runs. - When the run finishes, the status says why it stopped (
max results reached,every matching place read, or the cost limit). Click Export to download CSV, Excel, JSON, XML or HTML, or open the dataset in the API. - To repeat the search regularly, click Save as task, then Schedule it (daily, weekly, monthly) and optionally connect an integration (Google Sheets, Slack, webhook).
Tip: the Output tab has an Overview view (name, category, address, phone, website, e-mail, rating, reviews, link). All fields are in the full JSON / CSV export.
Tutorial: scrape Google Maps with the API
Every run can be started and read over the Apify API with your API token (Console → Settings → Integrations).
1. Run and get the results in one call (best for up to a few thousand places, the call waits up to 5 minutes):
curl -X POST "https://api.apify.com/v2/acts/logiover~google-maps-scraper/run-sync-get-dataset-items?token=YOUR_TOKEN&format=json" \-H "Content-Type: application/json" \-d '{"searchTerms":["dentist"],"locations":["Austin, TX"],"maxItems":200}'
2. Start a big run asynchronously, then fetch the dataset:
# startcurl -X POST "https://api.apify.com/v2/acts/logiover~google-maps-scraper/runs?token=YOUR_TOKEN" \-H "Content-Type: application/json" \-d '{"searchTerms":["restaurant"],"locations":["Texas"],"maxItems":0,"scrapeContacts":false}'# poll: GET https://api.apify.com/v2/actor-runs/RUN_ID?token=YOUR_TOKEN (status READY → RUNNING → SUCCEEDED)# download as CSVcurl "https://api.apify.com/v2/datasets/DATASET_ID/items?format=csv&clean=true&token=YOUR_TOKEN" -o places.csv
Add &fields=name,phone,website,email,rating,reviewsCount,address to download only the columns you need, or &format=xlsx for Excel.
3. Node.js (apify-client):
import { ApifyClient } from 'apify-client';const client = new ApifyClient({ token: process.env.APIFY_TOKEN });const run = await client.actor('logiover/google-maps-scraper').call({searchTerms: ['plumber'],locations: ['Denver, CO'],maxItems: 0,categoryFilter: ['plumber'],});const { items } = await client.dataset(run.defaultDatasetId).listItems();for (const p of items) console.log(p.name, p.phoneE164, p.website, p.email, p.rating, p.reviewsCount);
4. Python (apify-client):
from apify_client import ApifyClientclient = ApifyClient("YOUR_TOKEN")run = client.actor("logiover/google-maps-scraper").call(run_input={"searchTerms": ["dentist"],"locations": ["Berlin, Germany", "Hamburg, Germany"],"maxItems": 2000,"language": "de",})for place in client.dataset(run["defaultDatasetId"]).iterate_items():print(place["name"], place["phone"], place["email"], place["city"], place["rating"])
5. Read the run summary. Every run writes a SUMMARY record to its key-value store (GET /v2/key-value-stores/STORE_ID/records/SUMMARY) with the outcome, how many places were saved per search, how many map views were read, duplicates and out-of-area places skipped, filter counts and the contact-enrichment totals.
Input reference
| Field | Type | Default | Example | What it does and tips |
|---|---|---|---|---|
searchTerms | array of strings | [] (form example: restaurant) | ["dentist", "orthodontist"] | What to look for, as typed into Google Maps. Each term is searched in every location. Put the place in locations, not in the term, so the area can be split. |
locations | array of strings | [] (form example: New York, NY) | ["Austin, TX", "Texas", "Netherlands"] | City, district, postal code, state, region or country. Geocoded with OpenStreetMap (boundary polygon); if OpenStreetMap does not know the text, Google's own map view for it is used as a rectangle. |
maxItems | integer | 1000 (form example: 50) | 0, 500, 20000 | Total unique places to save across all searches. 0 = no limit. The run also respects your Maximum cost per run. |
scrapeContacts | boolean | true | false | Visit each place's website for e-mails, extra phones and social profiles. Off = Google Maps data only, fastest. |
language | string (select) | en | de, fr, es, tr, ja | Language of categories, hours and descriptions (Google's hl). Names and addresses stay as the business wrote them. |
minRating | string (select) | any | "4", "4.5" | Keep places rated at least this. Places without a rating are dropped when set. |
minReviews | integer | empty | 20 | Keep places with at least this many reviews. |
website | string (select) | any | withWebsite, withoutWebsite | Only places with / without a website. |
skipClosed | boolean | true | false | Skip places Google marks as permanently closed. Turn off to track closures. |
categoryFilter | array of strings | [] | ["plumber"] | Keep only places whose categories contain one of the words (case-insensitive, in the chosen language). |
maxItemsPerSearch | integer | 0 | 200 | Cap per search term × location, so one big city does not use up the whole maxItems. |
lat, lng | string (decimal degrees) | empty | "30.2672", "-97.7431" | Center of a circle to search instead of (or in addition to) named locations. |
radiusKm | integer | 5 when lat/lng are set | 3, 50 | Radius of the circle, 1–500 km. |
boundingBox | string | empty | "30.10,-97.95,30.52,-97.55" | Rectangle south,west,north,east to search. |
startUrls | array of URLs | [] | Maps search or place links | /maps/search/<term>/@lat,lng,zoomz links are searched over the visible map area (and split); /maps/place/…, ?cid= and place_id: links are looked up directly. |
placeIds | array of strings | [] | ["ChIJ5804KalZwokRzGll2Rm7nag", "12150073089411344844"] | Look up known places by place ID (ChIJ…), CID (digits) or feature ID (0x…:0x…). |
countryCode | string | empty (automatic) | "us", "de", "gb" | Google's country (gl). Empty = the country of each location. |
proxyConfiguration | object | Apify Proxy | — | Fallback only. Requests go out directly first; if Google slows them down or shows a captcha, the Actor switches to Apify datacenter proxies (a new IP per request), then to the proxy chosen here. |
Notes:
- Search terms × locations: 3 terms × 4 locations = 12 searches, run side by side and de-duplicated across each other.
- Without search terms, only
startUrls/placeIdsare processed. - Unknown or misspelled locations are reported in the log and run as a plain-text search (
"term in location", up to ~200 places) instead of silently searching somewhere else.
Output data dictionary (with measured fill rates)
One row per place, the same columns in every row (contact columns only when contact enrichment is on). Fill rate = share of rows with a value, measured on two platform runs on 2026-10-18: CA = 10,000 dentists in California with contact enrichment on; TX = every restaurant in Texas (89,013 places), Google Maps data only. Values are null when Google (or the website) has none — never an empty string or an invented 0.
| Field | Type | Meaning | Fill CA | Fill TX | Example |
|---|---|---|---|---|---|
placeId | string | Google place ID; unique per row | 100 % | 100 % | ChIJE_59cZy7woARjv6rHhpqFbw |
cid | string (digits) | Customer ID, as in maps.google.com/?cid= | 100 % | 100 % | 13552855314057657998 |
fid | string | Feature ID 0x…:0x… | 100 % | 100 % | 0x80c2bb9c717dfe13:0xbc156a1a1eabfe8e |
kgmid | string | Knowledge Graph id | 100 % | 100 % | /g/1vyxjpb7 |
name | string | Business name as listed | 100 % | 100 % | Dr. Joyce Family and Cosmetic Dentistry |
url | string (URL) | Opens the place on Google Maps (official Maps URL with query_place_id) | 100 % | 100 % | https://www.google.com/maps/search/?api=1&query=…&query_place_id=ChIJ… |
cidUrl | string (URL) | Short permanent link | 100 % | 100 % | https://maps.google.com/?cid=13552855314057657998 |
category | string | Primary Google category (in language) | 99.9 % | 100 % | Dentist |
categories | array of strings | All Google categories, primary first | 99.9 % | 100 % | ["Dentist", "Cosmetic dentist", "Dental implants periodontist"] |
description | string | Google's editorial summary of the place | 0 % (dentists) | 40.8 % | Tiny BYOB eatery serving Italian fare in a quaint setup with a patio… |
address | string | Full address as Google formats it | 99.8 % | 100 % | 1964 Westwood Blvd #215, Los Angeles, CA 90025 |
street | string | Street and number | 99.0 % | 99 % | 1964 Westwood Blvd #215 |
neighborhood | string | Neighborhood, or the mall / building the place is in | 27.2 % | 42 % | West Los Angeles |
city | string | City / locality | 99.7 % | 99.9 % | Los Angeles |
postalCode | string | Postal / ZIP code | 99.2 % | 99.5 % | 90025 |
state | string | State / region (empty where Google gives none, e.g. Berlin) | 99.8 % | 100 % | California |
countryCode | string | ISO 3166-1 alpha-2 | 99.8 % | 100 % | US |
lat | number | Latitude (WGS 84) | 100 % | 100 % | 34.0474398 |
lng | number | Longitude (WGS 84) | 100 % | 100 % | -118.4344449 |
plusCode | string | Full plus code (Open Location Code) | 100 % | 100 % | 85632HW8+X6 |
timeZone | string | IANA time zone | 100 % | 100 % | America/Los_Angeles |
phone | string | Phone as displayed on Google Maps in that country | 97.5 % | 92.1 % | (310) 470-7200 |
phoneE164 | string | Same phone in E.164 | 97.5 % | 92.1 %E164 | +13104707200 |
website | string (URL) | Website as listed (Google redirect wrappers removed) | 74.5 % | 74.9 % | http://www.drjoycedentistry.com/?utm_campaign=gbp |
domain | string | Website domain | 74.5 % | 74.9 % | drjoycedentistry.com |
rating | number | Average star rating, 1–5 | 86.7 % | 94 % | 4.8 |
reviewsCount | integer | Number of Google reviews | 86.7 % | 94 % | 207 |
reviewsUrl | string (URL) | Google's reviews page for the place | 82.0 % | 86.9 % | https://search.google.com/local/reviews?placeid=… |
openingHours | array of {day, hours} | Regular hours Monday→Sunday | 80.1 % | 89.4 % | [{"day":"Monday","hours":"8 AM–5 PM"}, …] |
permanentlyClosed | boolean | Google marks the place permanently closed | 100 % | 100 % | false |
claimed | boolean | Business profile claimed by the owner (false = "Claim this business") | 100 % | 100 % | true |
hotelStars | integer | Hotel star class (hotels only) | — | — | 3 |
imageUrl | string (URL) | Main photo, 1024 × 768 | 69.7 % | 94.1 % | https://lh3.googleusercontent.com/…=w1024-h768-k-no |
photosCount | integer | Number of photos on the listing | 68.8 % | 93.8 % | 7 |
reservationUrl | string (URL) | Table reservation link (OpenTable, Resy, own site …) | — | 6.2 % | https://www.opentable.com/restaurant/profile/… |
orderOnlineUrl | string (URL) | Online ordering link of a provider (when not Google's own) | — | 0.4 % | https://www.doordash.com/store/… |
appointmentUrl | string (URL) | Online booking for appointments | 25.2 % | 0.2 % | https://scheduling.simplifeye.co/#key=… |
attributes | array of strings | Google attributes (mostly accessibility) | 98.0 % | 93.1 % | ["Accessibility: Wheelchair accessible entrance"] |
email | string | Best e-mail from the website (own domain first) | 27.3 % | off | info@drjoycedentistry.com |
emails | array of strings | All validated e-mails found (≤ 10) | 27.3 % | off | ["info@drjoycedentistry.com"] |
websitePhones | array of strings | tel: numbers on the website other than the Google phone | 18.1 % | off | ["9494937004"] |
facebook | string (URL) | Facebook page | 30.7 % | off | https://www.facebook.com/people/Dr-Joyce-… |
instagram | string (URL) | Instagram account | 15.6 % | off | https://instagram.com/drjoycedentistry |
linkedin | string (URL) | LinkedIn company / person page | 3.6 % | off | https://www.linkedin.com/company/… |
twitter | string (URL) | X (Twitter) account | 6.7 % | off | https://twitter.com/… |
youtube | string (URL) | YouTube channel | 6.3 % | off | https://www.youtube.com/@… |
tiktok | string (URL) | TikTok account | 1.0 % | off | https://www.tiktok.com/@… |
pinterest | string (URL) | Pinterest profile | 1.1 % | off | https://www.pinterest.com/… |
contactPageUrl | string (URL) | Contact page read when the homepage had no e-mail | 31.4 % | off | https://…/contact-us/ |
contactsStatus | string | Result of the website visit | 100 % | off | ok / no website / no contacts found on website / website not readable (HTTP 403) |
searchTerm | string | Search term (or lookup: …) that found the place | 100 % | 100 % | dentist |
searchLocation | string | Location as you typed it | 100 % | 100 % | California |
rank | integer | Position in Google's answer for the whole-area view (city-sized searches and plain-text searches) | first view only | — | 7 |
scrapedAt | string (ISO 8601) | Run start time | 100 % | 100 % | 2026-10-18T20:24:07.321Z |
How to read the rates: contact fields are shares of all places (27.3 % of all California dentists got an e-mail = 36.7 % of those with a website). description exists mostly for restaurants, shops and attractions; reservationUrl / orderOnlineUrl mostly for restaurants; appointmentUrl mostly for clinics, salons and trades; hotelStars only for hotels.
CSV / Excel columns (in this order): placeId, cid, fid, kgmid, name, url, cidUrl, category, categories/0…n, description, address, street, neighborhood, city, postalCode, state, countryCode, lat, lng, plusCode, timeZone, phone, phoneE164, website, domain, rating, reviewsCount, reviewsUrl, openingHours/0/day, openingHours/0/hours … openingHours/6/hours, permanentlyClosed, claimed, hotelStars, imageUrl, photosCount, reservationUrl, orderOnlineUrl, appointmentUrl, attributes/0…n, email, emails/0…n, websitePhones/0…n, facebook, instagram, linkedin, twitter, youtube, tiktok, pinterest, contactPageUrl, contactsStatus, searchTerm, searchLocation, rank, scrapedAt.
Real output sample
Two rows exactly as saved by platform runs on 2026-10-18 (the first from the California dentists run with contact enrichment, the second from the Texas restaurants run without it; the long photo URL is shortened):
{"placeId": "ChIJAw8o2mC7woARKllG2KnzFaI","cid": "11679509119458761002","fid": "0x80c2bb60da280f03:0xa215f3a9d846592a","kgmid": "/g/1tlz_fxg","name": "Derrick L. Thompson DDS","url": "https://www.google.com/maps/search/?api=1&query=Derrick%20L.%20Thompson%20DDS&query_place_id=ChIJAw8o2mC7woARKllG2KnzFaI","cidUrl": "https://maps.google.com/?cid=11679509119458761002","category": "Dentist","categories": ["Dentist","Cosmetic dentist","Dental hygienist","Dental implants periodontist"],"description": null,"address": "6221 Wilshire Blvd, Los Angeles, CA 90048","street": "6221 Wilshire Blvd","neighborhood": "Beverly Grove","city": "Los Angeles","postalCode": "90048","state": "California","countryCode": "US","lat": 34.0635566,"lng": -118.363861,"plusCode": "85633J7P+CF","timeZone": "America/Los_Angeles","phone": "(310) 479-4432","phoneE164": "+13104794432","website": "https://dthompsondds.com/","domain": "dthompsondds.com","rating": 5,"reviewsCount": 466,"reviewsUrl": "https://search.google.com/local/reviews?placeid=ChIJAw8o2mC7woARKllG2KnzFaI&q=dentist&authuser=0&hl=en&gl=US","openingHours": [{"day": "Monday","hours": "9 AM–5 PM"},{"day": "Tuesday","hours": "9 AM–5 PM"},{"day": "Wednesday","hours": "9 AM–5 PM"},{"day": "Thursday","hours": "9 AM–5 PM"},{"day": "Friday","hours": "Closed"},{"day": "Saturday","hours": "Closed"},{"day": "Sunday","hours": "Closed"}],"permanentlyClosed": false,"claimed": true,"hotelStars": null,"imageUrl": "https://lh3.googleusercontent.com/grass-cs/AABkmLeDAPF6vpBqE…=w1024-h768-k-no","photosCount": 27,"reservationUrl": null,"orderOnlineUrl": null,"appointmentUrl": "https://www.dthompsondds.com/schedule?utm_source=google_apt&ao=Google","attributes": ["Accessibility: Wheelchair accessible entrance","Accessibility: Wheelchair accessible parking lot","Accessibility: Wheelchair accessible restroom"],"email": "officemgr@derricklanedds.com","emails": ["officemgr@derricklanedds.com"],"websitePhones": [],"facebook": "https://www.facebook.com/dr.derrick.thompson","instagram": "https://www.instagram.com/derrickthompsondds","linkedin": null,"twitter": null,"youtube": null,"tiktok": null,"pinterest": null,"contactPageUrl": null,"contactsStatus": "ok","searchTerm": "dentist","searchLocation": "California","rank": null,"scrapedAt": "2026-10-18T20:24:07.321Z"}
{"placeId": "ChIJ0bpq0abP-4YRluww5_1ogNc","cid": "15528526954888227990","fid": "0x86fbcfa6d16abad1:0xd78068fde730ec96","kgmid": "/g/11bx5p2csv","name": "Saltgrass Steak House","url": "https://www.google.com/maps/search/?api=1&query=Saltgrass%20Steak%20House&query_place_id=ChIJ0bpq0abP-4YRluww5_1ogNc","cidUrl": "https://maps.google.com/?cid=15528526954888227990","category": "Steak house","categories": ["Steak house","American restaurant","Seafood restaurant"],"description": "Informal Texas-themed chain offers a meaty menu & full bar amid cattle kitsch decor.","address": "7240 TX-191, Odessa, TX 79762","street": "7240 TX-191","neighborhood": null,"city": "Odessa","postalCode": "79762","state": "Texas","countryCode": "US","lat": 31.909217499999997,"lng": -102.2989264,"plusCode": "853VWP52+MC","timeZone": "America/Chicago","phone": "(432) 563-1951","phoneE164": "+14325631951","website": "https://www.saltgrass.com/location/saltgrass-odessa/","domain": "saltgrass.com","rating": 4,"reviewsCount": 2635,"reviewsUrl": "https://search.google.com/local/reviews?placeid=ChIJ0bpq0abP-4YRluww5_1ogNc&q=restaurant&authuser=0&hl=en&gl=US","openingHours": [{"day": "Monday","hours": "11 AM–9:30 PM"},{"day": "Tuesday","hours": "11 AM–9:30 PM"},{"day": "Wednesday","hours": "11 AM–9:30 PM"},{"day": "Thursday","hours": "11 AM–9:30 PM"},{"day": "Friday","hours": "11 AM–10 PM"},{"day": "Saturday","hours": "11 AM–10 PM"},{"day": "Sunday","hours": "11 AM–9:30 PM"}],"permanentlyClosed": false,"claimed": true,"hotelStars": null,"imageUrl": "https://lh3.googleusercontent.com/grass-cs/AABkmLcMZ7uQQRM0p…=w1024-h768-k-no","photosCount": 1200,"reservationUrl": "https://www.saltgrass.com/location/saltgrass-odessa/","orderOnlineUrl": null,"appointmentUrl": null,"attributes": ["Accessibility: Wheelchair accessible entrance","Accessibility: Wheelchair accessible parking lot","Accessibility: Wheelchair accessible restroom","Accessibility: Wheelchair accessible seating"],"searchTerm": "restaurant","searchLocation": "Texas","rank": null,"scrapedAt": "2026-10-18T20:24:12.791Z"}
How the area splitting works (and why Google Maps stops at 120)
The cap. A Google Maps search shows 20 places per page and stops after about six pages — roughly 120 places per search, however many exist. That is why scraping "restaurants in Texas" with a single search returns a tiny, random-looking sample: Google answers with the most prominent places for the visible map, not with all of them. The JSON behind the result list behaves the same way: one map view returns at most about 100–120 places for a city block and up to ~200 for a large view (measured 2026-10-18), and asking for a second page of the same view repeats or stops.
The fix: many small map views. The Actor never relies on one search. For every search term and location it:
- Geocodes the location with OpenStreetMap and keeps its real boundary (a polygon for cities, states and countries; a circle for an explicit lat/lng + radius; a rectangle for a bounding box or a Google Maps link).
- Searches the whole area as one map view first. Those places come back within seconds and carry
rank— Google's own order for that area. - Splits any view that is full. When 50 or more of the places Google returned lie inside the view, the view is cut into four and each quarter is searched again. Views wider than 100 km are always split (for a state-sized view Google zooms out to the whole continent and answers nationwide favourites — measured: a Texas-wide view returned 69 places, 10 of them in Texas). Views that touch the area only from outside (the ocean next to a coastal city, Oklahoma next to Texas) are never searched.
- Stops where Google runs out. A view with fewer than 50 places inside it is complete: Google has filled its answer with everything in the view and then with places outside it. The smallest view is 100 m, so even the densest city blocks are read.
- Keeps only places inside the area (the polygon / circle / box — not just the bounding rectangle) and de-duplicates by place ID across views, search terms and locations.
Does it really find everything? We tested the densest restaurant district we know of, a 1.1 × 1.2 km piece of Manhattan's East Village. A brute-force grid of 90 overlapping searches (one every 120 m) found 605 distinct restaurants inside the box. The Actor's splitting found 599 of them with 33 searches — 99.0 % of the brute-force total for a third of the requests. In the same district, one single map view returned 96 restaurants out of the ~194 inside a 500 m square, which is exactly the gap the splitting closes.
What it costs in requests. Rural views need one request; dense downtowns need a few levels of splitting. Measured: Los Angeles dentists, 1,000 places → 28 map views; Austin plumbers, every one (315) → 24 views; 20,000 Texas restaurants → 522 views; all of Texas → 7,310 views. Each view returns up to ~200 places in one request, so there is no paging delay.
Order of results. Views are read breadth-first: the first rows are the whole-area view (the most prominent places, with rank), then each split level. With a small maxItems you therefore get the places Google considers most relevant for the whole area first — not the places of one corner.
How much data can I get from Google Maps?
Measured on the Apify platform on 2026-10-18, default memory (2 GB):
| Run | Places | Time | Notes |
|---|---|---|---|
| Form example (50 restaurants, New York, e-mails on) | 50 | 7.9 s | first rows after ~4 s |
| 1,000 restaurants, Chicago, default settings (e-mails on) | 1,000 | 39 s | 0 duplicates; 804 websites visited |
| 1,000 dentists, Los Angeles, default settings | 1,000 | 43.9 s | 0 duplicates; 784 websites visited |
| 300 dentists, Berlin + London + Istanbul (3 searches) | 300 | 17.8 s | 76 % of the websites gave an e-mail |
| 60 hotels, Shinjuku (Tokyo) | 60 | 10.5 s | hotel star class, local + E.164 phones |
| 10,000 dentists, California, e-mails on | 10,000 | 422 s | 0 duplicates; 7,450 websites visited, 2,732 with an e-mail |
| 20,000 restaurants, Texas, Google data only | 20,000 | 129 s | 522 map views, 0 duplicates |
| Every restaurant in Texas, Google data only | 89,013 | 2,345 s (39 min) | every map view read (7,310 views, 13 split levels), 0 duplicates, 0 refusals from Google, 1,880 permanently closed places skipped |
Rules of thumb from these runs:
- Google data only: the first tens of thousands of places come at 100–200 per second; reading the very last place of a big state takes longer because dense cities need many small views (all of Texas: 39 minutes, every view read).
- With e-mails and social profiles: about 25 places per second (every website is visited); 1,000 places in under a minute, 10,000 in about 7 minutes.
- Per city: a mid-size city has hundreds of places per trade and thousands of restaurants; the run log and the SUMMARY show exactly how many map views each search needed.
- Per country: use the country name as the location (
"Netherlands","Portugal") — the boundary polygon keeps neighbouring countries out. For very large countries, splitting by state or region gives you per-region progress and lets you cap each withmaxItemsPerSearch.
Big runs need a big enough "Maximum cost per run". Apify stops every pay-per-result run at its Maximum cost per run (you set it in the run options; the platform also sets a default). The Actor reads that limit at the start, stops cleanly when it is reached and says so in the status message — for example "Saved 20 places — this run's maximum cost ($0.05) covers 20 results at the current price. Raise 'Maximum cost per run' to get more." The run still ends as Succeeded and you pay only for the places saved. For a whole state, raise the limit to cover it (see What you pay).
E-mails and social profiles: the contact enrichment
Google Maps lists a phone and a website for most businesses, but not their e-mail. With Add e-mails & social profiles from websites on (the default), the Actor visits each place's website once:
- The homepage is read (the website URL from Google Maps; Google's own redirect links such as
/url?q=…are unwrapped first — about 5 % of Google Maps websites are stored that way). - If the homepage shows no e-mail, one obvious contact / about / imprint page on the same site is read (
contact,kontakt,contacto,impressum,about,iletisim, … in 15+ languages). - From the HTML it extracts:
- E-mails from
mailto:links, visible text, Cloudflare-protected addresses (decoded),[at]/(at)/[dot]obfuscations and schema.org"email"fields. Every address is validated (syntax, real-looking TLD, no file names such aslogo@2x.png, no tracking hashes, nosentry/wixpress/example.com/ site-builder placeholders such ashi@mystore.com, nonoreply). Addresses on the business's own domain are listed first;emailis the best one,emailsall of them (up to 10). - Phones from
tel:links (websitePhones), minus the number Google already shows. - Social profiles: the first Facebook page, Instagram account, LinkedIn company/person page, X (Twitter) account, YouTube channel, TikTok account and Pinterest profile linked from the site — share buttons, intent links, posts and login pages are ignored.
- E-mails from
- Hard limits: about 7 s and 1.5 MB per page, 9 s per site, 64 sites in parallel. A slow or broken website never holds up the run; it just leaves the contact fields empty with the reason in
contactsStatus.
Measured hit rates (2026-10-18):
| Search (platform runs, 2026-10-18) | Websites visited | With e-mail | With a social profile | Not readable |
|---|---|---|---|---|
Dentists — Munich (Zahnarzt, language de) | 452 | 373 (83 %) | 98 (22 %) | 19 (4 %) |
| Dentists — Berlin, London, Istanbul | 286 | 216 (76 %) | 133 (47 %) | 10 (3 %) |
| Dentists, orthodontists, dental clinics — Berlin, London, Istanbul | 1,575 | 1,087 (69 %) | 636 (40 %) | 142 (9 %) |
| Car repair — Sydney | 386 | 198 (51 %) | 134 (35 %) | 49 (13 %) |
| Plumbers — Austin, TX | 300 | 151 (50 %) | 107 (36 %) | 43 (14 %) |
| Dentists — Los Angeles | 784 | 291 (37 %) | 324 (41 %) | 112 (14 %) |
| Dentists — all of California (10,000 places) | 7,450 | 2,732 (37 %) | 3,211 (43 %) | 902 (12 %) |
| Restaurants — Chicago | 804 | 248 (31 %) | 264 (33 %) | 137 (17 %) |
| Coffee shops — Seattle | 306 | 89 (29 %) | 88 (29 %) | 73 (24 %) |
| Hotels — Shinjuku, Tokyo | 239 | 57 (24 %) | 78 (33 %) | 27 (11 %) |
European businesses publish e-mail addresses far more often (German sites must carry an Impressum), trades publish them more than restaurants, and US clinics and restaurants often use contact forms instead. In a hand check, sampled e-mails were found literally on the business websites (8 of 8 that loaded) and the social links pointed to the business's own pages.
Why some websites are "not readable": the site is down, answers 403 to non-browser visitors (some Cloudflare setups), redirects to a booking platform, or does not answer within the time limit. Those rows still have every Google Maps field.
What you pay
A fixed price per place saved in the dataset. Compute, proxies and the website visits for e-mails and social profiles are included. There is no monthly rental, no start fee and no charge for duplicates, for places outside your area, for places your filters removed, or for ads (which are skipped).
| Apify plan | Price per 1,000 places | 1,000 places | 10,000 places | 100,000 places |
|---|---|---|---|---|
| Free | $2.50 | $2.50 | $25.00 | $250.00 |
| Bronze | $2.23 | $2.23 | $22.33 | $223.30 |
| Silver | $1.97 | $1.97 | $19.67 | $196.70 |
| Gold, Platinum, Diamond | $1.70 | $1.70 | $17.00 | $170.00 |
The e-mail and social-profile enrichment costs nothing extra: a place costs the same with or without it.
Maximum cost per run
Every pay-per-result run on Apify has a Maximum cost per run (Run options → Max cost per run; the platform sets a default when you set none). The Actor reads it before it starts:
- If the limit covers fewer places than you asked for, the log says so at the start ("This run's maximum cost ($5.00) covers 2,000 results at the current price — fewer than the 10,000 requested").
- It stops exactly at the number of places the limit covers, saves them, and finishes as Succeeded with the status "Saved N places — this run's maximum cost ($X) covers N results at the current price. Raise 'Maximum cost per run' to get more." The
SUMMARYrecord hasstoppedBy: "MAX_COST". - You are never charged more than the limit, and the run never ends as Aborted because of it.
To export a whole state or country, set the limit to at least the number of places you expect × the price per place (for example 50,000 places × $0.0025 = $125 on the Free plan) — or keep maxItems and the limit low for a first look.
Integrations
API. Start runs and read datasets with the REST API (see the API tutorial) or the official clients: apify-client for JavaScript/TypeScript and apify-client for Python. Datasets download as JSON, JSONL, CSV, Excel (XLSX), XML, HTML or RSS; fields=, omit=, offset=, limit= select exactly what you need.
Make (Integromat). Use the Apify app: Run an Actor with logiover/google-maps-scraper and your input JSON, then Get Dataset Items and map name, phone, email, website into Google Sheets, HubSpot, Pipedrive, Airtable or an e-mail tool.
Zapier. Trigger Run Actor on a schedule or from a form, and use Find Dataset Items to push each place into your CRM or a spreadsheet row.
n8n. The Apify node (or an HTTP Request node calling run-sync-get-dataset-items) returns the places as items you can filter, de-duplicate by placeId and write to Postgres, Sheets or a CRM.
Google Sheets. Connect the Apify Google Sheets integration to a saved task: after every run, new places are appended to your sheet. Or import the CSV export link with =IMPORTDATA("https://api.apify.com/v2/datasets/DATASET_ID/items?format=csv&clean=true&token=…").
Airtable, HubSpot, Salesforce, Pipedrive and other CRMs. Add a webhook on Run succeeded that calls your middleware (or a Make/Zapier/n8n scenario) with the dataset id; upsert by placeId so re-runs update existing companies instead of duplicating them. phoneE164 is the format CRMs and dialers expect.
Webhooks and scheduling. Save your input as a task, schedule it (cron or the Console scheduler) and attach a webhook for ACTOR.RUN.SUCCEEDED. Typical setups: weekly "new businesses in my territory" feeds, monthly rank tracking for a keyword, nightly refresh of known places via placeIds.
Data warehouses. Export to S3 / Google Cloud Storage via the Apify integrations or pull the dataset over the API into BigQuery, Snowflake or Postgres; the flat row (arrays only for categories, hours, e-mails, attributes) maps directly to a table.
MCP and AI agents. The Actor works through the Apify MCP server, so Claude, ChatGPT and other agents can call it as a tool ("list the dentists in Rotterdam with an e-mail and a rating above 4.5") and receive structured rows. For RAG, embed name, categories, description, address, openingHours and attributes.
Performance tips
- Put the place in
locations, not in the search term."dentist"+"Austin, TX"is split into map views and fully read;"dentist in Austin"without a location is one Google search (~200 places at most). - Turn contact enrichment off for pure Google Maps exports. Google data alone runs at 100–200 places per second on big areas; with e-mails it is ~25 per second because every website is visited.
- Use specific terms.
"plumber"finds plumbers and Google's neighbours (water-heater stores, HVAC companies); addcategoryFilter: ["plumber"]to keep only plumbers. - Several related terms catch more businesses. Google matches the term against names and categories;
"dentist","dental clinic"and"orthodontist"overlap but each adds places the others miss. Duplicates across terms are removed for free. - Cap big multi-location runs per search with
maxItemsPerSearch, so every city gets its share beforemaxItemsis reached. - For countries, consider regions. One country-wide search works; splitting it into states/regions gives you per-region results and lets you stop early.
- Use place IDs for refreshes. Looking up 1,000 known places by
placeIdsis one request per place — no searching. - Language matters for categories and hours, not for coverage:
language: "de"returns German category names and weekday names.
Troubleshooting: every status message explained
| Status message / outcome | What it means | What to do |
|---|---|---|
Saved N places (max results reached) in S s. | You got the maxItems you asked for. | Raise maxItems (or set 0) for more. |
Saved N places (every matching place read) in S s. | Every map view of every search was read; Google has no more places for these searches in these areas. | Add more search terms or locations. |
Saved N places — this run's maximum cost ($X) covers N results… | The run's Maximum cost per run was reached; SUMMARY stoppedBy: MAX_COST. | Raise Max cost per run in the run options. |
Saved N places (stopped at the run time limit) | The run's timeout (default 1 hour) came first. | Raise the timeout in the run options, or split the job. |
No places matched — Google Maps answered but returned 0 places… (outcome EMPTY_RESULT, run Succeeded) | Google answered, but nothing matched (or your filters removed everything — see filteredOut in SUMMARY). | Check the spelling of the term, use a broader term or fewer filters. |
Run Failed: No places collected: no page could be fetched… (outcome BLOCKED / FETCH_FAILED) | Google refused every route (direct, datacenter proxy, your proxy). This is reported as a failure on purpose — an empty dataset must never look like a successful search. | Retry later, or choose a different proxy group (e.g. residential) in Proxy configuration. |
Nothing to search… (outcome BAD_INPUT) | No search terms, URLs or place IDs were given. | Add searchTerms + locations, startUrls or placeIds. |
Log: "X" → <place> (N km², boundary polygon) | How each location was understood. | If the wrong place was picked, add the country or state: "Paris, France", "Portland, OR". |
Log: Location "X" could not be found… | Neither OpenStreetMap nor Google could place it; it ran as the text "term in X" (up to ~200 places). | Fix the spelling or use lat/lng + radiusKm or boundingBox. |
Log: Google Maps refused the direct connection…; switching to the datacenter proxy. | Google rate-limited the direct route; the run continues on Apify datacenter proxies (a new IP per request) and returns to the direct route when it works again. | Nothing — this is automatic. |
contactsStatus: website not readable (HTTP 403) | The business's website refused the visit. | Nothing to fix on your side; the Google Maps fields are complete. |
contactsStatus: no contacts found on website | The site (homepage + one contact page) shows no e-mail, tel: link or social profile. | Normal for sites with contact forms only. |
The SUMMARY record of every run (key-value store) adds the details: per-search map views, splits and depth, duplicates skipped, places outside the area, filter counts, contact-enrichment totals, the network route used and the reason the run stopped.
Honest limits
- Google's own data is the ceiling. The Actor returns what Google Maps returns for your search terms. Businesses that do not match the term (wrong category, unusual name) are found only with additional terms.
- No price level. Google Maps no longer includes the "$$" price level in its result data (checked 2026-10-18 on restaurants in New York, including steakhouses and fast food, from US and non-US connections, and on the place page itself), so the field is not offered rather than shipped empty.
- Temporarily closed places are not marked in Google's result data;
permanentlyClosedcovers businesses Google marks as closed for good. - Reviews text is not included — this Actor exports places. Each row has
reviewsUrl,ratingandreviewsCount. - Opening hours are the regular weekly hours; holiday hours and secondary hours (delivery, brunch) are not separate fields.
- E-mails come from public websites only. Businesses without a website, or whose website shows only a contact form, have no e-mail. The Actor does not guess or generate addresses.
- Service-area businesses (plumbers, cleaners) often hide their street address on Google Maps; for them
addressis empty or only a city, and the coordinates are the center of their service area. - Very dense blocks: the smallest map view is 100 m; in the measured worst case the splitting found 99.0 % of what a brute-force grid found.
- Not real-time: a run is a snapshot; schedule it to track changes.
Comparison: Google Places API, manual copying and this Actor
| This Actor | Official Google Places API | Copying from Google Maps by hand | |
|---|---|---|---|
| Setup | Apify account; no API key, no billing account with Google | Google Cloud project, API key, billing account | None |
| Results per search | Whole areas: city, state, country (area splitting) | 20 per page, 60 per Text/Nearby search | ~120 per search, by scrolling |
| E-mails and social profiles | Included (from the business websites) | Not available | Manually, site by site |
| Phone, website, rating, reviews count, hours | Yes, every row | Yes, billed per field group | Yes |
| Export | CSV, Excel, JSON, XML, API, integrations | JSON responses you have to page and store | Copy & paste |
| Storage terms | Your data, export and keep it | Google's terms restrict caching / storing most fields | — |
| Cost model | Fixed price per place, everything included | Per request and per field tier | Your time |
| Best for | Lead lists, market maps, bulk exports, monitoring | Real-time lookups inside an app | A handful of places |
The official API is the right tool when an app needs live data for a few places at a time under Google's terms; this Actor is built for bulk exports of public listing data for analysis and outreach.
FAQ
What is a Google Maps scraper?
A tool that reads the public business listings shown on Google Maps — name, address, phone, website, rating, reviews count, hours, coordinates — and saves them as structured data (rows in a spreadsheet or JSON) instead of you copying them by hand. This one also visits each business's website for e-mails and social profiles.
How do I scrape Google Maps without an API key?
Open this Actor, type what you are looking for in Search terms and where in Locations, and click Start. It reads the same data the Google Maps website shows to every visitor; no Google API key, no Google Cloud billing account and no login are involved.
Is this a Google Maps API alternative or a Google Places API alternative?
Yes for bulk use. The Places API is designed for apps that look up a few places live; this Actor exports whole areas into CSV/Excel/JSON with phones, websites, ratings, hours and e-mails, at a fixed price per place.
How many results can I get from Google Maps?
As many as Google Maps has for your search: a single Google Maps search stops at about 120 places, but the Actor splits the area into many map views, so a city, a state or a country is read completely. Measured: 89,013 restaurants for all of Texas in one run.
Why does Google Maps only show 120 results?
Google shows 20 places per page and stops after about six pages for any one search and map view. More places exist, but Google only returns the most prominent ones for that view. Searching many smaller views — what this Actor does automatically — is the only way past the limit.
How do I scrape all businesses in a city?
Use the city as the location, your business type as the search term and maxItems: 0. For "all businesses of every kind", run several broad terms ("store", "restaurant", "service", …) — Google Maps has no single "everything" search.
Can I scrape Google Maps for a whole state or a whole country?
Yes. Type the state ("Texas") or country ("Netherlands") as the location. The boundary comes from OpenStreetMap and is split into map views; places outside the boundary are dropped. Make sure Maximum cost per run covers the number of places you expect.
How do I extract emails from Google Maps?
Keep Add e-mails & social profiles from websites on (default). Google Maps itself does not publish e-mails; the Actor reads each listed website (homepage + one contact page) and returns validated addresses in email and emails.
How many of the places will have an e-mail address?
It depends on the industry and country. Measured on 2026-10-18: 76 % of dentists' websites in Berlin, London and Istanbul; 37 % in Los Angeles; 31 % of Chicago restaurants' websites; 37 % of 7,450 California dental websites.
Can I extract phone numbers from Google Maps?
Yes — phone (as shown on Google Maps in that country) and phoneE164 (international format, e.g. +12124666699) on about 95 % of places in the measured runs, plus extra numbers from the business's website in websitePhones.
Can I get the websites of businesses on Google Maps?
Yes, website (as listed, with Google's redirect wrappers removed) and domain (e.g. nonnatata.com). Use Website → Only places with a website to keep only those.
How do I find businesses without a website?
Set Website → Only places without a website. Combined with minReviews, it returns active businesses that have customers but no site — a classic lead list for web designers.
How do I export Google Maps data to Excel or CSV?
After the run, click Export in the Output tab and choose CSV or Excel, or use https://api.apify.com/v2/datasets/DATASET_ID/items?format=xlsx (or format=csv). Arrays such as categories and emails become numbered columns.
Can I export Google Maps results to Google Sheets?
Yes: connect the Apify Google Sheets integration to a saved task, or import the CSV export URL with IMPORTDATA, or use Make / Zapier / n8n.
Does it scrape Google Maps reviews?
It returns the rating, the number of reviews and a link to the reviews for every place. Review texts are not part of this Actor's output.
Does it return opening hours?
Yes, the regular hours for all seven days (openingHours), e.g. Monday: 11:30 AM–3:45 PM, 5–10:15 PM, in the language you choose.
Does it get the place ID and CID?
Yes: placeId (ChIJ…), cid (the number in maps.google.com/?cid=…), fid (feature ID) and kgmid for every place, plus two working links (url, cidUrl).
Can I scrape Google Maps by coordinates or radius?
Yes: set lat, lng and radiusKm (1–500 km). Or give a boundingBox (south,west,north,east), or paste a Google Maps link that contains @lat,lng,zoom.
Can I paste Google Maps URLs?
Yes. Search links (/maps/search/…/@lat,lng,zoomz) are searched over the visible area; place links (/maps/place/…, ?cid=, place_id:) are looked up directly.
Can I look up a list of place IDs or CIDs?
Yes, put them in Place IDs / CIDs — ChIJ place IDs, numeric CIDs and 0x…:0x… feature IDs are accepted. Each becomes one fresh row.
Does it work in other countries and languages?
Yes, anywhere Google Maps has listings. Measured in the US, Germany, the UK, Turkey, Japan, France and Australia. Set language for categories and hours in that language; the Google country is taken from each location automatically.
Can I search in a language other than English?
Yes. Search terms can be in any language ("Zahnarzt", "diş hekimi", "歯科"), and language controls the language of categories, weekdays and descriptions.
How fast is it?
First rows after about 4 seconds. 1,000 places with e-mails in 39–44 s; 10,000 with e-mails in 422 s; 20,000 without e-mails in 129 s (all measured 2026-10-18).
How much does it cost to scrape Google Maps?
$2.50 per 1,000 places on the Free plan, down to $1.70 per 1,000 on Gold and higher — including e-mails and social profiles. 10,000 places cost $17–$25. See What you pay.
Do I need proxies to scrape Google Maps?
No. The Actor connects directly first; if Google slows that route down or shows a captcha, it switches to Apify datacenter proxies with a new IP per request automatically, and back when the direct route works again. The proxy setting is only a last fallback.
Do I need a Google account or cookies?
No. Nothing the Actor reads requires signing in.
Will I get duplicates?
No. Places are de-duplicated by place ID across all map views, search terms and locations (measured: 0 duplicates in runs of 10,000, 20,000 and 89,013 places).
Are ads included?
No. Sponsored results are detected and skipped.
Why are some places outside my city?
They are not saved: every place is checked against the location's boundary polygon (or circle / box), and places outside are dropped (the SUMMARY counts them as outsideArea). If you see places from a neighbouring town, it is inside the boundary OpenStreetMap has for your location — use a district, a radius or a bounding box to narrow it.
Why did my run return fewer places than "Max places"?
Either every map view was read and Google has no more places for that term in that area ("every matching place read"), your filters removed some (SUMMARY filteredOut), or the run's Maximum cost per run was reached (the status message says so).
What is the difference between phone and phoneE164?
phone is the number as Google Maps displays it in that country ((212) 466-6699, 030 2513037); phoneE164 is the same number in international E.164 format (+12124666699, +49302513037) for dialers and CRMs.
What does claimed mean?
true when the business has claimed its Google Business Profile; false when Google shows "Claim this business" on the listing — useful for local-SEO and Google Business Profile service pitches.
Can I monitor new businesses on Google Maps?
Yes. Schedule the same search (as a task) daily or weekly and compare placeIds with the previous export; new IDs are new listings. Set skipClosed: false to also see which ones closed.
Can I track local rankings for a keyword?
Yes. For a city-sized location, rank is each place's position in Google's answer for the whole city view. Run the same keyword and city on a schedule to track movement.
Does it get Google Maps photos?
It returns the main photo (imageUrl, 1024 × 768) and the number of photos on the listing (photosCount).
Does it work for hotels?
Yes. Hotels get hotelStars where Google lists a star class, along with photos, address, phone and website.
Does it scrape service-area businesses (plumbers, cleaners) that hide their address?
Yes. They are returned with name, phone, website, rating and categories; Google gives them no street address, so address is empty or only a city.
How accurate is the data?
It is Google Maps' own data, as fresh as the run. Every field was checked by hand on 26 places in the US, Germany, the UK, Turkey, Japan, Australia and France against the live Google Maps page and a second request to Google's place endpoint; all compared fields matched.
Can I use it with Make, Zapier or n8n?
Yes — use the Apify app/node to run the Actor and fetch the dataset, then route the places to any of the thousands of apps those platforms connect to.
Can AI agents use this Google Maps scraper?
Yes, through the Apify MCP server or the API. An agent can ask for "cafés in Lisbon open on Sunday with an Instagram account" and get structured rows back.
Is there a free trial?
Apify's Free plan includes monthly platform credit you can use on this Actor; the form example (50 places) costs about $0.13.
What happens if Google blocks the run?
The Actor backs off on rate limits, switches network routes (direct → datacenter proxy → your proxy) and retries. If nothing works, the run fails with the reason in the log and the SUMMARY record instead of pretending to have succeeded with no data.
Can I scrape Google Maps for multiple keywords at once?
Yes. Add several search terms; each is combined with each location, results are de-duplicated, and maxItemsPerSearch caps each combination.
How do I get only one exact category, e.g. only plumbers?
Use categoryFilter: ["plumber"]. Google mixes neighbouring categories into most searches; the filter keeps only places whose categories contain your word.
What format are the coordinates in?
Decimal degrees (WGS 84): lat 40.7568769, lng -73.9804147 — ready for any map tool, plus the full plusCode.
I need a field or filter that is missing. Can you add it?
Yes — open an issue on the Actor's Issues tab and describe it.
Glossary
- Place ID — Google's public identifier of a place (
ChIJ…), used by the Places API, Google Ads and most tools. Stable for most places; Google can refresh it, which is why the CID is also given. - CID (customer ID) — the decimal number in
maps.google.com/?cid=…; a permanent link to a listing. It equals the second half of the feature ID. - Feature ID (fid) — Google's internal id
0x…:0x…. The Actor uses it to look places up directly. - kgmid — the Knowledge Graph machine id (
/g/…or/m/…) of the business. - Plus code — an Open Location Code (
87G8Q227+8C) that identifies a location to ~14 m, also where there are no street addresses. Computed with the official algorithm from the place's coordinates; identical to the code on the Google Maps place page in every hand check. - Map view / viewport — the rectangle of the map Google searches in. Google answers at most ~100–200 places per view, so the Actor searches many views.
- Area splitting (quadtree) — cutting a full view into four smaller views until each is complete.
- Boundary polygon — the outline of a city/state/country from OpenStreetMap, used to keep only places inside the area.
- E.164 — the international phone number format
+<country code><number>. - Claimed listing — a Google Business Profile the owner has verified; unclaimed listings show "Claim this business".
- Pay per result — the pricing model: you pay per place saved, nothing per request or per minute.
- Maximum cost per run — Apify's per-run spending cap for pay-per-result Actors; the run stops cleanly at it.
Is it legal to scrape Google Maps?
This Actor reads publicly available business listing information — the same data any visitor sees on Google Maps without signing in — and public pages of the businesses' own websites. Business names, addresses, phone numbers and opening hours are information businesses publish so that customers can find them.
Personal data and GDPR. Some fields can be personal data: e-mail addresses and phone numbers of sole traders, doctors or lawyers, or personal social media profiles. If you are in the EU/EEA/UK or process data about people there, the GDPR applies: you need a lawful basis (for B2B outreach usually legitimate interest, documented), must inform people where you got their data, honour objections and deletion requests, keep only what you need, and follow your country's rules on unsolicited e-mails, calls and texts (e.g. ePrivacy/PECR in the EU and UK, CAN-SPAM and TCPA in the US, CASL in Canada). Do not use the data for spam.
You are responsible for using the data in line with Google's terms, the terms of the websites visited, and applicable laws. If in doubt, consult a lawyer. Scraping public data is generally lawful in many jurisdictions, but how you store and use it matters most.
Legal & trademark disclaimer: This Actor is an independent tool and is not affiliated with, endorsed by, or sponsored by Google LLC. "Google" and "Google Maps" are trademarks of Google LLC, used here only to describe the data source.
Changelog
- 1.0 (2026-10-18) — First release: Google Maps search data (up to ~200 places per request) with automatic area splitting over OpenStreetMap boundaries (city, state, country, circle, bounding box, Google Maps links), place lookups by place ID / CID / feature ID / URL, contact enrichment from websites (e-mails with validation,
tel:phones, seven social networks), filters (rating, reviews, website, closed, category), 31 languages, pay-per-result budget handling.
Support
Questions, a bug, or a feature request? Open an issue on the Issues tab — we reply within 24 hours. If a run did something unexpected, include the run link so we can see its log and SUMMARY.