# Google Maps Scraper — Leads, Contacts, Emails & Social Profiles (`ntriqpro/google-maps-scraper-leads`) Actor

Google Maps scraper for lead generation: search any category and city, get places with phone, website, verified emails, social profiles and newest reviews in one run. Layered add-ons, batch input, pay per event.

- **URL**: https://apify.com/ntriqpro/google-maps-scraper-leads.md
- **Developed by:** [daehwan kim](https://apify.com/ntriqpro) (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 $2.08 / 1,000 place scrapeds

This Actor is paid per event. You are not charged for the Apify platform usage, but only a fixed price for specific events.
Since this Actor supports Apify Store discounts, the price gets lower the higher subscription plan you have.

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 — Leads, Contacts, Emails & Social Profiles

**Give it a category and a city, get sales-ready leads in one run.** Every place comes with name,
address, phone, website, rating and map URL. Turn on the add-ons and the same run also reads each
business's own website for emails, phones and social links, **verifies every email** (syntax, MX
record, disposable domain), opens the **social profiles**, and pulls the **newest Google reviews**.
Batch input: any number of queries, Google Maps URLs or place IDs.

> This Actor is an **independent, unofficial tool**. It is **not affiliated with, endorsed by,
> or sponsored by** Google. It reads only **publicly accessible** Google Maps listings and the
> businesses' own public websites, without logging in. Its request logic was written with reference
> to the MIT-licensed [gosom/google-maps-scraper](https://github.com/gosom/google-maps-scraper);
> no third-party code is bundled. **You are responsible** for complying with the target sites' terms
> of service and with privacy law (GDPR, CCPA, PIPA and others) in your jurisdiction, and **you are the
> data controller** for any personal data (emails, phone numbers, reviewer names) returned by a run you
> start. Use the output for lawful purposes only.

### Who this is for

Lead-generation agencies, local-marketing teams, sales reps and researchers who need **contactable**
business lists — not just map pins. If you only need places, run it with the add-ons off and pay for
places only.

### What one run returns

| Row type | One row per | Fields |
|---|---|---|
| `place` | business | `title`, `address`, `phone`, `website`, `totalScore`, `reviewsCount`, `categoryName`, `url`, `placeId`, `contact` (emails, phones, social links), `filterApplied` |
| `email` | email found on the website | `email`, `verdict` (`deliverable`, `deliverable-role`, `disposable`, `no-mail-server`, `invalid-syntax`), `mxFound`, `mxHosts`, `roleBased`, `freeProvider`, `disposable` |
| `social` | social link found on the website | `platform`, `profileUrl`, `handle`, `pageTitle`, `statusCode` |
| `review` | newest Google review (optional) | `name`, `stars`, `text`, `publishedAtDate`, `isLocalGuide`, `reviewerNumberOfReviews` |

Google shows a logged-out client at most about 5 reviews per business; this Actor does not pretend
otherwise. Reviews are off by default (`maxReviewsPerPlace: 0`).

### Pricing (pay per event)

| Event | Charged per | USD (FREE plan; paid plans get 20–48% off) |
|---|---|---|
| `apify-actor-start` | run | 0.005 |
| `place-scraped` | place row | 0.004 |
| `filter-applied` | place kept, when any filter is on | 0.001 |
| `contact-details-scraped` | place whose website was read | 0.003 |
| `lead-email-verified` | email row | 0.003 |
| `social-profile-scraped` | social row | 0.004 |
| `review-scraped` | review row | 0.0005 |
| `cross-platform-review-scraped` | App Store / Google Play review row | 0.0003 |

**Example:** 100 dentists in Austin with contacts and email verification, about 60 of them with a
website and 1.5 emails each: 100 places $0.40 + 60 contacts $0.18 + 90 emails $0.27 + start $0.005
\= **about $0.86**. A places-only run of the same 100 businesses is $0.405.

Every row written to the dataset is charged, whatever the target site answered. A place that fails a
filter is not delivered and not charged. Notice rows (`noticeCode`) are messages, never charged.

### Input

```json
{
  "queries": ["dentist, Austin TX", "https://www.google.com/maps/place/..."],
  "maxPlacesPerQuery": 20,
  "minRating": 4,
  "requireWebsite": true,
  "includeContactDetails": true,
  "verifyEmails": true,
  "scrapeSocialProfiles": true,
  "maxReviewsPerPlace": 0,
  "proxyConfiguration": { "useApifyProxy": true }
}
```

- `queries` — array (required). Search phrases, Maps URLs, place IDs, or "name, city".
- Filters — `minRating`, `requireWebsite`, `requirePhone`.
- Add-ons — `includeContactDetails`, `verifyEmails`, `scrapeSocialProfiles`, `maxReviewsPerPlace`, `crossPlatforms`.
- Free Apify plans receive the first 25 result rows per run; paid plans receive the full result set.

### Output example

```json
{ "rowType": "place", "title": "Bright Smile Dental", "phone": "+1 512-555-0100", "website": "https://brightsmile.example",
  "totalScore": 4.8, "reviewsCount": 312, "categoryName": "Dentist", "contact": { "emails": ["info@brightsmile.example"], "social": { "instagram": "https://instagram.com/brightsmile" } } }
{ "rowType": "email", "title": "Bright Smile Dental", "email": "info@brightsmile.example", "verdict": "deliverable-role", "mxFound": true, "roleBased": true }
{ "rowType": "social", "title": "Bright Smile Dental", "platform": "instagram", "handle": "brightsmile", "statusCode": 200 }
```

### Runs on the Apify platform

Schedule it, call it from the API, or use it in a workflow. Datacenter proxy is enough for Google
Maps; residential proxy is rarely needed. Runs are headless Chromium; 4 GB memory is recommended.

If this Actor saved you time, a sentence about what you used it for helps the next person decide.

### Leave a review

A short review on the **Reviews** tab, good or bad, helps other people find this Actor and tells us what to build next. Found a bug or need a feature? Open an issue on the **Issues** tab and we'll look into it.

# Actor input Schema

## `queries` (type: `array`):

One or more Google Maps search queries, Google Maps URLs, place IDs, or "business name, city" strings. At least one is required.

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

Apify-standard list of Google Maps URLs to start from, as an alternative or addition to queries.

## `maxPlacesPerQuery` (type: `integer`):

Maximum number of Google Maps businesses to collect for each query.

## `minRating` (type: `integer`):

Keep only places rated at least this (0 = no filter). Any active filter charges `filter-applied` once per place kept.

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

Keep only places that list a website (best for email leads).

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

Keep only places that list a phone number.

## `includeContactDetails` (type: `boolean`):

Read each business's own website for publicly listed emails, phones and social links. Paid add-on `contact-details-scraped` per place with a website.

## `verifyEmails` (type: `boolean`):

Syntax, MX record and disposable-domain check for every email found. Paid add-on `lead-email-verified` per email.

## `scrapeSocialProfiles` (type: `boolean`):

Open each social link found on the website (Facebook, Instagram, LinkedIn, X, YouTube, TikTok) and return one row per profile with handle and page title. Paid add-on `social-profile-scraped` per profile.

## `maxReviewsPerPlace` (type: `integer`):

Newest Google reviews per place (0 = skip reviews; Google shows at most 5 per place to a logged-out client). Each review row is a paid `review-scraped` event.

## `reviewsSort` (type: `string`):

Order in which Google Maps reviews are fetched. Use Newest together with sinceTimestamp for incremental runs.

## `sinceTimestamp` (type: `string`):

ISO-8601 timestamp (for example 2026-08-01T00:00:00Z) or a Unix epoch. Only reviews published after this point are returned and charged, so a daily or weekly re-run costs a fraction of a full run. Google Maps publishes a relative age ("3 months ago"), so the cutoff is applied to an approximate date.

## `negativeReviewAlert` (type: `integer`):

Set to 2, for example, to return only 1- and 2-star reviews. Combine with sinceTimestamp and a webhook to get an alert whenever a new bad review appears. Leave empty to return every review.

## `crossPlatforms` (type: `array`):

Additional review sources to check for the same business, matched by business name. Trustpilot and Tripadvisor sit behind bot-challenge walls (403) and return a notice row instead of reviews; they are off by default.

## `maxReviewsPerPlatform` (type: `integer`):

Maximum number of reviews to collect per business on each enabled cross-platform source.

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

Language code used to request results (for example en, ko, es).

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

Two-letter country code used to bias search results (for example us, kr, gb).

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

Apify Proxy settings. Datacenter proxy is the default and is what we recommend; residential proxy costs far more per gigabyte and is rarely needed for Google Maps.

## `browserConcurrency` (type: `integer`):

How many business pages the single browser opens at once. Higher is faster but uses more memory.

## Actor input object example

```json
{
  "queries": [
    "dentist, Austin TX"
  ],
  "startUrls": [],
  "maxPlacesPerQuery": 20,
  "includeContactDetails": true,
  "verifyEmails": true,
  "reviewsSort": "newest",
  "crossPlatforms": [
    "appstore",
    "googleplay"
  ],
  "maxReviewsPerPlatform": 50,
  "language": "en",
  "countryCode": "us",
  "proxyConfiguration": {
    "useApifyProxy": true,
    "apifyProxyGroups": []
  },
  "browserConcurrency": 3
}
```

# Actor output Schema

## `dataset` (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 = {
    "queries": [
        "dentist, Austin TX"
    ],
    "startUrls": [],
    "maxPlacesPerQuery": 20,
    "minRating": 0,
    "requireWebsite": false,
    "requirePhone": false,
    "includeContactDetails": true,
    "verifyEmails": true,
    "scrapeSocialProfiles": false,
    "maxReviewsPerPlace": 0,
    "reviewsSort": "newest",
    "crossPlatforms": [
        "appstore",
        "googleplay"
    ],
    "maxReviewsPerPlatform": 50,
    "language": "en",
    "countryCode": "us",
    "proxyConfiguration": {
        "useApifyProxy": true,
        "apifyProxyGroups": []
    },
    "browserConcurrency": 3
};

