# Unclaimed Google Maps Leads Scraper (`pawanhiray/unclaimed-google-maps-leads`) Actor

Finds unclaimed Google Maps business listings and enriches them with emails, social links, and AI-ready markdown from their websites.

- **URL**: https://apify.com/pawanhiray/unclaimed-google-maps-leads.md
- **Developed by:** [Pawan Hiray](https://apify.com/pawanhiray) (community)
- **Categories:** Lead generation, SEO tools, AI
- **Stats:** 2 total users, 0 monthly users, 0.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

Pay per usage

This Actor is paid per platform usage. The Actor is free to use, and you only pay for the Apify platform usage, which gets cheaper the higher subscription plan you have.

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

## 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

## Unclaimed Google Maps Leads Scraper | AI-Enriched B2B Lead Generation

> **Automatically find unclaimed Google Maps business listings, extract contact details, and generate AI-ready markdown profiles — all in one Apify Actor.**

Stop wasting hours manually searching for unclaimed Google Business Profiles. This Actor scans Google Maps at scale, identifies businesses that haven't claimed their listings, enriches them with emails, social links, and website content — delivering leads ready for outreach or AI/RAG pipelines.

---

### What This Actor Does

**Phase 1 — Google Maps Discovery:**
- Accepts multiple search queries (e.g., "Plumbers in Miami", "Auto repair in Chicago")
- Scrolls through Google Maps results, clicking each listing to inspect the detail pane
- Detects the "Own this business?" / "Claim this business" indicator — only keeps unclaimed leads
- Extracts: business name, Maps URL, phone, website, rating, review count, address

**Phase 2 — Website Enrichment:**
- Visits each unclaimed business's website
- Scrapes homepage + common subpages (/contact, /about, etc.)
- Extracts valid email addresses with domain blacklist filtering
- Discovers Facebook and Instagram profile links
- Converts cleaned website HTML into dense, token-optimized Markdown for LLM/RAG ingestion

**Pay-Per-Event Billing:**
- Charges `lead-scraped` only for each successfully enriched unclaimed business

---

### Key Features

| Feature | Description |
|---------|-------------|
| **Multi-Query Support** | Run unlimited search queries in a single run |
| **Smart Unclaimed Detection** | Inspects the detail pane for "Own this business?" / "Claim this business" signals — not just sidebar heuristics |
| **Email Extraction** | Regex-based extraction with domain blacklisting to filter out junk, platform, and placeholder emails |
| **Social Link Discovery** | Automatically finds Facebook and Instagram profiles from website HTML |
| **AI-Ready Markdown** | Generates clean, dense Markdown from website content — optimized for LLM context windows and RAG vector stores |
| **Contact Page Crawling** | Deep-crawls /contact, /about, and related subpages to maximize email discovery |
| **Anti-Detection** | Custom user agent, automation flag disabling, randomized scroll delays |
| **Proxy Support** | Built-in Apify Proxy integration for Google Maps block bypass |
| **Resilient Error Handling** | Every extraction wrapped in isolated try/catch — one bad listing never crashes the run |

---

### Output Schema

Each record in the dataset:

```json
{
  "businessName": "ABC Plumbing Co",
  "mapsUrl": "https://www.google.com/maps/place/ABC-Plumbing/...",
  "phone": "(214) 555-1234",
  "website": "https://abcplumbing.com",
  "rating": 4.5,
  "reviewsCount": 127,
  "extractedEmails": ["info@abcplumbing.com", "service@abcplumbing.com"],
  "socialLinks": {
    "facebook": "https://facebook.com/abcplumbing",
    "instagram": "https://instagram.com/abcplumbing"
  },
  "isUnclaimed": true,
  "aiReadyMarkdown": "# ABC Plumbing Co\n\nWe provide 24/7 emergency plumbing services in Dallas..."
}
````

#### Field Reference

| Field | Type | Description |
|-------|------|-------------|
| `businessName` | String | Official business name from Google Maps |
| `mapsUrl` | String | Direct Google Maps place URL |
| `phone` | String | Business phone number |
| `website` | String | Business website URL |
| `rating` | Number | Google Maps star rating (1-5) |
| `reviewsCount` | Number | Total Google reviews |
| `extractedEmails` | String\[] | Valid emails found on the website |
| `socialLinks.facebook` | String | Facebook profile URL (or null) |
| `socialLinks.instagram` | String | Instagram profile URL (or null) |
| `isUnclaimed` | Boolean | Always `true` — all results are unclaimed |
| `aiReadyMarkdown` | String | Clean Markdown of website content for LLM/RAG use |

***

### Input Configuration

| Field | Type | Required | Default | Description |
|-------|------|----------|---------|-------------|
| `searchQueries` | String\[] | Yes | — | Google Maps search terms (e.g., `["Dentists in Dallas"]`) |
| `maxResultsPerQuery` | Integer | No | `100` | Max unclaimed leads per query (1-500) |
| `proxyConfiguration` | Object | No | Apify Proxy | Proxy settings — **strongly recommended** for Google Maps |

#### Example Input

```json
{
  "searchQueries": [
    "Plumbing services in Miami",
    "Auto repair shops in Houston",
    "Landscaping companies in Chicago"
  ],
  "maxResultsPerQuery": 50,
  "proxyConfiguration": {
    "useApifyProxy": true,
    "apifyProxyGroups": ["RESIDENTIAL"]
  }
}
```

***

### Getting Started

1. **Add to your Apify account** — click "Add to My Actors" or deploy via CLI
2. **Configure inputs** — add your search queries and set max results
3. **Enable Apify Proxy** — required for Google Maps (use `RESIDENTIAL` group for best results)
4. **Run the Actor** — results appear in the Dataset tab
5. **Export** — download as JSON, CSV, or access via API

#### Running via CLI

```bash
## Install dependencies
npm install

## Run locally
npx apify run

## Push to Apify
npx apify-cli push --force
```

***

### Use Cases

#### B2B Marketing Agencies

- **Lead generation**: Find unclaimed businesses that need online presence management
- **Cold outreach**: Use extracted emails + business context for personalized campaigns
- **Service pitching**: "I noticed your Google listing is unclaimed — we can help fix that"

#### AI / RAG Developers

- **Knowledge base building**: Use `aiReadyMarkdown` for vector embeddings
- **Business profiling**: Structured data + unstructured content in one record
- **Automated research**: Feed into LLM pipelines for market analysis

#### SEO & Local Marketing

- **Auditing**: Identify businesses with weak or non-existent Google presence
- **Competitive analysis**: Find unclaimed listings in specific niches/locations
- **Client acquisition**: Build prospect lists for local SEO services

***

### Tips for Best Results

- **Search queries matter**: Trades and service businesses (plumbers, HVAC, roofing, auto repair) are more likely to be unclaimed than professional services (dentists, lawyers)
- **Use specific locations**: "Plumbers in Downtown Dallas" yields better results than "Plumbers in Texas"
- **Enable Residential Proxy**: Google Maps aggressively blocks datacenter IPs — use `RESIDENTIAL` proxy group
- **Scale gradually**: Start with `maxResultsPerQuery: 10` to validate, then increase
- **Multiple queries**: Run several related queries in one batch for maximum coverage

***

### How Unclaimed Detection Works

This Actor does **not** rely on fragile sidebar heuristics. For each listing:

1. Clicks into the business detail pane on Google Maps
2. Scans the full page for:
   - `a[href*="place/claim"]` or `a[href*="business/claim"]` elements
   - `[data-claim]` attributes
   - `.claim-banner` elements
   - Text content containing "Own this business?" or "Claim this business"
3. Only listings where at least one indicator is found are kept as leads

This approach is significantly more reliable than checking for the indicator's absence on the sidebar card.

***

### Architecture

```
Phase 1: Google Maps
  PlaywrightCrawler → search query → scroll feed → click a.hfpxzc links
  → detail pane → isUnclaimed check → extract info → save to allListings[]

Phase 2: Website Enrichment
  PlaywrightCrawler → visit website → extract emails + social links
  → convert to Markdown → push to Dataset → charge per lead
```

**Stack:** Node.js + Crawlee (PlaywrightCrawler) + Apify SDK + Turndown (HTML→Markdown)

***

### Dependencies

| Package | Purpose |
|---------|---------|
| `apify` | Apify Actor SDK — dataset, billing, proxy |
| `crawlee` | Web crawling framework with Playwright support |
| `playwright` | Browser automation for Google Maps navigation |
| `turndown` | HTML-to-Markdown conversion for AI-ready content |

***

### Error Handling

- **Navigation failures**: Retried up to 2 times with exponential backoff
- **DOM extraction**: Each field extracted in isolated try/catch — partial data is preserved
- **Website timeouts**: 25s for homepage, 15s for subpages — gracefully returns empty results
- **CAPTCHA/blocking**: Apify Proxy with residential IPs mitigates most blocks

***

### License

MIT

***

**Built for lead generation at scale.** Whether you're pitching unclaimed businesses on Google Maps management services or building AI-powered market research tools, this Actor delivers structured, enriched data ready for immediate use.

# Actor input Schema

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

List of Google Maps search queries (e.g., 'Dentists in Dallas', 'Plumbers in Miami')

## `maxResultsPerQuery` (type: `integer`):

Maximum number of results to scrape per search query

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

Proxy configuration for bypassing Google Maps blocks. Use Apify proxy groups.

## Actor input object example

```json
{
  "searchQueries": [
    "Dentists in Dallas",
    "Plumbers in Miami"
  ],
  "maxResultsPerQuery": 100,
  "proxyConfiguration": {
    "useApifyProxy": true
  }
}
```

# 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": [
        "Dentists in Dallas",
        "Plumbers in Miami"
    ]
};

// Run the Actor and wait for it to finish
const run = await client.actor("pawanhiray/unclaimed-google-maps-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 = { "searchQueries": [
        "Dentists in Dallas",
        "Plumbers in Miami",
    ] }

# Run the Actor and wait for it to finish
run = client.actor("pawanhiray/unclaimed-google-maps-leads").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 '{
  "searchQueries": [
    "Dentists in Dallas",
    "Plumbers in Miami"
  ]
}' |
apify call pawanhiray/unclaimed-google-maps-leads --silent --output-dataset

```

## MCP server setup

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

```

## OpenAPI specification

```json
{
    "openapi": "3.0.1",
    "info": {
        "title": "Unclaimed Google Maps Leads Scraper",
        "description": "Finds unclaimed Google Maps business listings and enriches them with emails, social links, and AI-ready markdown from their websites.",
        "version": "1.0",
        "x-build-id": "1h4UvCxhKrm3DJTbA"
    },
    "servers": [
        {
            "url": "https://api.apify.com/v2"
        }
    ],
    "paths": {
        "/acts/pawanhiray~unclaimed-google-maps-leads/run-sync-get-dataset-items": {
            "post": {
                "operationId": "run-sync-get-dataset-items-pawanhiray-unclaimed-google-maps-leads",
                "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/pawanhiray~unclaimed-google-maps-leads/runs": {
            "post": {
                "operationId": "runs-sync-pawanhiray-unclaimed-google-maps-leads",
                "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/pawanhiray~unclaimed-google-maps-leads/run-sync": {
            "post": {
                "operationId": "run-sync-pawanhiray-unclaimed-google-maps-leads",
                "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",
                "required": [
                    "searchQueries"
                ],
                "properties": {
                    "searchQueries": {
                        "title": "Search Queries",
                        "type": "array",
                        "description": "List of Google Maps search queries (e.g., 'Dentists in Dallas', 'Plumbers in Miami')",
                        "default": [
                            "Dentists in Dallas",
                            "Plumbers in Miami"
                        ],
                        "items": {
                            "type": "string"
                        }
                    },
                    "maxResultsPerQuery": {
                        "title": "Max Results Per Query",
                        "minimum": 1,
                        "maximum": 500,
                        "type": "integer",
                        "description": "Maximum number of results to scrape per search query",
                        "default": 100
                    },
                    "proxyConfiguration": {
                        "title": "Proxy Configuration",
                        "type": "object",
                        "description": "Proxy configuration for bypassing Google Maps blocks. Use Apify proxy groups.",
                        "default": {
                            "useApifyProxy": true
                        }
                    }
                }
            },
            "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
                                    }
                                }
                            }
                        }
                    }
                }
            }
        }
    }
}
```
