# Electrician Lead Scraper - Maps Phone Email (Unofficial) (`brainy_frostfield/electrician-lead-scraper`) Actor

UNOFFICIAL Google Maps electrician lead scraper with validated phones, public emails, license detection, and specialties (EV, emergency, solar). Not affiliated with Google. No AI language models.

- **URL**: https://apify.com/brainy\_frostfield/electrician-lead-scraper.md
- **Developed by:** [Viv K](https://apify.com/brainy_frostfield) (community)
- **Categories:** Lead generation, Developer tools, Automation
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $4.00 / 1,000 place leads

This Actor is paid per event and usage. You are charged both the fixed price for specific events and for Apify platform usage.

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

## What's an Apify Actor?

Actors are web data automations that power AI and operations. They run on the Apify platform to scrape websites, process data, connect APIs, and automate workflows.
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.

- **AI agents and MCP clients** — the [Apify MCP server](https://docs.apify.com/integrations/mcp.md) at `https://mcp.apify.com` (remote, streamable HTTP, OAuth on first use).
- **Agentic workflows and local Actor development** — [Agent Skills](https://apify.com/.well-known/agent-skills/index.json) with the [Apify CLI](https://docs.apify.com/cli/docs.md): `npm install -g apify-cli`, then `apify login`.
- **JavaScript/TypeScript projects** — the official [JS/TS client](https://docs.apify.com/api/client/js/docs.md): `npm install apify-client`.
- **Python projects** — the official [Python client](https://docs.apify.com/api/client/python/docs.md): `pip install apify-client`.
- **Any other language** — 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

## Electrician Lead Scraper – Google Maps + Phone & Email (Unofficial)

Find **electricians and electrical contractors** from Google Maps, with **validated phone numbers**, optional **public website emails**, free **email-domain (MX) checks**, **license detection**, **specialty flags** (EV charger, 24/7 emergency, solar, generator…), and **lead scoring** (HOT / WARM / COLD).

No AI language models. No Google Places API key required.

> **UNOFFICIAL** — not affiliated with, endorsed by, or sponsored by Google LLC. Google Maps is a trademark of Google LLC.\
> You are solely responsible for complying with Google’s Terms of Service, privacy laws (GDPR/CCPA), anti-spam rules (CAN-SPAM/CASL), website terms, and [Apify’s Acceptable Use Policy](https://docs.apify.com/legal/acceptable-use-policy).\
> **Do not use for unsolicited mass messaging.** Scraping Google Maps may violate Google’s contractual terms even when data is publicly visible.

***

### Features

- Search Google Maps by **location** and **keywords** (electricians, emergency electrician, EV charger installer…)
- Extract **name, address, phone, website, rating, hours, Maps URL**
- Detect **unclaimed** Google listings
- Optional crawl of public website pages for **emails**, extra **phones**, and **social links**
- Detect **license numbers** (best-effort regex patterns)
- Specialty flags: **24/7 emergency**, **EV charger**, **solar**, **generator**, panel upgrade, commercial/residential…
- **Licensed / insured / bonded** mentions from website text
- Normalize phones with **libphonenumber**
- Free **MX domain check** on found emails
- Simple **niche tag** (e.g. emergency electrician, EV charger installation)
- **Lead score** 0–100 and tier **HOT / WARM / COLD**

Phones, emails, licenses, and specialties are only taken from Maps and text that appears on public pages. Nothing is invented by AI.

***

### How to use

1. Add one or more **locations** (city or ZIP).
2. Add **search terms** (e.g. `electricians` or `EV charger installer`).
3. Set **Max results per query** (try **10–20** first; defaults stay small for Store tests).
4. Turn on **Extract emails**, **Find license**, and **Detect specialties** as needed.
5. Set proxy to **Apify Proxy → RESIDENTIAL** (recommended for Maps).
6. Click **Start**, then download the dataset.

#### Example input

```json
{
  "locations": ["Los Angeles, CA"],
  "searchTerms": ["electricians"],
  "maxPlacesPerQuery": 10,
  "extractEmails": true,
  "extractWebsitePhones": true,
  "findLicense": true,
  "detectSpecialties": true,
  "validateMxRecords": true,
  "maxWebsitePagesPerPlace": 2,
  "proxyConfiguration": {
    "useApifyProxy": true,
    "apifyProxyGroups": ["RESIDENTIAL"]
  }
}
```

#### Input fields

| Field | Description |
|---|---|
| Target locations | Cities, states, or ZIPs |
| Search terms | Maps keywords |
| Max results per query | Cap per location × term |
| Max total places | Optional cap for the whole run |
| Extract emails | Crawl public website pages for emails |
| Extract website phones | Also collect phones from site pages |
| Find license | Scan site text for license / contractor patterns |
| Detect specialties | Flag EV, emergency, solar, generator, etc. |
| Validate MX | Free check that the email domain can receive mail |
| Max pages per website | How many site pages to check |
| Proxy for Google Maps | Prefer **residential** |
| Filters | Phone only / email only / emergency only / EV only / include no website |

***

### Output example

```json
{
  "query": "electricians in Los Angeles, CA",
  "businessName": "LA Peak Electric",
  "niche": "EV charger installation",
  "address": "200 N Spring St, Los Angeles, CA 90012",
  "primaryPhone": "+13235550100",
  "primaryPhoneNational": "(323) 555-0100",
  "phones": [
    {
      "phone": "+13235550100",
      "national": "(323) 555-0100",
      "sourceType": "google_maps",
      "confidence": 96
    }
  ],
  "hasPhone": true,
  "website": "https://lapeakelectric.example",
  "emails": [
    {
      "email": "service@lapeakelectric.example",
      "source": "mailto_contact",
      "confidence": 95,
      "mxValid": true
    }
  ],
  "primaryEmail": "service@lapeakelectric.example",
  "hasEmail": true,
  "licenseNumbers": ["920387"],
  "isLicensed": true,
  "specialties": ["EV Charger", "24/7 Emergency", "Panel Upgrade"],
  "isEVChargerSpecialist": true,
  "isEmergency24_7": true,
  "isSolarSpecialist": false,
  "isGeneratorSpecialist": false,
  "insuranceInfo": {
    "mentionsLicensed": true,
    "mentionsInsured": true,
    "mentionsBonded": true,
    "fullyLicensedBondedInsured": true
  },
  "leadScore": 78,
  "leadTier": "WARM",
  "leadReasons": [
    "EV charger specialist (high ticket)",
    "24/7 emergency positioning"
  ],
  "googleMapsUrl": "https://www.google.com/maps/place/...",
  "scrapedAt": "2026-08-08T12:00:00.000Z"
}
```

***

### Pricing

**Pay per event** + **platform usage**. You pay **both**:

1. **Event fees** (below) — paid to the Actor developer
2. **Platform usage** — paid to Apify for compute, data transfer, storage, and **proxies**

#### Platform usage & residential proxy (important)

Google Maps runs need **Apify Proxy → RESIDENTIAL**. Residential traffic is billed by Apify **per GB** (rate depends on your plan; often around **$7–$8 / GB** on lower plans).

- Browser/Maps traffic is heavier than simple HTTP scrapes, so even small runs can use tens–hundreds of MB.
- **Proxy + compute usually cost more than the event fees** on short test runs.
- Start with a **small test** (low `maxPlacesPerQuery`) before large city lists.
- Without residential proxy you often get **0 results**, but you still avoid that proxy charge.

#### Event fees

| Event | When charged | Price |
|---|---|---|
| Place lead | Each business saved | **$0.004** ($4.00 per 1,000) |
| Phone enrichment | Only if at least one validated phone is found | **$0.005** ($5.00 per 1,000) |
| Email enrichment | Only if at least one public email is found | **$0.004** ($4.00 per 1,000) |

**Event fee examples** (platform usage — including residential proxy — is **extra**):

| Result mix | Approx. event cost only |
|---|---|
| 1,000 places, all with phone, no emails | **$9.00** + usage |
| 1,000 places, all with phone + email | **$13.00** + usage |
| 1,000 places, ~80% phone, ~40% email | **~$9.60** + usage |

Total cost scales with locations, search terms, max results, **residential proxy GB**, and compute. Defaults stay small for Store auto-tests and cheap first runs.

***

### Tips

- **Residential proxy** is important for Google Maps. Without it you may get zero results.
- Expect **proxy usage** to be a large share of the run cost; keep max results low while testing.
- More cities × more keywords × higher max results = longer runs and higher **proxy + compute** cost.
- Search **`EV charger installer`** or **`emergency electrician`** for specialty-focused lists.
- **No website** / **unclaimed** / **few reviews** often score **HOT** for agencies.
- License detection is **best-effort** and varies by state wording.

***

### Compliance

- Public business information only; no login walls.
- Business emails and phones may still be personal data under GDPR/CCPA in some cases.
- You are responsible for lawful use and outreach (anti-spam and privacy rules).
- Do not use for spam or illegal activity.

***

### Limitations

- Google Maps may block non-residential traffic.
- Phones/emails hidden in images or complex scripts may be missed.
- License regexes are best-effort; not every state format is covered.
- `mxValid` checks the **domain**, not that a specific mailbox is active.
- Lead score is a heuristic, not a guarantee of conversion.
- Maps does not return unlimited listings per area.
- Maps page layout can change over time.

***

### Troubleshooting

| Problem | What to try |
|---|---|
| 0 results | Use residential proxy; lower max results; check the run log |
| Places but no emails | Common for form-only sites; try more website pages |
| No license numbers | Site may not publish a license; turn off “find license” or accept empty |
| Slow or costly run | Fewer locations/terms; lower max results |
| Empty after filters | Turn off “only EV” / “only emergency” / “only with email” for testing |

Support: open an **Issue** on this Actor with your run ID and input (no secrets).

# Actor input Schema

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

Cities, states, or ZIP codes (e.g. Los Angeles, CA).

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

Maps keywords (electricians, emergency electrician, EV charger installer…).

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

Maximum businesses per location × term. Default is small for fast Store tests.

## `maxTotalPlaces` (type: `integer`):

Optional run-wide cap. Leave empty/0 for no global cap.

## `extractEmails` (type: `boolean`):

Collect public emails from business websites.

## `extractWebsitePhones` (type: `boolean`):

Also collect phones from website tel links and text.

## `findLicense` (type: `boolean`):

Scan website text for license / contractor license patterns.

## `detectSpecialties` (type: `boolean`):

Flag EV charger, emergency 24/7, solar, generator, panel upgrade, etc.

## `validateMxRecords` (type: `boolean`):

Free DNS check that email domains can receive mail.

## `maxWebsitePagesPerPlace` (type: `integer`):

Pages to check (home, contact, services, about).

## `websiteRequestDelayMs` (type: `integer`):

Polite delay between website page requests.

## `defaultCountryCode` (type: `string`):

ISO country code used when parsing phone numbers.

## `includeNoWebsite` (type: `boolean`):

Keep listings even without a website (often HOT for agencies).

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

Only keep leads with at least one validated phone.

## `onlyWithEmail` (type: `boolean`):

Only keep leads with at least one public email.

## `onlyEmergency` (type: `boolean`):

Only keep leads flagged as emergency / 24-7.

## `onlyEVCharger` (type: `boolean`):

Only keep leads that mention EV charger installation.

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

Residential proxy is strongly recommended for Maps.

## `websiteProxyConfiguration` (type: `object`):

Optional proxy for website crawling.

## `maxScrolls` (type: `integer`):

How many times to scroll Maps results.

## `debugLog` (type: `boolean`):

More detail in the run log.

## Actor input object example

```json
{
  "locations": [
    "Los Angeles, CA"
  ],
  "searchTerms": [
    "electricians"
  ],
  "maxPlacesPerQuery": 5,
  "extractEmails": true,
  "extractWebsitePhones": true,
  "findLicense": true,
  "detectSpecialties": true,
  "validateMxRecords": true,
  "maxWebsitePagesPerPlace": 2,
  "websiteRequestDelayMs": 800,
  "defaultCountryCode": "US",
  "includeNoWebsite": true,
  "onlyWithPhone": false,
  "onlyWithEmail": false,
  "onlyEmergency": false,
  "onlyEVCharger": false,
  "proxyConfiguration": {
    "useApifyProxy": true,
    "apifyProxyGroups": [
      "RESIDENTIAL"
    ]
  },
  "maxScrolls": 10,
  "debugLog": false
}
```

# Actor output Schema

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

Dataset of electrician leads.

# 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 = {
    "locations": [
        "Los Angeles, CA"
    ],
    "searchTerms": [
        "electricians"
    ],
    "maxPlacesPerQuery": 5,
    "maxWebsitePagesPerPlace": 2
};

// Run the Actor and wait for it to finish
const run = await client.actor("brainy_frostfield/electrician-lead-scraper").call(input);

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

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

```

## Python example

```python
from apify_client import ApifyClient

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

# Prepare the Actor input
run_input = {
    "locations": ["Los Angeles, CA"],
    "searchTerms": ["electricians"],
    "maxPlacesPerQuery": 5,
    "maxWebsitePagesPerPlace": 2,
}

# Run the Actor and wait for it to finish
run = client.actor("brainy_frostfield/electrician-lead-scraper").call(run_input=run_input)

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

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

```

## CLI example

```bash
echo '{
  "locations": [
    "Los Angeles, CA"
  ],
  "searchTerms": [
    "electricians"
  ],
  "maxPlacesPerQuery": 5,
  "maxWebsitePagesPerPlace": 2
}' |
apify call brainy_frostfield/electrician-lead-scraper --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,brainy_frostfield/electrician-lead-scraper"
        }
    }
}

```

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

## OpenAPI specification

Download the OpenAPI definition: https://api.apify.com/v2/actors/tlCWvT5roBfZ8WtU5/builds/Kqk8BCcBqwhn1nbYG/openapi.json
