# Google Maps Extractor - Business Leads, Phones & Websites (`tenfoldfleet/google-maps-extractor`) Actor

Extract business leads from Google Maps for any search and location: name, phone, website, address, rating, reviews, categories, opening hours and coordinates. An optional website visit adds emails and social media links. $1 per 1,000 places; filters, empty searches and failures are free.

- **URL**: https://apify.com/tenfoldfleet/google-maps-extractor.md
- **Developed by:** [Tenfold Fleet](https://apify.com/tenfoldfleet) (community)
- **Categories:** Lead generation, 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 places

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

### What does Google Maps Extractor do?

**Google Maps Extractor** turns a Google Maps search into a **B2B lead list**. Type what you sell to (`dentist`, `roofing contractor`, `coffee shop`) and where (`Austin, TX`, `Manchester, UK`, a zip code), and it returns every business Google lists for that search: **name, phone number, website, full address, rating, review count, categories, opening hours, coordinates** and a **Google Maps link**. Turn on one switch and it also visits each business website to collect **emails** and **social profiles** (Facebook, Instagram, LinkedIn, X, YouTube, TikTok).

It reads [Google Maps](https://www.google.com/maps) search results directly over HTTP, without a browser, so 1,000 places come back in minutes, not hours. Use it in the Apify Console, or call it as a **Google Maps leads API** from your code, Make, Zapier, n8n or an AI agent.

> Not affiliated with, endorsed by or sponsored by Google. Google Maps is a trademark of Google LLC.

### Why use this Google Maps extractor?

- 📇 **Sales prospecting**: build a call or email list of every plumber, clinic or agency in a city, with phone numbers in international format.
- 📧 **Cold email lists**: with website enrichment on, get emails and social links next to each business, ready for your CRM.
- 🏪 **Local market research**: count competitors per area, compare ratings and reviews, and map them by coordinates.
- 🔎 **Deep result lists**: up to about 250-300 places per search in a big city, read 100 at a time.
- 🧹 **Clean data, no double billing**: a business that shows up in several of your searches is returned and charged **once**.
- 💸 **Filters are free**: minimum rating, minimum reviews, "has a phone", "has a website" and "skip closed" cost nothing extra; places that don't pass are simply not charged.

Looking only for businesses that have **no website** (prospects for web designers)? See [Businesses Without Websites](https://apify.com/tenfoldfleet/businesses-without-websites), which returns just those leads.

### What data can it extract?

| Field | Example |
|---|---|
| `name` | `ATX Family Dental` |
| `primaryCategory`, `categories` | `Dentist`, `["Dentist", "Cosmetic dentist", ...]` |
| `phone` / `phoneFormatted` | `+15127173147` / `(512) 717-3147` |
| `website` / `domain` | `https://www.atxfamilydental.com/` / `atxfamilydental.com` (tracking parameters removed) |
| `address`, `street`, `neighborhood`, `city`, `postalCode`, `state`, `countryCode` | `1700 S 1st St, Austin, TX 78704`, ... `Texas`, `US` |
| `rating` / `reviewCount` | `4.9` / `917` |
| `latitude` / `longitude` | `30.2482` / `-97.7560` |
| `openingHours` | `[{"day": "Monday", "hours": "8 AM-5 PM"}, ...]` |
| `timezone` | `America/Chicago` |
| `businessStatus` | `open`, `temporarily closed` or `permanently closed` |
| `placeId`, `cid`, `googleMapsUrl` | `ChIJb5gBC-u0RIYRHkntaUcdJGs`, `7720327853776914718`, link |
| `searchQuery`, `location`, `rankInSearch` | `dentist`, `Austin, TX`, `1` (position in Google's list) |
| `emails` (enrichment) | `["info@atxfamilydental.com"]` |
| `socialProfiles` (enrichment) | `{"facebook": "...", "instagram": "...", "linkedin": null, ...}` |
| `contactPageUrl` (enrichment) | `https://www.atxfamilydental.com/contact/` |

### How to extract leads from Google Maps

1. Click **Try for free** (or **Start**) on this page.
2. In **What to search for**, add one or more business types, e.g. `dentist`, `orthodontist`.
3. In **Where to search**, add cities, regions or zip codes, e.g. `Austin, TX`, `78704`. Every query is searched in every location.
4. Set **Max places per search** and any filters (rating, reviews, phone, website).
5. Optional: turn on **Find emails and social profiles on each website**.
6. Click **Start**. When the run finishes, download the places as **JSON, CSV, Excel or HTML**, or read them through the Apify API.

### How much does it cost?

This Actor uses pay-per-event pricing, the same on every Apify plan:

| Event | Price |
|---|---|
| Place (one unique business) | **$1 per 1,000 places** ($0.001 each) |
| Website contacts (only when enrichment is on **and** an email or social profile is found) | **$1.50 per 1,000** ($0.0015 each) |
| Run start | $0.00005 per run |

**Free of charge:** places removed by your filters, duplicates across your searches, searches with no results, searches Google blocks, websites that fail to load and websites where nothing is found.

Examples: 2,000 dentists across 15 zip codes cost about **$2**. The same 2,000 with enrichment, where about 1,500 websites show an email or social profile, cost about **$4.25**. On the Apify free plan, the $5 monthly credit covers about 4,900 places. Set a **maximum cost per run** and the Actor stops when it reaches it.

### Input

```json
{
    "searchQueries": ["dentist", "orthodontist"],
    "locations": ["Austin, TX", "Round Rock, TX"],
    "maxPlacesPerSearch": 100,
    "minRating": "4",
    "minReviews": 10,
    "requirePhone": true,
    "skipClosed": true,
    "enrichContacts": true,
    "language": "en",
    "country": "us"
}
```

### Output

Each place is one row. You can download the dataset as **JSON, CSV, Excel, XML or HTML**.

```json
{
    "placeId": "ChIJb5gBC-u0RIYRHkntaUcdJGs",
    "cid": "7720327853776914718",
    "name": "ATX Family Dental",
    "primaryCategory": "Dentist",
    "categories": ["Dentist", "Cosmetic dentist", "Dental clinic", "Emergency dental service", "Pediatric dentist", "Teeth whitening service"],
    "address": "1700 S 1st St, Austin, TX 78704",
    "street": "1700 S 1st St",
    "neighborhood": "Bouldin Creek",
    "city": "Austin",
    "postalCode": "78704",
    "state": "Texas",
    "countryCode": "US",
    "phone": "+15127173147",
    "phoneFormatted": "(512) 717-3147",
    "website": "https://www.atxfamilydental.com/",
    "domain": "atxfamilydental.com",
    "rating": 4.9,
    "reviewCount": 917,
    "latitude": 30.2482229,
    "longitude": -97.7559705,
    "openingHours": [{ "day": "Monday", "hours": "8 AM-5 PM" }, { "day": "Saturday", "hours": "Closed" }],
    "timezone": "America/Chicago",
    "businessStatus": "open",
    "googleMapsUrl": "https://www.google.com/maps/search/?api=1&query=ATX%20Family%20Dental&query_place_id=ChIJb5gBC-u0RIYRHkntaUcdJGs",
    "emails": ["info@atxfamilydental.com"],
    "socialProfiles": { "facebook": null, "instagram": "https://www.instagram.com/atxfamilydental", "linkedin": null, "x": null, "youtube": null, "tiktok": null },
    "contactPageUrl": "https://www.atxfamilydental.com/contact/",
    "searchQuery": "dentist",
    "location": "Austin, TX",
    "rankInSearch": 2,
    "scrapedAt": "2026-10-20T09:42:11.188Z"
}
```

A search that finds nothing, or that Google blocks, adds one free row with an `error` field, so you can see which searches to retry.

### Tips

- **Google ends a search after about 250-300 places** (fewer in small towns). For a big city, search by zip code or neighborhood (`dentist` in `78701`, `78702`, ...). Duplicates between neighboring areas are removed and never charged twice.
- Put the place in **Where to search**, not only in the query. Without a place, Google answers with businesses near the server, in the USA.
- Use the **language** setting for category names and opening hours in another language (`de`, `fr`, `es`), and **country** for the Google region (`gb`, `de`, `au`).
- Website enrichment visits the homepage and up to 2 contact or about pages, with a 10-second limit per page. It is slower than a plain run; start with a small search to check the results.
- `rankInSearch` is the place's position in Google's list for that search, useful for local SEO checks.

### FAQ

#### Do I need a Google account, an API key or cookies?

No. The Actor reads public Google Maps search results and needs no login or API key.

#### Why did I get fewer places than I asked for?

Google ends a search after about 250-300 places (often fewer outside big cities), and your filters, closed businesses and duplicates from your other searches are removed. Split the area into smaller locations to get more.

#### Which countries work?

Any country Google Maps covers. Write the location with the country (`Lyon, France`) and set **language** and **country** if you want local category names.

#### When is the website contacts fee charged?

Only when enrichment is on, the website loads, and at least one email or social profile is found. Businesses without a website, websites that fail and websites with nothing on them are free.

#### Can I get reviews or photos?

No. This Actor returns business details and contacts for lead lists, not review texts or photos.

### Disclaimer

This Actor collects business information that companies publish on Google Maps and on their own websites. Emails of named people (for example `jane@business.com`) can still be personal data under the **GDPR**, the UK GDPR, the CCPA and similar laws. You are responsible for having a lawful basis such as legitimate interest, honouring opt-outs and do-not-call lists, and following the marketing rules of your country (for example PECR, CAN-SPAM, TCPA). Use the data in line with Google's terms and the laws that apply to you.

# Actor input Schema

## `searchQueries` (type: `array`):

Business types or keywords, as you would type them into Google Maps: "dentist", "plumber", "coffee shop", "car dealer". Every query is searched in every location below.

## `locations` (type: `array`):

Cities, regions or zip codes, e.g. "Austin, TX", "Manchester, UK", "10115 Berlin" or "78704". The search sent to Google is "<query> in <location>". Leave it empty only if your queries already name the place ("dentist in Austin, TX"); otherwise Google returns places near the server, in the USA. Google lists up to about 250-300 places per search, so split a big city into zip codes or neighborhoods to get more.

## `maxPlacesPerSearch` (type: `integer`):

How many places to return for each query + location pair. Google itself ends a search after about 250-300 places, fewer in small towns.

## `maxItems` (type: `integer`):

Stop after this many places across all searches (0 = no limit). You can also cap the cost with the run's maximum charge. On the Apify free plan, the $5 monthly credit covers about 4,900 places.

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

Language of category names and opening hours, as a code: en, de, fr, es, pt-BR, ...

## `country` (type: `string`):

Two-letter country code that Google uses as the search region: us, gb, de, ca, au, ... The location text decides where results come from; this only fine-tunes it.

## `minRating` (type: `string`):

Only places with at least this Google rating. Filters are free: places that don't pass are skipped and never charged.

## `minReviews` (type: `integer`):

Only places with at least this many Google reviews (0 = any).

## `requirePhone` (type: `boolean`):

Skip places without a phone number on Google Maps.

## `requireWebsite` (type: `boolean`):

Skip places without a website on Google Maps.

## `skipClosed` (type: `boolean`):

Skip places that Google marks as permanently or temporarily closed.

## `enrichContacts` (type: `boolean`):

Visit each business website (homepage plus up to 2 contact pages) and add emails, Facebook, Instagram, LinkedIn, X, YouTube and TikTok links. The contact fee is charged only for places where at least one email or social profile is found. Makes the run slower.

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

The default (Apify datacenter proxy, US) works. If Google blocks a request, the actor retries on a new IP and then through residential proxy at no extra cost to you.

## Actor input object example

```json
{
  "searchQueries": [
    "dentist"
  ],
  "locations": [
    "Austin, TX"
  ],
  "maxPlacesPerSearch": 20,
  "maxItems": 0,
  "language": "en",
  "country": "us",
  "minRating": "0",
  "minReviews": 0,
  "requirePhone": false,
  "requireWebsite": false,
  "skipClosed": true,
  "enrichContacts": false,
  "proxyConfiguration": {
    "useApifyProxy": true,
    "apifyProxyCountry": "US"
  }
}
```

# Actor output Schema

## `results` (type: `string`):

No description

# 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 = {
    "searchQueries": [
        "dentist"
    ],
    "locations": [
        "Austin, TX"
    ],
    "maxPlacesPerSearch": 20,
    "proxyConfiguration": {
        "useApifyProxy": true,
        "apifyProxyCountry": "US"
    }
};

// Run the Actor and wait for it to finish
const run = await client.actor("tenfoldfleet/google-maps-extractor").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 = {
    "searchQueries": ["dentist"],
    "locations": ["Austin, TX"],
    "maxPlacesPerSearch": 20,
    "proxyConfiguration": {
        "useApifyProxy": True,
        "apifyProxyCountry": "US",
    },
}

# Run the Actor and wait for it to finish
run = client.actor("tenfoldfleet/google-maps-extractor").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 '{
  "searchQueries": [
    "dentist"
  ],
  "locations": [
    "Austin, TX"
  ],
  "maxPlacesPerSearch": 20,
  "proxyConfiguration": {
    "useApifyProxy": true,
    "apifyProxyCountry": "US"
  }
}' |
apify call tenfoldfleet/google-maps-extractor --silent --output-dataset

```

## MCP server setup

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

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/YdVV43RodzfIg5IEZ/builds/E1AYzYGBm9XlkgPnY/openapi.json
