# Google Maps Scraper — Cheap Places & Business Leads, No Browser (`fabrikit/google-maps-places-scraper`) Actor

Scrape Google Maps places without a browser: name, categories, address, business phone, website, rating, review count, opening hours, coordinates and plus code for any search and area. Deep tile scan covers whole cities. No reviews or personal data. Pay per result, no subscription.

- **URL**: https://apify.com/fabrikit/google-maps-places-scraper.md
- **Developed by:** [Fabrikit](https://apify.com/fabrikit) (community)
- **Categories:** Lead generation, Travel, Automation
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $1.00 / 1,000 place results

This Actor is paid per event. You are not charged for the Apify platform usage, but only a fixed price for specific events.

Learn more: https://docs.apify.com/actors/running/actors-in-store.md#pay-per-event

## What's an Apify Actor?

An Actor is a serverless cloud program that runs on the Apify platform. It has two run modes.
In Batch mode, an Actor accepts a well-defined JSON input, performs an action which can take anything from a few seconds to a few hours,
and optionally produces a well-defined JSON output, datasets with results, or files in key-value store.
In Standby mode, an Actor provides a web server which can be used as a website, API, or an MCP server.

Apify vocabulary and the platform model are defined once, in the agent quickstart at https://apify.com/agents.md.

## How to integrate an Actor?

If asked about integration, you help developers integrate Actors into their projects.
You adapt to their stack and deliver integrations that are safe, well-documented, and production-ready.

Do not guess an integration path. Every one of them is in the agent quickstart at https://apify.com/agents.md: the Apify MCP server, Agent Skills with the Apify CLI, the JavaScript and Python clients, the REST API, and the account-free path for an agent with no human to sign in. It also carries the rule on stating cost before the first paid run.

For examples already wired to this Actor's own input schema, see the [API](#api) section below.

Each client library has reference documentation the quickstart does not restate: [JavaScript/TypeScript](https://docs.apify.com/api/client/js/docs.md) (`npm install apify-client`) and [Python](https://docs.apify.com/api/client/python/docs.md) (`pip install apify-client`).

# README

## Google Maps Scraper — Cheap Places & Business Leads (No Browser)

Extract business listings from Google Maps for any search term and any area: **name, categories, full address (street, city, postal code, state, country), business phone, website, rating, review count, opening hours, coordinates, plus code, Google place ID / CID and a Maps link**.

It reads the same JSON data the Google Maps web app loads, over plain HTTP — no headless browser — so it is fast and cheap: you pay per place saved (see *Pricing*). A deep area scan splits busy areas into smaller map tiles, so a city-wide search returns far more than the ~120–200 places a single map view shows.

- No login, no API key, no Google Cloud billing account
- Whole cities, regions or countries, a radius around a point, or your own Google Maps search URLs
- Filters: minimum rating, has website, has phone, category contains, skip permanently closed
- Business data only: **no reviews, no reviewer names, no owner/personal data**

### What you get

| Field | Example |
|---|---|
| `name` | Bittersweet |
| `category`, `categories` | Coffee shop · \[Coffee shop, Cafe, Espresso bar] |
| `address`, `street`, `neighborhood`, `city`, `postalCode`, `state`, `countryCode` | 180 Dekalb Ave, Brooklyn, NY 11205 · … · US |
| `lat`, `lng`, `plusCode` | 40.6894477, -73.9725096 · 87G8M2QG+QX |
| `phone`, `phoneInternational`, `phoneUnformatted` | (718) 852-2556 · +1 718-852-2556 · +17188522556 |
| `website`, `domain` | http://www.bittersweetbk.com/ · bittersweetbk.com |
| `rating`, `reviewsCount` | 4.5 · 352 |
| `openingHours` | \[{ day: "Monday", hours: "7 AM–5 PM" }, …] |
| `description` | Google's one-line summary, when it has one |
| `permanentlyClosed`, `temporarilyClosed` | false · false |
| `placeId`, `cid`, `kgmid`, `googleMapsUrl` | ChIJ6wYBS7dbwokR0K9qNZKlD2A · 6921933199671734224 · … |
| `imageUrl`, `imagesCount`, `timezone`, `priceLevel` | main photo · 109 · America/New_York · (rarely provided) |
| `searchString`, `searchLocation`, `rank`, `scrapedAt` | which search found it and its position |

### Input examples

**Dentists in a city (the default):**

```json
{
    "searchStrings": ["dentist"],
    "location": "Austin, Texas",
    "maxItemsPerSearch": 50
}
```

**Several categories, every place in the area, with filters:**

```json
{
    "searchStrings": ["plumber", "electrician", "hvac contractor"],
    "location": "Denver, Colorado",
    "maxItemsPerSearch": 0,
    "minRating": 4,
    "onlyWithWebsite": true
}
```

**A radius around a point, in another language:**

```json
{
    "searchStrings": ["Zahnarzt"],
    "latitude": 52.5200,
    "longitude": 13.4050,
    "radiusKm": 3,
    "language": "de",
    "countryCode": "de"
}
```

**Your own Google Maps search URLs** (term and visible map area are read from the URL):

```json
{
    "startUrls": [{ "url": "https://www.google.com/maps/search/pizza/@41.9028,12.4964,15z" }]
}
```

### Output example

```json
{
    "placeId": "ChIJ6wYBS7dbwokR0K9qNZKlD2A",
    "cid": "6921933199671734224",
    "name": "Bittersweet",
    "category": "Coffee shop",
    "categories": ["Coffee shop", "Cafe", "Espresso bar"],
    "address": "180 Dekalb Ave, Brooklyn, NY 11205",
    "street": "180 Dekalb Ave",
    "neighborhood": "Fort Greene",
    "city": "Brooklyn",
    "postalCode": "11205",
    "state": "New York",
    "countryCode": "US",
    "lat": 40.6894477,
    "lng": -73.9725096,
    "plusCode": "87G8M2QG+QX",
    "phone": "(718) 852-2556",
    "phoneInternational": "+1 718-852-2556",
    "phoneUnformatted": "+17188522556",
    "website": "http://www.bittersweetbk.com/",
    "domain": "bittersweetbk.com",
    "rating": 4.5,
    "reviewsCount": 352,
    "priceLevel": null,
    "description": "Cozy coffee shop offering handcrafted coffee, house-made pastries & sandwiches.",
    "openingHours": [
        { "day": "Monday", "hours": "7 AM–5 PM" },
        { "day": "Tuesday", "hours": "7 AM–5 PM" },
        { "day": "Wednesday", "hours": "7 AM–5 PM" },
        { "day": "Thursday", "hours": "7 AM–5 PM" },
        { "day": "Friday", "hours": "7 AM–5 PM" },
        { "day": "Saturday", "hours": "7:30 AM–5 PM" },
        { "day": "Sunday", "hours": "7:30 AM–5 PM" }
    ],
    "permanentlyClosed": false,
    "temporarilyClosed": false,
    "timezone": "America/New_York",
    "imageUrl": "https://lh3.googleusercontent.com/grass-cs/AABkmLew…=w800-h600-k-no",
    "imagesCount": 109,
    "kgmid": "/g/1tl8lmsd",
    "googleMapsUrl": "https://www.google.com/maps/search/?api=1&query=Bittersweet&query_place_id=ChIJ6wYBS7dbwokR0K9qNZKlD2A",
    "searchString": "coffee shop",
    "searchLocation": "Brooklyn, New York",
    "rank": 3,
    "scrapedAt": "2026-10-13T12:21:08.284Z"
}
```

The dataset has two ready-made views: **Overview** and **Contacts (leads)** (name, phone, website, domain, address, postal code, country) — export either one to CSV/Excel in one click.

### Pricing

Pay per event — you only pay for places actually saved to the dataset.

| Event | When |
|---|---|
| `place-result` | each place saved to the dataset |
| `apify-actor-start` | once per run (a fraction of a cent) |

From 30 October 2026, 1,000 places cost US$3 on the Apify Free plan; paid Apify plans pay less per place — see the **Pricing** tab for your plan's rate. Duplicates, filtered-out places and places outside your area are never charged. Set a maximum cost per run in the Apify console and the actor stops cleanly when it is reached.

### How the area scan works

1. **Location** is looked up on Google Maps itself, which returns the area's boundaries (city, district, postal code, state or country).
2. The area is searched as a map view. Google only lists the most prominent places of a view and pads the list with places outside it — exactly like the Maps app, where more pins appear as you zoom in.
3. With **Deep area scan** on, every tile that still holds many places is split into 4 smaller tiles and searched again, recursively. On "dentist" in Austin this finds 1,251 places versus ~170 from one map view.
4. Places outside the area (and across national/state borders) are dropped, results are deduplicated by place ID across all your search terms, and the run stops exactly at your limit.

### FAQ

**How many places can I get?** As many as Google Maps shows when you zoom in across the area. Set **Max places per search term** to `0` for everything. Big cities hold hundreds to thousands of places per category.

**Does it scrape reviews or emails?** No. It returns business-level data only. Reviews, reviewer names and photos of people, owner accounts and personal data are deliberately not collected. Use the `website`/`domain` fields with an email-finder of your choice if you need emails.

**Why is `address` empty for some businesses?** Service-area businesses (plumbers, cleaners, mobile services) hide their street address on Google Maps; you still get name, phone, website, categories and an approximate location.

**Why does the location also include nearby towns?** Google returns a bounding box for a city, so neighbouring suburbs inside that box are included. Use the `city` field to filter, or a smaller location / radius.

**Is `priceLevel` filled?** Only when Google includes a price level in its list results, which is currently rare. Everything else in the table above is filled whenever the business published it.

**Do I need proxies?** No setup needed. The actor starts on Apify datacenter proxy and, if Google rate-limits those IPs, switches automatically to residential proxy for the rest of the run. The run summary (key-value store record `SUMMARY`) shows which proxy was used, per-search counts and any errors.

**What happens if Google blocks everything?** The run fails with a clear message instead of finishing "successfully" with 0 results, and you are not charged for places that were not saved.

**Which languages and countries?** Any. `language` sets the language of categories, hours and descriptions; `countryCode` helps with ambiguous place names.

**Can I get leads for several cities in one run?** Run one task per city (the `location` field takes one area), or paste several Google Maps search URLs into `startUrls`. Results are deduplicated by place ID across your search terms.

### Use cases

- **Lead generation** — local business lists with phone and website for sales and agencies
- **Market research** — count and map competitors by category, rating and neighbourhood
- **Local SEO** — audit categories, ratings and review counts across a city
- **Travel & directories** — restaurants, hotels, attractions with coordinates and hours
- **Data enrichment** — attach place IDs, coordinates and plus codes to your own records

### Is it legal to scrape Google Maps?

This actor only collects business information that Google Maps shows publicly to any visitor, without logging in, and it deliberately skips reviews, reviewer names and owner accounts. Business listings can still contain personal data, for example the phone number or address of a sole trader, so laws such as the EU GDPR, Chile's Ley 21.719 or the California CCPA, and anti-spam rules for cold calls and e-mails, may apply to how you use the data; you are responsible for a lawful purpose. Respect Google's terms of service, and do not republish photos or descriptions as your own. This is general information, not legal advice.

### Integrations

Run the Google Maps Scraper from the Apify API or the JavaScript and Python clients, push new leads to your CRM with webhooks, or schedule it in Apify Console. It works with n8n, Make and Zapier (for example, to send the **Contacts (leads)** view to Google Sheets or HubSpot), and with LangChain and LlamaIndex through their Apify integrations. AI agents in Claude, ChatGPT, Cursor and other MCP clients can find and run it through Apify's MCP server. Export as JSON, CSV or Excel, or read from the dataset API.

### Use with AI agents

Use this actor to list businesses on Google Maps for a search term and an area (city, region, country, radius or Maps URL), with address, phone, website, rating, review count, opening hours and coordinates.

```json
{ "searchStrings": ["coffee shop"], "location": "Brooklyn, New York", "maxItemsPerSearch": 30 }
```

Main output fields: `name`, `category`, `address`, `city`, `postalCode`, `countryCode`, `phone`, `website`, `domain`, `rating`, `reviewsCount`, `openingHours`, `lat`, `lng`, `placeId`, `googleMapsUrl`. It is pay-per-event: an agent pays a small start fee plus a fixed price per place saved, not for compute time.

### Related actors

- [Chile Company RUT Lookup](https://apify.com/fabrikit/chile-company-rut-lookup) — official SII data for Chilean businesses you find on the map.
- [Google Ads Transparency Scraper](https://apify.com/fabrikit/google-ads-transparency-scraper) — check which of those businesses advertise on Google.
- [Booking.com Scraper](https://apify.com/fabrikit/booking-hotels-scraper) — hotel prices and ratings for the same city.
- [Airbnb Scraper](https://apify.com/fabrikit/airbnb-search-scraper) — short-term rentals with prices and coordinates.
- [Google Trends Scraper](https://apify.com/fabrikit/google-trends-scraper) — search interest for a category by region.

#### Ready-made examples

- [Dentists in Miami with phone numbers](https://apify.com/fabrikit/google-maps-places-scraper/examples/dentists-miami-phone-numbers)
- [Plumbers in London with websites](https://apify.com/fabrikit/google-maps-places-scraper/examples/plumbers-london-websites)
- [Restaurantes en Ciudad de México](https://apify.com/fabrikit/google-maps-places-scraper/examples/restaurantes-ciudad-de-mexico)

### Changelog

- **2026-10-16** — README: legal notes, integrations, AI-agent usage, related actors and example tasks added; pricing text updated.
- **2026-10-15** — Tiered pricing announced, effective 2026-10-30 (lower per-place price on paid Apify plans).
- **2026-10-13** — Builds 0.1.1–0.1.2: initial release with deep area scan, radius and URL search, lead filters, Contacts view and residential proxy fallback; default memory 512 MB.

### En español

Extrae negocios de Google Maps para cualquier búsqueda y zona: nombre, categorías, dirección completa (calle, ciudad, código postal, región, país), teléfono del negocio, sitio web, nota, cantidad de reseñas, horario, coordenadas, plus code, place ID y enlace a Maps. Funciona por HTTP sin navegador, se cobra por lugar guardado (precio vigente en la pestaña Pricing) y el escaneo profundo divide la zona en cuadrantes para obtener muchos más resultados que una sola vista del mapa. Escribe el rubro en **Search terms** (por ejemplo `dentista`), la zona en **Location** (`Providencia, Santiago, Chile`) y elige `language: "es"`. No recopila reseñas, nombres de usuarios ni datos personales: solo datos públicos de negocios.

# Actor input Schema

## `searchStrings` (type: `array`):

What to look for on Google Maps, one term per line — exactly what you would type in the Maps search box: a category (`dentist`, `coffee shop`, `plumber`) or a name (`Starbucks`). Every term is searched in the location below. Put the place in **Location**, not here, so the actor can scan the whole area.

## `location` (type: `string`):

City, region, neighborhood, postal code with country, or country (`Austin, Texas`, `Kreuzberg, Berlin`, `90210, USA`, `Portugal`). Google finds its boundaries and the actor scans that whole area tile by tile. Leave empty to let Google decide (results then cluster around one spot).

## `maxItemsPerSearch` (type: `integer`):

Stop each search term after this many places (after filters). `0` = no limit: keep zooming into the area until Google shows nothing new. Big cities hold thousands of places per category.

## `language` (type: `string`):

Language of category names, opening hours and descriptions (Google's `hl`).

## `countryCode` (type: `string`):

Two-letter country code (`us`, `de`, `br`...). Helps Google pick the right place for ambiguous locations ("Valencia") and sets the country of the residential proxy fallback.

## `startUrls` (type: `array`):

Alternatively paste Google Maps search URLs, e.g. `https://www.google.com/maps/search/dentist/@30.2672,-97.7431,13z`. The term and the visible map area are taken from the URL. Place (`/maps/place/`) URLs are not supported.

## `latitude` (type: `number`):

Search a circle instead of a named location: center latitude (e.g. `40.7580`). Needs longitude too; overrides Location.

## `longitude` (type: `number`):

Center longitude (e.g. `-73.9855`).

## `radiusKm` (type: `number`):

Radius of the circle around latitude/longitude, in kilometres.

## `splitArea` (type: `boolean`):

Google lists only the most prominent places of a map view and reveals the rest as you zoom in. When on, busy parts of the area are split into smaller tiles and searched again, which finds many more places. Turn off for a single quick view.

## `onlyInsideArea` (type: `boolean`):

Drop places outside the location's boundaries (or the circle / URL map view). Google pads its lists with nearby places outside the area; turn off to keep them.

## `minRating` (type: `number`):

Keep only places with at least this star rating (1–5). Places without a rating are dropped when this is set.

## `onlyWithWebsite` (type: `boolean`):

Keep only businesses that list a website.

## `onlyWithPhone` (type: `boolean`):

Keep only businesses that list a phone number.

## `categoryFilter` (type: `array`):

Keep only places whose Google categories contain one of these words (case- and accent-insensitive), e.g. `dentist` keeps "Cosmetic dentist" and drops "Dental supply store". Use the same language as **Language**.

## `skipClosedPlaces` (type: `boolean`):

Drop places Google marks as permanently closed.

## `proxyConfiguration` (type: `object`):

Apify datacenter proxy by default. If Google blocks or rate-limits those IPs, the actor switches automatically to Apify RESIDENTIAL proxy (country from the Country field, else US) — no action needed.

## Actor input object example

```json
{
  "searchStrings": [
    "dentist"
  ],
  "location": "Austin, Texas",
  "maxItemsPerSearch": 50,
  "language": "en",
  "countryCode": "",
  "radiusKm": 5,
  "splitArea": true,
  "onlyInsideArea": true,
  "onlyWithWebsite": false,
  "onlyWithPhone": false,
  "skipClosedPlaces": true,
  "proxyConfiguration": {
    "useApifyProxy": true
  }
}
```

# Actor output Schema

## `places` (type: `string`):

All places collected during the run

## `summary` (type: `string`):

Per-search counts, proxy rung used and errors

# API

You can run this Actor programmatically using our API. Below are code examples in JavaScript, Python, and CLI, as well as the OpenAPI specification and MCP server setup.

## JavaScript example

```javascript
import { ApifyClient } from 'apify-client';

// Initialize the ApifyClient with your Apify API token
// Replace the '<YOUR_API_TOKEN>' with your token
const client = new ApifyClient({
    token: '<YOUR_API_TOKEN>',
});

// Prepare Actor input
const input = {
    "searchStrings": [
        "dentist"
    ],
    "location": "Austin, Texas",
    "maxItemsPerSearch": 50,
    "proxyConfiguration": {
        "useApifyProxy": true
    }
};

// Run the Actor and wait for it to finish
const run = await client.actor("fabrikit/google-maps-places-scraper").call(input);

// Fetch and print Actor results from the run's dataset (if any)
console.log('Results from dataset');
console.log(`💾 Check your data here: https://console.apify.com/storage/datasets/${run.defaultDatasetId}`);
const { items } = await client.dataset(run.defaultDatasetId).listItems();
items.forEach((item) => {
    console.dir(item);
});

// 📚 Want to learn more 📖? Go to → https://docs.apify.com/api/client/js/docs

```

## Python example

```python
from apify_client import ApifyClient

# Initialize the ApifyClient with your Apify API token
# Replace '<YOUR_API_TOKEN>' with your token.
client = ApifyClient("<YOUR_API_TOKEN>")

# Prepare the Actor input
run_input = {
    "searchStrings": ["dentist"],
    "location": "Austin, Texas",
    "maxItemsPerSearch": 50,
    "proxyConfiguration": { "useApifyProxy": True },
}

# Run the Actor and wait for it to finish
run = client.actor("fabrikit/google-maps-places-scraper").call(run_input=run_input)

# Fetch and print Actor results from the run's dataset (if there are any)
print(f"💾 Check your data here: https://console.apify.com/storage/datasets/{run.default_dataset_id}")
for item in client.dataset(run.default_dataset_id).iterate_items():
    print(item)

# 📚 Want to learn more 📖? Go to → https://docs.apify.com/api/client/python/docs/quick-start

```

## CLI example

```bash
echo '{
  "searchStrings": [
    "dentist"
  ],
  "location": "Austin, Texas",
  "maxItemsPerSearch": 50,
  "proxyConfiguration": {
    "useApifyProxy": true
  }
}' |
apify call fabrikit/google-maps-places-scraper --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,fabrikit/google-maps-places-scraper"
        }
    }
}
```

The hosted server signs you in with OAuth on first connect, so no API token belongs in this config. Clients without OAuth support can send an `Authorization: Bearer <APIFY_API_TOKEN>` header instead, using a token from API & Integrations in Apify Console (https://console.apify.com/settings/integrations).

## OpenAPI specification

Download the OpenAPI definition: https://api.apify.com/v2/actors/3YbRgTZL0mfzE1dDh/builds/lRIP1kgpkggouNHKl/openapi.json