// Run the Actor and wait for it to finish
const run = await client.actor("ntriqpro/google-maps-scraper-leads").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 = {
    "queries": ["dentist, Austin TX"],
    "startUrls": [],
    "maxPlacesPerQuery": 20,
    "minRating": 0,
    "requireWebsite": False,
    "requirePhone": False,
    "includeContactDetails": True,
    "verifyEmails": True,
    "scrapeSocialProfiles": False,
    "maxReviewsPerPlace": 0,
    "reviewsSort": "newest",
    "crossPlatforms": [
        "appstore",
        "googleplay",
    ],
    "maxReviewsPerPlatform": 50,
    "language": "en",
    "countryCode": "us",
    "proxyConfiguration": {
        "useApifyProxy": True,
        "apifyProxyGroups": [],
    },
    "browserConcurrency": 3,
}

# Run the Actor and wait for it to finish
run = client.actor("ntriqpro/google-maps-scraper-leads").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 '{
  "queries": [
    "dentist, Austin TX"
  ],
  "startUrls": [],
  "maxPlacesPerQuery": 20,
  "minRating": 0,
  "requireWebsite": false,
  "requirePhone": false,
  "includeContactDetails": true,
  "verifyEmails": true,
  "scrapeSocialProfiles": false,
  "maxReviewsPerPlace": 0,
  "reviewsSort": "newest",
  "crossPlatforms": [
    "appstore",
    "googleplay"
  ],
  "maxReviewsPerPlatform": 50,
  "language": "en",
  "countryCode": "us",
  "proxyConfiguration": {
    "useApifyProxy": true,
    "apifyProxyGroups": []
  },
  "browserConcurrency": 3
}' |
apify call ntriqpro/google-maps-scraper-leads --silent --output-dataset

```

## MCP server setup

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

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/5VN1lTWevFvULUZY5/builds/CfZKhL7iaX5Rojmug/openapi.json
