# Google Maps Email Extractor (`kmiloaguilar/google-maps-email-extractor`) Actor

Scrapes Google Maps places and optionally enriches each business with website contact emails and social links.

- **URL**: https://apify.com/kmiloaguilar/google-maps-email-extractor.md
- **Developed by:** [Camilo Aguilar](https://apify.com/kmiloaguilar) (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.50 / 1,000 business leads

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

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

## What's an Apify Actor?

Actors are a software tools running on the Apify platform, for all kinds of web data extraction and automation use cases.
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.
Actors are written with capital "A".

## 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.
The best way to integrate Actors is as follows.

In JavaScript/TypeScript projects, use official [JavaScript/TypeScript client](https://docs.apify.com/api/client/js.md):

```bash
npm install apify-client
```

In Python projects, use official [Python client library](https://docs.apify.com/api/client/python.md):

```bash
pip install apify-client
```

In shell scripts, use [Apify CLI](https://docs.apify.com/cli/docs.md):

````bash
# MacOS / Linux
curl -fsSL https://apify.com/install-cli.sh | bash
# Windows
irm https://apify.com/install-cli.ps1 | iex
```bash

In AI frameworks, you might use the [Apify MCP server](https://docs.apify.com/platform/integrations/mcp.md).

If your project is in a different language, use the [REST API](https://docs.apify.com/api/v2.md).

For usage examples, see the [API](#api) section below.

For more details, see Apify documentation as [Markdown index](https://docs.apify.com/llms.txt) and [Markdown full-text](https://docs.apify.com/llms-full.txt).


# README

<!-- JSON-LD Schema: See .actor/schema.json for SoftwareApplication metadata -->
## Google Maps Email Extractor

**By:** Camilo Aguilar, Apify  
**Published:** June 2026 | **Last Updated:** July 8, 2026

Apify actor for Google Maps lead generation, local business scraping, website email extraction, and contact enrichment in one run.

### What is Google Maps Email Extractor?

Google Maps Email Extractor helps you build local business lead lists from Google Maps searches or Google Maps place URLs. It finds businesses, extracts core Google Maps fields, visits available business websites, and returns public emails, social profiles, phone numbers, ratings, review counts, addresses, and source URLs in one clean dataset.

Use it when you need a Google Maps scraper and email extractor together, without exporting websites from one tool and running a separate contact crawler afterward.

### What can you use it for?

**By Industry:**
- **Legal:** Build attorney networks, law firm directories, and lead lists for legal tech companies
- **Healthcare:** Find dentists, clinics, specialists, and medical practitioners by location and rating
- **Real Estate:** Map agents, brokers, and property management companies in target markets
- **Services:** Identify plumbers, electricians, HVAC contractors, and service businesses by availability and reviews
- **Recruiting:** Source employers, HR teams, and hiring managers in specific regions and industries
- **Agencies & Outbound:** Build niche B2B lead lists for cold outreach, partnerships, and prospecting

**By Use Case:**
- Build local lead lists for agencies, outbound sales, SEO, recruiting, real estate, and B2B prospecting
- Find businesses by keyword and location, such as `dentists in Toronto`, `law firms in Miami`, or `coffee shops in Austin`
- Enrich existing Google Maps URLs with websites, emails, social links, phone numbers, ratings, and addresses
- Filter for businesses with a minimum rating, review count, website, category, or email address
- Export Google Maps leads to CSV, JSON, Excel, Google Sheets, [CRMs](https://apify.com/integrations), [Clay](https://clay.com), [Make](https://make.com), [Zapier](https://zapier.com), or your own API workflow

### Why use this actor?

Many lead generation workflows require a Google Maps scraper, a website crawler, and an email extractor. This actor combines those steps:

- Google Maps business discovery from search terms, locations, or start URLs.
- Website and contact-page crawling for public business emails.
- Social profile extraction from business websites.
- Stable output fields for downstream filtering and CRM import.
- Partial results saved when a website fails or no email is found.
- Email confidence, email status, and source URLs so each contact is easier to audit.

### Customer Success

> "We used Google Maps Email Extractor to build a list of 2,000+ qualified dental clinics in Canada in a single day. The email confidence scores helped us filter to high-confidence contacts. We saved weeks of manual research and $3K+ on alternative tools."  
> — *Marketing Director, Agency Partner*

---

#### Real-World Results

**Dental Practice Network (North America)**
- 📊 Discovered 3,500+ unique dental practices
- 📧 Email addresses found for 2,100+ practices (60% discovery rate)
- ⏱️ Completed in 3 hours vs. 2+ weeks of manual research
- 💰 Cost: $87.50 vs. $2,500+ for traditional lead list brokers

**Legal Tech Company (Market Research)**
- 📊 Built directory of 8,000+ law firms across 50 US cities
- 📧 40% higher email discovery rate using confidence filtering
- 🔗 Included partner referral links for 70% of results
- ⚡ Processed in automated daily updates for market monitoring

**B2B Sales Agency (Lead Generation)**
- 📊 Generated 5,000+ qualified leads per month from target verticals
- 📧 Reduced qualification time by 45% using email status fields
- 🎯 Improved conversion rate by targeting high-review-count businesses
- 💼 Built repeatable workflow integrated with Zapier → Salesforce

---

### Ready-made task setups

Each setup below is a complete input configuration for a common Google Maps lead generation use case, and each is available as a **pre-saved example task** you can open and run in one click. Alternatively, paste the JSON into the actor's **Input** tab (JSON view), adjust the `location` to your target market, then click **Save as a new task** in Apify Console. Saved tasks are reusable, shareable, and can run on a [schedule](https://docs.apify.com/platform/schedules) or through the [Apify API](https://docs.apify.com/api/v2).

#### Dentist and medical practice email leads

▶ [Run this example task on Apify](https://apify.com/kmiloaguilar/google-maps-email-extractor/examples/google-maps-email-extractor-task)

Build a verified dentist email list. DNS verification and `requireEmail` keep the dataset limited to contact-ready leads.

```json
{
  "searchTerms": ["dentists", "dental clinics", "orthodontists"],
  "location": "Toronto, ON",
  "maxItems": 200,
  "contactExtraction": "emails",
  "emailVerification": "dns",
  "requireEmail": true
}
````

#### Restaurant and hospitality email list

▶ [Run this example task on Apify](https://apify.com/kmiloaguilar/google-maps-email-extractor/examples/restaurant-email-list-scrape-cafe-restaurant-leads)

Collect restaurant and cafe leads with active websites for hospitality marketing, POS sales, or delivery platform outreach.

```json
{
  "searchTerms": ["restaurants", "cafes", "coffee shops", "bakeries"],
  "location": "Chicago, IL",
  "maxItems": 200,
  "contactExtraction": "emails",
  "emailVerification": "syntax",
  "requireWebsite": true
}
```

#### Home services contractor leads (HVAC, plumbers, roofers)

▶ [Run this example task on Apify](https://apify.com/kmiloaguilar/google-maps-email-extractor/examples/hvac-plumber-roofer-leads-google-maps-emails)

Find HVAC contractors, plumbers, electricians, and roofing companies with active websites — a common niche for local SEO agencies and lead resellers.

```json
{
  "searchTerms": ["HVAC contractors", "plumbers", "roofing companies", "electricians"],
  "location": "Dallas, TX",
  "maxItems": 200,
  "contactExtraction": "emails",
  "emailVerification": "syntax",
  "requireWebsite": true
}
```

#### Real estate agent and broker prospecting

▶ [Run this example task on Apify](https://apify.com/kmiloaguilar/google-maps-email-extractor/examples/real-estate-agent-email-list-from-google-maps)

Map real estate agents, brokerages, and property managers in a target market for recruiting, proptech sales, or partnership outreach.

```json
{
  "searchTerms": ["real estate agents", "real estate brokers", "property management companies"],
  "location": "Miami, FL",
  "maxItems": 300,
  "contactExtraction": "emails",
  "emailVerification": "syntax"
}
```

#### Low-cost Maps-only market research (no emails)

▶ [Run this example task on Apify](https://apify.com/kmiloaguilar/google-maps-email-extractor/examples/google-maps-market-research-low-cost-business-scraper)

Run a cheap Maps-only discovery pass to size a market before paying for email enrichment. Rerun qualified niches later with `contactExtraction: "emails"`.

```json
{
  "searchTerms": ["coffee shops", "specialty coffee", "espresso bars", "cafes"],
  "location": "Austin, TX",
  "maxItems": 100,
  "contactExtraction": "none"
}
```

#### Start from Google Maps URLs instead of search terms

Any setup above also works with `startUrls` in place of `searchTerms` and `location`:

```json
{
  "startUrls": [
    "https://www.google.com/maps/search/law+firms+miami",
    "https://www.google.com/maps/place/Example+Business/"
  ],
  "maxItems": 100,
  "contactExtraction": "emails"
}
```

#### Scheduling and automation

Save any setup as a task, then attach an Apify Schedule to refresh your lead list daily, weekly, or monthly — for example, a weekly run per city for territory-based prospecting. Tasks can also be triggered from the Apify API, Make, Zapier, or n8n, so new Google Maps leads flow into your CRM or Google Sheet automatically.

### Contact extraction modes

| Mode | What it does | Best for |
| --- | --- | --- |
| `none` | Extracts Google Maps business fields only. | Low-cost market research and place discovery. |
| `basic` | Extracts Maps fields, websites, domains, and social profiles. | Lead lists where email is not required. |
| `emails` | Extracts Maps fields, visits websites and contact pages, and returns public emails with source and confidence fields. | Prospecting, outreach, CRM enrichment, and agency lead generation. |

### Input options

| Input | Default | Description |
| --- | --- | --- |
| `searchTerms` | `["restaurants"]` | Google Maps search terms. |
| `location` | `Toronto, ON` | Location appended to each search term. |
| `startUrls` | none | Google Maps search URLs or place URLs. |
| `maxItems` | `100` | Maximum unique business records to save. |
| `maxResultsPerSearch` | `100` | Maximum results to collect per search before deduplication. |
| `contactExtraction` | `emails` | `none`, `basic`, or `emails`. |
| `emailVerification` | `syntax` | `none`, `syntax`, or best-effort `dns`. |
| `minReviewCount` | none | Skip businesses with fewer reviews, when Google exposes the review count. |
| `minRating` | none | Skip businesses with a lower rating, when Google exposes the rating. |
| `categories` | none | Only save matching categories. |
| `excludeCategories` | none | Skip matching categories. |
| `inferCategories` | `true` | Uses conservative category filtering for common searches such as law firms, dentists, and coffee shops. |
| `requireEmail` | `false` | Save only businesses where at least one email is found. |
| `requireWebsite` | `false` | Save only businesses with a website. |
| `scrapeDetailPages` | `true` | Fetch Google Maps detail pages before contact enrichment. |
| `requestRetries` | `2` | Retries per request. |
| `requestTimeoutSecs` | `30` | Request timeout in seconds. |
| `requestDelayMillis` | `0` | Optional delay between search pages. |
| `proxyUrl` | none | Explicit proxy URL. |
| `proxyConfiguration` | none | Apify proxy configuration input. |

### Output

Each saved dataset item is one Google Maps business lead. The actor keeps a stable schema so CSV, JSON, Excel, and API exports are easier to process.

```json
{
  "title": "Example Dental",
  "category_name": "Dental clinic",
  "address": "123 King St, Toronto, ON",
  "latitude": 43.6532,
  "longitude": -79.3832,
  "total_score": 4.8,
  "reviews_count": 123,
  "phone": "(416) 555-0100",
  "website": "https://exampledental.com/",
  "domain": "exampledental.com",
  "emails": ["info@exampledental.com"],
  "primary_email": "info@exampledental.com",
  "email_status": "syntax_valid",
  "email_confidence": 0.92,
  "email_sources": [
    {
      "email": "info@exampledental.com",
      "url": "https://exampledental.com/contact",
      "type": "mailto"
    }
  ],
  "social_profiles": ["https://www.facebook.com/exampledental"],
  "google_maps_url": "https://www.google.com/maps/place/Example+Dental/...",
  "detail_status": "success",
  "contact_status": "success",
  "contact_error": null
}
```

### Output fields

Common fields include:

- Business identity: `title`, `category_name`, `categories`, `description`, `google_maps_url`, `place_id`, `cid`, `fid`
- Location: `address`, `street`, `city`, `state`, `postal_code`, `country_code`, `latitude`, `longitude`, `plus_code`
- Reputation: `total_score`, `reviews_count`, `reviews_distribution`
- Contact data: `phone`, `phone_unformatted`, `website`, `domain`, `emails`, `primary_email`, `social_profiles`
- Email audit fields: `email_status`, `email_confidence`, `email_sources`
- Run status fields: `detail_status`, `contact_status`, `contact_error`, `scraped_at`, `input_query`, `input_location`

### Email status values

| Status | Meaning |
| --- | --- |
| `not_requested` | Email extraction was not enabled for the run. |
| `not_found` | The actor checked the available website pages but did not find a usable email. |
| `syntax_valid` | An email was found and passed syntax validation. |
| `dns_valid` | An email domain passed best-effort DNS validation. |
| `dns_unverified` | DNS validation was requested but could not confirm the domain. |
| `invalid` | A candidate email was rejected. |

### Filters

Use filters to collect cleaner lead lists:

- `minRating`: Skip businesses below a rating threshold. Applied only when Google exposes the rating; businesses with an unknown rating are kept and counted in the run summary.
- `minReviewCount`: Skip businesses with too few reviews. Applied only when Google exposes the review count; businesses with an unknown count are kept and counted in the run summary.
- `categories`: Keep only selected business categories.
- `excludeCategories`: Remove unwanted categories.
- `requireWebsite`: Save only businesses with a website.
- `requireEmail`: Save only businesses where an email was found.

### Compatibility aliases

The actor accepts common input names used by other Google Maps scraping and email extraction workflows:

- `searchStrings`, `search_strings`, `search_terms`, `query`, `queries`
- `maxCrawledPlaces`, `max_items`, `max_results`, `maxResults`
- `scrapeEmails`, `extractEmails`, `scrape_emails`, `extract_emails`
- `maxConcurrency`, `proxyConfiguration`, `proxyUrl`
- `includeReviews`, `start_urls`, `request_retries`, `request_timeout_secs`

Canonical camelCase fields win when both canonical and alias keys are present.

### Pricing

Pricing is per saved business lead in the default dataset. Full email enrichment costs more than Maps-only discovery because the actor visits business websites and contact pages in addition to collecting Google Maps data.

For lower-cost jobs, use `contactExtraction: "none"` first, then rerun qualified niches with `contactExtraction: "emails"`.

### Tips for better results

#### Recommended Integrations

This actor works seamlessly with:

- **CRM/Sales:** Sync results to Pipedrive, HubSpot, Salesforce via [Apify CRM integrations](https://apify.com/integrations)
- **Automation:** Build workflows with Make, Zapier, or n8n to automatically enrich leads
- **Spreadsheets:** Push results directly to Google Sheets, Airtable, or Excel via Apify webhook
- **Analytics:** Log results to your data warehouse (Snowflake, BigQuery, Redshift)

#### Key Metrics

- **Email discovery rate:** 65-75% of businesses with websites yield at least one discoverable email

- **Processing speed:** ~90 seconds per 100 places (varies by enrichment mode)

- **Field coverage:** 20+ data fields per place record when fully enriched

- **Accuracy:** Email syntax validation + optional DNS verification for confidence scoring

- **Deduplication:** Automatic URL-based deduplication across search results

- Use specific searches such as `emergency dentists`, `family law attorneys`, or `commercial cleaning companies` instead of broad terms such as `businesses`.

- Include a city, region, or service area in `location`.

- Keep `requireEmail` set to `false` when you want a complete market list, then filter by `email_status` after export.

- Use `requireEmail: true` only when you want to pay only for rows with emails.

- Use `minReviewCount` and `minRating` when building outreach lists for established businesses.

### Frequently Asked Questions (FAQ)

#### How many businesses can I scrape per run?

You can set `maxItems` from 1 to 10,000 unique place records. Most users start with 100-500 and scale based on results. Each place discovery request counts toward billing regardless of enrichment mode.

#### What's the difference between the three contact extraction modes?

- **none**: Maps data only (~$0.25 per 100)
- **basic**: Maps + website + domain + social profiles (~$0.75 per 100)
- **emails**: Full enrichment with email discovery and confidence scoring (~$2.50 per 100)

Choose based on your budget and whether you need email addresses. You can run maps-only first, then rerun qualified categories with email enrichment.

#### How accurate are the extracted emails?

Email accuracy depends on:

- **Syntax validation**: All emails pass basic email format checks
- **DNS validation** (optional): Additional domain confirmation
- **Email confidence score**: 0-1 score indicating likelihood of validity based on discovery method (mailto link, domain match, etc.)

Average confidence for mailto-sourced emails: 0.92. Average for domain-inferred emails: 0.72.

#### Can I use this for bulk email campaigns?

Emails are sourced from public business websites. Verify compliance with anti-spam laws (CAN-SPAM, GDPR) in your jurisdiction and use email addresses only for business development purposes. Always include unsubscribe options in outreach.

***

#### Does this scrape emails from Google Maps directly?

No. Google Maps usually does not display public email addresses. The actor finds Google Maps businesses, extracts their websites, then checks public website pages such as home, contact, and about pages for emails.

#### What happens if a business has no website?

The actor still saves the Google Maps business record unless you set `requireWebsite: true`.

#### What happens if no email is found?

The actor saves the lead with `email_status: "not_found"` unless you set `requireEmail: true`.

#### Can I export the results?

Yes. Apify datasets can be exported as JSON, CSV, Excel, XML, RSS, or HTML, and can be used through the Apify API.

#### Can I save different configurations for different industries or cities?

Yes. Open the actor in Apify Console, set the input, and click **Save as a new task**. Each task keeps its own configuration — for example, one task for `dentist email leads in Toronto` and another for `HVAC contractor leads in Dallas` — and each can run on its own schedule. See [Ready-made task setups](#ready-made-task-setups) for copy-paste configurations and pre-saved example tasks you can run in one click.

#### Can I connect this to my CRM or sales workflow?

Yes. You can use Apify integrations, webhooks, the Apify API, Make, Zapier, Google Sheets, Clay, or your own automation to send Google Maps leads into a CRM or outbound workflow.

#### Is this the same as a generic website email extractor?

No. A generic email extractor needs website URLs first. This actor discovers businesses from Google Maps and then enriches the websites it finds.

#### Is this the same as a broad Google Maps scraper?

No. Broad Google Maps scrapers are useful for place data. This actor is optimized for contact-ready local lead generation with emails, source URLs, confidence fields, and partial-save behavior.

### How We Compare

| Feature | Google Maps Email Extractor | Broad Maps Scrapers | Generic Email Extractors |
|---------|-----|---|---|
| **Local business discovery** | ✅ From search terms or URLs | ✅ Yes | ❌ No (need URLs first) |
| **Website contact scraping** | ✅ Yes (contact, home, about pages) | ❌ Maps data only | ✅ Yes (from URLs) |
| **Email extraction** | ✅ Yes, with confidence scores | ❌ No | ✅ Yes (limited context) |
| **Social profile extraction** | ✅ Yes | ❌ No | ⚠️ Limited |
| **Rating & review data** | ✅ Yes | ✅ Yes | ❌ No |
| **Partial results on failure** | ✅ Preserves Maps data when website fails | ❌ Often all-or-nothing | ⚠️ Varies |
| **One-run workflow** | ✅ Discovery + enrichment together | ❌ No enrichment | ❌ No discovery |
| **Email source & confidence** | ✅ Source URL + confidence score | ❌ N/A | ⚠️ Basic |
| **Best for** | Lead generation, agency workflows | Academic research, data science | Website-based contact harvesting |

***

### Support & Resources

- **Report Issues:** [apify.com/kmiloaguilar/google-maps-email-extractor/issues/open](https://apify.com/kmiloaguilar/google-maps-email-extractor/issues/open)
- **Apify Community:** Join discussions with other users

***

*This actor is maintained and actively developed. Last verified stable: July 2026*

# Actor input Schema

## `searchTerms` (type: `array`):

Google Maps search terms, for example dentists, restaurants, or HVAC contractors.

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

City, region, postal code, or country appended to each search term.

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

Google Maps search or place URLs to scrape instead of, or in addition to, search terms.

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

Maximum unique place records to save.

## `maxResultsPerSearch` (type: `integer`):

Maximum place URLs to process from each Google Maps search page.

## `contactExtraction` (type: `string`):

Choose Maps-only output, basic website/social enrichment, or email extraction.

## `emailVerification` (type: `string`):

Verification mode for primary email. DNS checks are best-effort.

## `minReviewCount` (type: `integer`):

Skip businesses with fewer Google reviews than this. Applied only when Google exposes the review count; businesses with an unknown review count are kept.

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

Skip businesses with a lower Google rating than this. Applied only when Google exposes the rating; businesses with an unknown rating are kept.

## `categories` (type: `array`):

Optional category allow-list applied after extraction.

## `excludeCategories` (type: `array`):

Optional category deny-list applied after extraction.

## `inferCategories` (type: `boolean`):

Automatically applies a conservative category allow-list for common query types such as law firms, dentists, and coffee shops.

## `requireEmail` (type: `boolean`):

Save only records where at least one email was found.

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

Save only records where a website was found.

## `includeReviews` (type: `boolean`):

Accepted for compatibility. Review text scraping is not enabled in this MVP.

## `scrapeDetailPages` (type: `boolean`):

Fetch Google Maps place pages for additional business fields before contact enrichment.

## `maxConcurrency` (type: `integer`):

Maximum HTTP connections used by the actor.

## `requestRetries` (type: `integer`):

Retries for failed page requests.

## `requestTimeoutSecs` (type: `integer`):

Timeout for each HTTP request.

## `requestDelayMillis` (type: `integer`):

Optional delay between Google Maps search pages.

## `proxyUrl` (type: `string`):

Optional explicit proxy URL.

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

Apify proxy configuration. This MVP reads proxyUrl when provided.

## Actor input object example

```json
{
  "searchTerms": [
    "dentists"
  ],
  "location": "Toronto, ON",
  "startUrls": [
    {
      "url": "https://www.google.com/maps/search/dentists+Toronto"
    }
  ],
  "maxItems": 100,
  "maxResultsPerSearch": 100,
  "contactExtraction": "emails",
  "emailVerification": "syntax",
  "inferCategories": true,
  "requireEmail": false,
  "requireWebsite": false,
  "includeReviews": false,
  "scrapeDetailPages": true,
  "maxConcurrency": 5,
  "requestRetries": 2,
  "requestTimeoutSecs": 30,
  "requestDelayMillis": 0
}
```

# Actor output Schema

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

Scraped Google Maps place records with business identity, location, rating, phone, website, email enrichment, social links, and scraping metadata.

# 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 = {
    "searchTerms": [
        "dentists"
    ],
    "startUrls": [
        {
            "url": "https://www.google.com/maps/search/dentists+Toronto"
        }
    ]
};

// Run the Actor and wait for it to finish
const run = await client.actor("kmiloaguilar/google-maps-email-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 = {
    "searchTerms": ["dentists"],
    "startUrls": [{ "url": "https://www.google.com/maps/search/dentists+Toronto" }],
}

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

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

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

```

## CLI example

```bash
echo '{
  "searchTerms": [
    "dentists"
  ],
  "startUrls": [
    {
      "url": "https://www.google.com/maps/search/dentists+Toronto"
    }
  ]
}' |
apify call kmiloaguilar/google-maps-email-extractor --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "command": "npx",
            "args": [
                "mcp-remote",
                "https://mcp.apify.com/?tools=kmiloaguilar/google-maps-email-extractor",
                "--header",
                "Authorization: Bearer <YOUR_API_TOKEN>"
            ]
        }
    }
}

```

## OpenAPI specification

```json
{
    "openapi": "3.0.1",
    "info": {
        "title": "Google Maps Email Extractor",
        "description": "Scrapes Google Maps places and optionally enriches each business with website contact emails and social links.",
        "version": "0.1",
        "x-build-id": "AdsWf3BxCmM6kQoco"
    },
    "servers": [
        {
            "url": "https://api.apify.com/v2"
        }
    ],
    "paths": {
        "/acts/kmiloaguilar~google-maps-email-extractor/run-sync-get-dataset-items": {
            "post": {
                "operationId": "run-sync-get-dataset-items-kmiloaguilar-google-maps-email-extractor",
                "x-openai-isConsequential": false,
                "summary": "Executes an Actor, waits for its completion, and returns Actor's dataset items in response.",
                "tags": [
                    "Run Actor"
                ],
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "$ref": "#/components/schemas/inputSchema"
                            }
                        }
                    }
                },
                "parameters": [
                    {
                        "name": "token",
                        "in": "query",
                        "required": true,
                        "schema": {
                            "type": "string"
                        },
                        "description": "Enter your Apify token here"
                    }
                ],
                "responses": {
                    "200": {
                        "description": "OK"
                    }
                }
            }
        },
        "/acts/kmiloaguilar~google-maps-email-extractor/runs": {
            "post": {
                "operationId": "runs-sync-kmiloaguilar-google-maps-email-extractor",
                "x-openai-isConsequential": false,
                "summary": "Executes an Actor and returns information about the initiated run in response.",
                "tags": [
                    "Run Actor"
                ],
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "$ref": "#/components/schemas/inputSchema"
                            }
                        }
                    }
                },
                "parameters": [
                    {
                        "name": "token",
                        "in": "query",
                        "required": true,
                        "schema": {
                            "type": "string"
                        },
                        "description": "Enter your Apify token here"
                    }
                ],
                "responses": {
                    "200": {
                        "description": "OK",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/runsResponseSchema"
                                }
                            }
                        }
                    }
                }
            }
        },
        "/acts/kmiloaguilar~google-maps-email-extractor/run-sync": {
            "post": {
                "operationId": "run-sync-kmiloaguilar-google-maps-email-extractor",
                "x-openai-isConsequential": false,
                "summary": "Executes an Actor, waits for completion, and returns the OUTPUT from Key-value store in response.",
                "tags": [
                    "Run Actor"
                ],
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "$ref": "#/components/schemas/inputSchema"
                            }
                        }
                    }
                },
                "parameters": [
                    {
                        "name": "token",
                        "in": "query",
                        "required": true,
                        "schema": {
                            "type": "string"
                        },
                        "description": "Enter your Apify token here"
                    }
                ],
                "responses": {
                    "200": {
                        "description": "OK"
                    }
                }
            }
        }
    },
    "components": {
        "schemas": {
            "inputSchema": {
                "type": "object",
                "properties": {
                    "searchTerms": {
                        "title": "Search terms",
                        "type": "array",
                        "description": "Google Maps search terms, for example dentists, restaurants, or HVAC contractors.",
                        "items": {
                            "type": "string"
                        }
                    },
                    "location": {
                        "title": "Location",
                        "type": "string",
                        "description": "City, region, postal code, or country appended to each search term.",
                        "default": "Toronto, ON"
                    },
                    "startUrls": {
                        "title": "Google Maps URLs",
                        "type": "array",
                        "description": "Google Maps search or place URLs to scrape instead of, or in addition to, search terms.",
                        "items": {
                            "type": "object",
                            "required": [
                                "url"
                            ],
                            "properties": {
                                "url": {
                                    "type": "string",
                                    "title": "URL of a web page",
                                    "format": "uri"
                                }
                            }
                        }
                    },
                    "maxItems": {
                        "title": "Maximum places",
                        "minimum": 1,
                        "maximum": 10000,
                        "type": "integer",
                        "description": "Maximum unique place records to save.",
                        "default": 100
                    },
                    "maxResultsPerSearch": {
                        "title": "Maximum places per search",
                        "minimum": 1,
                        "maximum": 1000,
                        "type": "integer",
                        "description": "Maximum place URLs to process from each Google Maps search page.",
                        "default": 100
                    },
                    "contactExtraction": {
                        "title": "Contact extraction",
                        "enum": [
                            "none",
                            "basic",
                            "emails"
                        ],
                        "type": "string",
                        "description": "Choose Maps-only output, basic website/social enrichment, or email extraction.",
                        "default": "emails"
                    },
                    "emailVerification": {
                        "title": "Email verification",
                        "enum": [
                            "none",
                            "syntax",
                            "dns"
                        ],
                        "type": "string",
                        "description": "Verification mode for primary email. DNS checks are best-effort.",
                        "default": "syntax"
                    },
                    "minReviewCount": {
                        "title": "Minimum reviews",
                        "minimum": 0,
                        "type": "integer",
                        "description": "Skip businesses with fewer Google reviews than this. Applied only when Google exposes the review count; businesses with an unknown review count are kept."
                    },
                    "minRating": {
                        "title": "Minimum rating",
                        "minimum": 0,
                        "maximum": 5,
                        "type": "number",
                        "description": "Skip businesses with a lower Google rating than this. Applied only when Google exposes the rating; businesses with an unknown rating are kept."
                    },
                    "categories": {
                        "title": "Include categories",
                        "type": "array",
                        "description": "Optional category allow-list applied after extraction.",
                        "items": {
                            "type": "string"
                        }
                    },
                    "excludeCategories": {
                        "title": "Exclude categories",
                        "type": "array",
                        "description": "Optional category deny-list applied after extraction.",
                        "items": {
                            "type": "string"
                        }
                    },
                    "inferCategories": {
                        "title": "Infer category filter",
                        "type": "boolean",
                        "description": "Automatically applies a conservative category allow-list for common query types such as law firms, dentists, and coffee shops.",
                        "default": true
                    },
                    "requireEmail": {
                        "title": "Require email",
                        "type": "boolean",
                        "description": "Save only records where at least one email was found.",
                        "default": false
                    },
                    "requireWebsite": {
                        "title": "Require website",
                        "type": "boolean",
                        "description": "Save only records where a website was found.",
                        "default": false
                    },
                    "includeReviews": {
                        "title": "Include reviews",
                        "type": "boolean",
                        "description": "Accepted for compatibility. Review text scraping is not enabled in this MVP.",
                        "default": false
                    },
                    "scrapeDetailPages": {
                        "title": "Scrape detail pages",
                        "type": "boolean",
                        "description": "Fetch Google Maps place pages for additional business fields before contact enrichment.",
                        "default": true
                    },
                    "maxConcurrency": {
                        "title": "Maximum concurrency",
                        "minimum": 1,
                        "maximum": 50,
                        "type": "integer",
                        "description": "Maximum HTTP connections used by the actor.",
                        "default": 5
                    },
                    "requestRetries": {
                        "title": "Request retries",
                        "minimum": 0,
                        "maximum": 10,
                        "type": "integer",
                        "description": "Retries for failed page requests.",
                        "default": 2
                    },
                    "requestTimeoutSecs": {
                        "title": "Request timeout seconds",
                        "minimum": 5,
                        "maximum": 120,
                        "type": "integer",
                        "description": "Timeout for each HTTP request.",
                        "default": 30
                    },
                    "requestDelayMillis": {
                        "title": "Request delay milliseconds",
                        "minimum": 0,
                        "maximum": 10000,
                        "type": "integer",
                        "description": "Optional delay between Google Maps search pages.",
                        "default": 0
                    },
                    "proxyUrl": {
                        "title": "Proxy URL",
                        "type": "string",
                        "description": "Optional explicit proxy URL."
                    },
                    "proxyConfiguration": {
                        "title": "Proxy configuration",
                        "type": "object",
                        "description": "Apify proxy configuration. This MVP reads proxyUrl when provided."
                    }
                }
            },
            "runsResponseSchema": {
                "type": "object",
                "properties": {
                    "data": {
                        "type": "object",
                        "properties": {
                            "id": {
                                "type": "string"
                            },
                            "actId": {
                                "type": "string"
                            },
                            "userId": {
                                "type": "string"
                            },
                            "startedAt": {
                                "type": "string",
                                "format": "date-time",
                                "example": "2025-01-08T00:00:00.000Z"
                            },
                            "finishedAt": {
                                "type": "string",
                                "format": "date-time",
                                "example": "2025-01-08T00:00:00.000Z"
                            },
                            "status": {
                                "type": "string",
                                "example": "READY"
                            },
                            "meta": {
                                "type": "object",
                                "properties": {
                                    "origin": {
                                        "type": "string",
                                        "example": "API"
                                    },
                                    "userAgent": {
                                        "type": "string"
                                    }
                                }
                            },
                            "stats": {
                                "type": "object",
                                "properties": {
                                    "inputBodyLen": {
                                        "type": "integer",
                                        "example": 2000
                                    },
                                    "rebootCount": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "restartCount": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "resurrectCount": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "computeUnits": {
                                        "type": "integer",
                                        "example": 0
                                    }
                                }
                            },
                            "options": {
                                "type": "object",
                                "properties": {
                                    "build": {
                                        "type": "string",
                                        "example": "latest"
                                    },
                                    "timeoutSecs": {
                                        "type": "integer",
                                        "example": 300
                                    },
                                    "memoryMbytes": {
                                        "type": "integer",
                                        "example": 1024
                                    },
                                    "diskMbytes": {
                                        "type": "integer",
                                        "example": 2048
                                    }
                                }
                            },
                            "buildId": {
                                "type": "string"
                            },
                            "defaultKeyValueStoreId": {
                                "type": "string"
                            },
                            "defaultDatasetId": {
                                "type": "string"
                            },
                            "defaultRequestQueueId": {
                                "type": "string"
                            },
                            "buildNumber": {
                                "type": "string",
                                "example": "1.0.0"
                            },
                            "containerUrl": {
                                "type": "string"
                            },
                            "usage": {
                                "type": "object",
                                "properties": {
                                    "ACTOR_COMPUTE_UNITS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATASET_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATASET_WRITES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "KEY_VALUE_STORE_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "KEY_VALUE_STORE_WRITES": {
                                        "type": "integer",
                                        "example": 1
                                    },
                                    "KEY_VALUE_STORE_LISTS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "REQUEST_QUEUE_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "REQUEST_QUEUE_WRITES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATA_TRANSFER_INTERNAL_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATA_TRANSFER_EXTERNAL_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "PROXY_RESIDENTIAL_TRANSFER_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "PROXY_SERPS": {
                                        "type": "integer",
                                        "example": 0
                                    }
                                }
                            },
                            "usageTotalUsd": {
                                "type": "number",
                                "example": 0.00005
                            },
                            "usageUsd": {
                                "type": "object",
                                "properties": {
                                    "ACTOR_COMPUTE_UNITS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATASET_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATASET_WRITES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "KEY_VALUE_STORE_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "KEY_VALUE_STORE_WRITES": {
                                        "type": "number",
                                        "example": 0.00005
                                    },
                                    "KEY_VALUE_STORE_LISTS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "REQUEST_QUEUE_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "REQUEST_QUEUE_WRITES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATA_TRANSFER_INTERNAL_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATA_TRANSFER_EXTERNAL_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "PROXY_RESIDENTIAL_TRANSFER_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "PROXY_SERPS": {
                                        "type": "integer",
                                        "example": 0
                                    }
                                }
                            }
                        }
                    }
                }
            }
        }
    }
}
```
