# Contractor Lead Scraper — Verified Emails (HVAC, Plumbing) (`samstorm/contractor-lead-scraper`) Actor

Scrape HVAC, plumber, roofer & electrician contacts from Google Maps with verified emails & phones. Real-time data from contractor websites. Export to HubSpot, Salesforce, or CSV. Built for home services marketing & SaaS sales.

- **URL**: https://apify.com/samstorm/contractor-lead-scraper.md
- **Developed by:** [Sam Kleespies](https://apify.com/samstorm) (community)
- **Categories:** Lead generation
- **Stats:** 92 total users, 17 monthly users, 100.0% runs succeeded, 1 bookmarks
- **User rating**: No ratings yet

## Pricing

from $50.00 / 1,000 enriched contractor 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 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

## Contractor Lead Scraper — Verified Emails (HVAC, Plumbing, Roofing, Electricians)

Generate a targeted HVAC contractor email list, plumber leads database, roofer contact list, or electrician leads directory — scraped live from Google Maps with verified contact details. This actor covers the full home services trades: HVAC companies, plumbers, roofers, electricians, general contractors, landscapers, painters, and pest control businesses, returning verified emails, phone numbers, addresses, ratings, and social links ready to import into your CRM.

Built for construction suppliers, home service SaaS companies, insurance brokers, subcontractor networks, and anyone who needs a contractor email list at scale — without paying for an overpriced, stale data subscription.

### Key Features

- **Google Maps search** — Find contractor businesses by trade type and location, powered by Playwright
- **Email extraction** — Automatically crawls contractor websites to find contact emails
- **DNS + SMTP verification** — Confirms email deliverability before export to minimize bounces
- **Social media links** — Extracts Facebook, Instagram, LinkedIn, and Twitter/X profiles
- **CRM-ready export** — Output in Full, HubSpot Import, or Salesforce Import format
- **Real-time data** — Fresh results scraped on demand, not a stale broker database
- **Deduplication** — Automatically removes duplicate listings from overlapping search results
- **No coding required** — Configure via form, click Start, download your contractor leads

### What Data Do You Get?

Each record is extracted from Google Maps and enriched with email addresses crawled live from the contractor's own website. Fields returned in Full output:

| Field | Description |
|-|-|
| `name` | Business name as listed on Google Maps |
| `category` | Contractor type (e.g., HVAC Company, Plumber, Roofer) |
| `address` | Full street address |
| `phone` | Primary phone number |
| `website` | Business website URL |
| `mapsUrl` | Direct Google Maps listing URL |
| `rating` | Star rating (0–5) |
| `reviewCount` | Total number of Google reviews |
| `email` | Primary verified email address |
| `emailVerified` | `true` if email passed DNS + SMTP check |
| `emailVerificationStatus` | `smtp_verified`, `dns_only`, `unverified`, or `unknown` |
| `emailVerificationNote` | Human-readable verification result |
| `allEmails` | All emails found on the site, each with verification status |
| `socialLinks` | Object with `facebook`, `instagram`, `linkedin`, `twitter` keys |

#### Sample Output Record

```json
{
  "name": "Comfort Air Solutions",
  "category": "HVAC Company",
  "address": "4521 Maple Ave, Dallas, TX 75219",
  "phone": "(214) 555-0192",
  "website": "https://comfortairsolutions.com",
  "mapsUrl": "https://www.google.com/maps/place/...",
  "rating": 4.7,
  "reviewCount": 312,
  "email": "service@comfortairsolutions.com",
  "emailVerified": true,
  "emailVerificationStatus": "smtp_verified",
  "emailVerificationNote": "Verified via SMTP",
  "allEmails": [
    {
      "address": "service@comfortairsolutions.com",
      "verified": true,
      "status": "smtp_verified",
      "verificationNote": "Verified via SMTP"
    }
  ],
  "socialLinks": {
    "facebook": "https://facebook.com/comfortairsolutions",
    "instagram": null,
    "linkedin": null,
    "twitter": null
  }
}
````

### Use Cases

- **HVAC leads and contractor prospecting**: Build an HVAC contractor email list or plumber leads database for any city or region in minutes — ideal for equipment suppliers, parts distributors, and refrigerant wholesalers targeting buying managers by territory.
- **Electrician and roofer lead generation**: Source electrician leads and roofing contractor contacts for product sales, subcontractor recruitment, or regional outreach. Filter by review count to prioritize high-volume, established businesses.
- **Home service SaaS prospecting**: Find home service leads for field service management, scheduling, invoicing, or estimating software by targeting active contractors in your region — sorted by rating to prioritize growth-minded operators.
- **Commercial insurance outreach**: Build targeted contractor email lists for commercial liability, bonding, and workers' comp campaigns. General contractors, electricians, and roofers are high-value prospects for specialty trade insurance.
- **Subcontractor sourcing**: Identify qualified subcontractors by trade, city, and rating. Contact owners directly via verified email rather than sorting through referral networks or online directories.
- **Construction supply and material sales**: Reach plumbing supply buyers, HVAC equipment purchasers, roofing material buyers, and electrical supply contacts by scraping contractors in your distribution territory.
- **Staffing and recruitment**: Identify high-rated home service businesses and reach hiring managers via verified email — far faster than posting on job boards and waiting for inbound applications.

### How It Works

**Phase 1 — Search Google Maps**: The actor queries Google Maps for each contractor type and location you specify, paginating through all results to capture every business listing — not just the first page.

**Phase 2 — Profile Extraction**: For each listing, it pulls the full data panel: business name, category, address, phone number, website URL, star rating, and review count directly from the Google Maps record.

**Phase 3 — Email Discovery**: The actor visits each contractor's website and crawls the homepage, contact page, and footer to find email addresses. Multiple emails per site are captured and stored in `allEmails`.

**Phase 4 — Email Verification**: Every email candidate is checked via DNS/MX lookup and SMTP handshake to confirm deliverability before being marked `emailVerified: true`. No actual emails are sent.

**Phase 5 — Social Media Extraction**: Facebook, Instagram, LinkedIn, and Twitter/X profile links are extracted from each business website for multi-channel outreach.

**Phase 6 — Output and Delivery**: Results stream into the Apify dataset as they complete. Export as JSON, CSV, or Excel, or push directly to HubSpot or Salesforce using the built-in CRM output formats.

### Input Options

| Parameter | Type | Default | Description |
|-|-|-|-|
| `businessType` | select | HVAC Company | Contractor trade type (HVAC, Plumber, Roofer, Electrician, General Contractor, Landscaper, Painter, Pest Control, Custom) |
| `location` | string | Dallas, TX | City, state, or ZIP code (e.g., "Austin, TX" or "30301") |
| `searchQuery` | string | — | Custom query — only used when businessType is "Custom" |
| `maxResults` | integer | 50 | Max leads to return (prefill: 3 for quick test; max: 500) |
| `enrichEmails` | boolean | true | Crawl contractor websites for email addresses |
| `verifyEmails` | boolean | true | Run DNS + SMTP verification on found emails |
| `enrichSocials` | boolean | true | Extract Facebook, Instagram, LinkedIn, Twitter/X links |
| `outputFormat` | string | full | `full`, `hubspot`, or `salesforce` |

### Output Formats

**Full Output** — Every scraped and enriched field: business name, contractor category, verified email, phone, website, complete address, rating, review count, social media links, and Google Maps URL. Best for custom segmentation or multi-step outreach pipelines.

**HubSpot-Ready** — Columns pre-mapped to HubSpot Contact and Company import properties. Drop the file directly into HubSpot's import tool with zero manual remapping. Includes `Company Name`, `Email`, `Phone Number`, `Street Address`, `Website URL`, `Google Maps URL`, `Rating`, `Number of Reviews`, `Industry`, `Facebook Company Page`, `LinkedIn Company Page`, `Twitter Handle`.

**Salesforce-Ready** — Fields aligned to the Salesforce Lead object standard: `Account Name`, `Phone`, `Website`, `Billing Street`, `Email__c`, `Rating__c`, `Review_Count__c`, `Google_Maps_URL__c`, `Facebook__c`, `LinkedIn__c`. `LeadSource` is pre-filled as "Google Maps Scraper" for attribution tracking.

### Why This Actor vs. Apollo or ZoomInfo?

| Feature | This Actor | Apollo / ZoomInfo |
|-|-|-|
| HVAC, plumber, roofer, electrician coverage | Comprehensive via Google Maps | Sparse — built for enterprise SaaS, not trades |
| Local home service leads | Fresh from Google Maps each run | Static database, often incomplete for SMBs |
| Verified contractor emails | Crawled from live business websites | Aged records, 20–40% bounce rates common |
| Cost per lead | Cents at scale | $0.50–$3.00+ per contact |
| Geographic targeting | Any city, ZIP, or metro area | Limited local precision |
| Subscription required | No — pay per run on Apify | Monthly or annual contracts |

Apollo and ZoomInfo are designed for enterprise SaaS deal cycles — they have poor coverage of HVAC companies, plumbers, roofers, and local electrical contractors. This actor pulls directly from Google Maps, where every active home service business maintains a listing, giving you far more relevant contractor leads at a fraction of the cost.

### Why This Actor vs. a General Google Maps Scraper?

| Feature | General Google Maps Scraper | This Actor |
|-|-|-|
| Pre-filtered contractor results | No — returns mixed categories | Yes — every result is a contractor |
| Verified email addresses | Extra add-on | Built-in, included in price |
| Email deliverability check (DNS+SMTP) | Not available | Built-in |
| Social media profiles | Extra add-on | Built-in |
| CRM-ready export (HubSpot, Salesforce) | Not available | Built-in |
| Single-actor simplicity | 2–3 actors chained | One actor, one click |

### Cost Estimation

Each run incurs two types of costs:

1. **Pay-per-event pricing** — You pay per enriched lead returned (see pricing on the actor page).
2. **Platform usage** — Apify charges for compute time and proxy bandwidth used during the run.

Typical costs for a 100-lead run:

- **Run time:** 5–15 minutes
- **Platform usage:** $0.50–$2.00 (depends on proxy type and email enrichment settings)
- **Total per lead:** varies by niche and location density

Tips for cost-effective runs:

- Start with a small test run (10–25 leads) to validate data quality for your target niche
- Disable email verification (`verifyEmails: false`) if you plan to verify in a separate tool
- Use specific locations (city + state) rather than broad regions to maximize result density

### Getting Started

1. [Create a free Apify account](https://apify.com) if you do not already have one.
2. Open the Contractor Lead Scraper actor page and click **Try for free**.
3. Select your `businessType` (e.g., HVAC Company, Plumber, Roofer) and enter your `location`.
4. Click **Start** and watch verified home service leads populate your dataset in real time.
5. Export as CSV or JSON, or connect directly to HubSpot or Salesforce using the built-in output formats.

For bulk territory builds, custom contractor categories, or dedicated support, reach out through the Apify actor page. If this actor saves you time, please [leave a review](https://apify.com/samstorm/contractor-lead-scraper/reviews) — it helps other users find this tool.

### Use via Apify API

```javascript
import { ApifyClient } from 'apify-client';

const client = new ApifyClient({ token: 'YOUR_API_TOKEN' });

// Example: get HVAC contractor leads in Dallas
const run = await client.actor('samstorm/contractor-lead-scraper').call({
    businessType: 'HVAC Company',
    location: 'Dallas, TX',
    maxResults: 100,
    enrichEmails: true,
    verifyEmails: true,
    outputFormat: 'hubspot',
});

const { items } = await client.dataset(run.defaultDatasetId).listItems();
console.log(`Got ${items.length} HVAC contractor leads`);
```

#### Python

```python
from apify_client import ApifyClient

client = ApifyClient('YOUR_API_TOKEN')

run = client.actor('samstorm/contractor-lead-scraper').call(run_input={
    'businessType': 'HVAC Company',
    'location': 'Dallas, TX',
    'maxResults': 100,
    'enrichEmails': True,
    'verifyEmails': True,
    'outputFormat': 'hubspot',
})

items = client.dataset(run['defaultDatasetId']).list_items().items
print(f'Got {len(items)} HVAC contractor leads')
```

### Multi-Location Workflows (200k+ leads/month)

Google Maps returns up to ~120 results per search query, so large-scale prospecting requires running the actor once per city or metro area and merging the datasets. Here's how to automate this:

**Option 1: Apify API loop** — Call the actor programmatically for each location in your territory:

```javascript
const locations = ['Houston, TX', 'Dallas, TX', 'Austin, TX', 'San Antonio, TX'];

for (const location of locations) {
    const run = await client.actor('samstorm/contractor-lead-scraper').call({
        businessType: 'HVAC Company',
        location,
        maxResults: 200,
        enrichEmails: true,
        verifyEmails: true,
    });
    console.log(`Completed ${location}: run ${run.id}`);
}
```

**Option 2: Apify Schedules** — Set up a schedule in the Apify Console that triggers runs for different locations on a recurring basis. Use a separate Saved Task for each city.

**Deduplication across runs:** Each run deduplicates internally by business name + address. When merging datasets from multiple runs, deduplicate on the same key (`name + address`) to remove businesses that appear in overlapping metro areas.

### Integrations

This actor works with the full Apify ecosystem and popular automation platforms:

- **Apify API & Webhooks** — Trigger runs programmatically and receive results via webhook when complete
- **Zapier** — Connect to 5,000+ apps using the [Apify Zapier integration](https://zapier.com/apps/apify)
- **Make (Integromat)** — Build multi-step automations with the [Apify Make module](https://www.make.com/en/integrations/apify)
- **Google Sheets** — Export results directly to a spreadsheet using Apify's built-in Google Sheets integration
- **Slack** — Get notified in Slack when a run completes using Apify's webhook notifications

### Contractor Lead Generation FAQ

**How do I build a contractor email list?**
Select your target contractor type (HVAC Company, Plumber, Roofer, Electrician, etc.) and enter the cities or ZIP codes you want to cover, then click Start. The actor queries Google Maps, crawls each contractor's website for contact emails, runs DNS and SMTP verification on every address, and delivers a clean, verified list ready to export or push to your CRM. No scraping experience required.

**What types of contractors can I scrape leads for?**
All major residential and commercial trades are supported: HVAC companies, plumbers, roofers, electricians, general contractors, painters, landscapers, pest control companies, and more. The "Custom" business type lets you target any niche that appears on Google Maps — concrete contractors, fencing companies, flooring installers, waterproofing specialists, pool builders, or any other home service trade.

**How much does building a contractor leads database cost?**
Unlike static list vendors that charge $500–$5,000 for a fixed contractor database that may be months old, this actor uses pay-per-lead pricing. Typical cost for a 100-lead run (including email verification) is a few dollars in Apify platform usage plus the per-lead fee shown on the actor page. There is no annual contract, and you get fresh data every time you run.

**Can I filter contractor leads by city, ZIP code, or region?**
Yes — location targeting is a core feature. Specify individual cities ("Austin, TX"), ZIP codes, county names, or metro area terms. Each location runs as a separate Google Maps search, giving comprehensive local coverage for regional suppliers, insurance brokers, or SaaS companies doing territory-based prospecting across the construction industry.

**How do I export contractor leads to HubSpot or Salesforce?**
Set `outputFormat` to `hubspot` or `salesforce` before running. HubSpot format maps columns directly to HubSpot Contact and Company import properties — drop the CSV into HubSpot's import tool with zero remapping. Salesforce format aligns to the Lead object standard with `LeadSource` pre-filled for attribution tracking.

**How are contractor emails verified?**
Every email found on a contractor's website goes through two-stage verification: a DNS/MX lookup confirms the domain is configured to receive mail, then an SMTP handshake probes the specific mailbox to confirm it exists — without sending any actual message. The `emailVerified: true` flag means the address passed both checks. This eliminates the 20–40% bounce rates common with purchased contractor lists.

**Why are contractor emails missing for some records?**
Email extraction depends on the business having a website with contact information visible in the HTML (not behind a contact form). Some contractors list only phone numbers or use only Facebook pages instead of a dedicated website. Records without emails still contain phone, address, and rating — useful for phone outreach or manual follow-up.

**How many contractor leads can I get per run?**
Google Maps typically returns up to ~120 results per search query. For larger datasets — say, all HVAC companies in Texas — run the actor multiple times with different city or ZIP inputs and combine the datasets. Each run deduplicates by business name and address, so overlapping results are automatically removed.

**How is this better than buying a static contractor list?**
Static contractor databases (InfoUSA, Lead411, D\&B) are compiled from trade directories that can be 6–24 months stale. They frequently lack emails for small trade shops, and when emails are present they often belong to a generic `info@` address rather than the owner. This actor pulls live from Google Maps and crawls each contractor's own website — so you get current business status, the actual published contact email, verified deliverability, and ratings to filter for high-quality prospects.

**Can I use this to find subcontractors?**
Yes. Search by trade type and location to identify qualified subcontractors in your area. Sort your export by `reviewCount` or `rating` to prioritize established businesses. Verified emails let you reach owners directly without going through referral networks or trade directories.

### Limitations

- Google Maps typically returns up to ~120 results per search query. Use multiple locations for larger datasets.
- Email extraction depends on the business having a website with publicly visible contact info. Businesses using only contact forms will not have emails extracted.
- SMTP verification may be blocked by some mail servers, resulting in `unknown` status rather than confirmed valid or invalid.
- This actor finds business and professional emails only — not personal consumer emails.
- Results reflect what is currently listed on Google Maps and may not include every contractor in a given market.

### Recent Updates

- **March 2026** — Version 1.0 release: production-ready with verified email pipeline
- **March 2026** — Optimized proxy usage with aggressive resource blocking — ~50% cost reduction per run
- **March 2026** — Added fail-fast error recovery: blocked requests abort immediately instead of retrying
- **March 2026** — Added social media link extraction (Facebook, Instagram, LinkedIn, Twitter/X)

### Related Lead Scrapers by samstorm

Build a complete prospecting database across industries with verified email enrichment:

| Actor | What It Does | Best For | Try It |
|---|---|---|---|
| [Dentist Lead Scraper](https://apify.com/samstorm/dentist-lead-scraper) | Verified emails from dental & medical practices | Dental supply sales, healthcare SaaS, medical recruiters | [Try free](https://apify.com/samstorm/dentist-lead-scraper) |
| [Lawyer Lead Scraper](https://apify.com/samstorm/lawyer-lead-scraper) | Attorney & law firm contact extraction | Legal tech sales, court reporting services, legal marketing | [Try free](https://apify.com/samstorm/lawyer-lead-scraper) |
| [Restaurant Lead Scraper](https://apify.com/samstorm/restaurant-lead-scraper) | Restaurant, bar, and cafe owner contacts | Food suppliers, POS system sales, restaurant tech | [Try free](https://apify.com/samstorm/restaurant-lead-scraper) |
| [Real Estate Lead Scraper](https://apify.com/samstorm/real-estate-lead-scraper) | Agent, broker, and property manager emails | Mortgage lenders, PropTech, real estate marketing | [Try free](https://apify.com/samstorm/real-estate-lead-scraper) |
| [Auto Dealer Lead Scraper](https://apify.com/samstorm/auto-dealer-lead-scraper) | Car dealership and auto shop contacts | Auto parts suppliers, dealer management software, F\&I products | [Try free](https://apify.com/samstorm/auto-dealer-lead-scraper) |
| [Wedding Vendor Lead Scraper](https://apify.com/samstorm/wedding-vendor-lead-scraper) | Venue, photographer, planner contacts | Wedding SaaS platforms, bridal advertising | [Try free](https://apify.com/samstorm/wedding-vendor-lead-scraper) |
| [Financial Advisor Lead Scraper](https://apify.com/samstorm/financial-advisor-lead-scraper) | Financial advisor and insurance agent emails | FinTech sales, compliance software, wealth management | [Try free](https://apify.com/samstorm/financial-advisor-lead-scraper) |
| [Veterinarian Lead Scraper](https://apify.com/samstorm/veterinarian-lead-scraper) | Vet clinic and pet service contacts | Pet supply distributors, veterinary SaaS | [Try free](https://apify.com/samstorm/veterinarian-lead-scraper) |
| [B2B Lead Enrichment](https://apify.com/samstorm/lead-enrichment-actor) | Google Maps to CRM for any business type | General B2B prospecting, custom niche research | [Try free](https://apify.com/samstorm/lead-enrichment-actor) |

[See all actors by samstorm](https://apify.com/samstorm)

### Help Us Improve

If this actor saves you time, please leave a review on the Apify Store. Your feedback helps other users discover this tool and helps us prioritize improvements. Report issues or request features through the Issues tab on the actor page.

# Actor input Schema

## `businessType` (type: `string`):

Select the contractor trade to search on Google Maps. The actor builds the query automatically — e.g., 'HVAC Company' finds heating, cooling, and air conditioning contractors in your city; 'Plumber' finds licensed plumbing contractors; 'Roofer' finds roofing companies; 'Electrician' finds electrical contractors. Choose 'Custom' to write your own search query for any other trade type.

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

The city, state, or ZIP code to search for contractors in. Use 'City, ST' format for best results (e.g., 'Dallas, TX', 'Phoenix, AZ', 'Chicago, IL'). ZIP codes and neighborhoods also work. For multi-city coverage, run the actor once per location and merge datasets — each run fully covers one market.

## `searchQuery` (type: `string`):

A raw Google Maps search query — only used when Business Type is set to 'Custom'. Use this to target trades not in the dropdown, such as 'concrete contractors in Denver, CO', 'pool builders near Orlando, FL', or 'waterproofing companies in Seattle, WA'. Write the query exactly as you would type it into Google Maps.

## `maxResults` (type: `integer`):

Maximum number of contractor leads to return. The prefill is 3 for a quick quality test — increase to 50–200 for production prospecting. Google Maps caps at ~120 results per search; run multiple locations to build larger datasets. Start small to verify results match your target trade and geography before scaling.

## `enrichEmails` (type: `boolean`):

When enabled, the actor visits each contractor's website and scans contact pages, footers, and about pages to extract email addresses. Disable if you only need phone numbers and addresses, or to run faster without website crawling. Most HVAC, plumbing, and electrical contractor sites publish a contact email in the footer or on a Contact page.

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

When enabled, each extracted email is checked via DNS/MX lookup and SMTP handshake to confirm the mailbox exists and can receive mail — without sending any actual message. Adds ~1 minute per batch but significantly reduces bounce rates on outreach campaigns. Only applies when 'Find Email Addresses' is enabled. Verified emails are flagged with emailVerified: true in the output.

## `enrichSocials` (type: `boolean`):

When enabled, the actor scans each contractor website for social media profile links: Facebook, Instagram, LinkedIn, and Twitter/X. Useful for multi-channel outreach, ad targeting (Facebook Custom Audiences), and account research before contacting. Many HVAC and plumbing companies are active on Facebook even when they lack a strong website.

## `outputFormat` (type: `string`):

Controls the structure of the output dataset. 'Full' returns all fields for custom pipelines. 'HubSpot Import' maps columns to HubSpot Contact and Company import properties for direct CSV upload with zero remapping. 'Salesforce Import' aligns to the Salesforce Lead object with LeadSource pre-filled. All formats are downloadable from Apify as CSV, JSON, or Excel.

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

Optional HTTP proxy URL for using third-party residential proxies instead of Apify's built-in proxies. Format: http://username:password@host:port. Compatible with IPRoyal, Smartproxy, Bright Data, and other rotating proxy services. Leave empty to use Apify's default residential proxies.

## Actor input object example

```json
{
  "businessType": "Plumber",
  "location": "Dallas, TX",
  "searchQuery": "emergency plumbers near Houston, TX",
  "maxResults": 50,
  "enrichEmails": true,
  "verifyEmails": true,
  "enrichSocials": true,
  "outputFormat": "hubspot",
  "proxyUrl": "http://user:pass@proxy.example.com:8080"
}
```

# Actor output Schema

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

No description

# API

You can run this Actor programmatically using our API. Below are code examples in JavaScript, Python, and CLI, as well as the OpenAPI specification and MCP server setup.

## JavaScript example

```javascript
import { ApifyClient } from 'apify-client';

// Initialize the ApifyClient with your Apify API token
// Replace the '<YOUR_API_TOKEN>' with your token
const client = new ApifyClient({
    token: '<YOUR_API_TOKEN>',
});

// Prepare Actor input
const input = {
    "location": "Dallas, TX",
    "searchQuery": "HVAC companies in Dallas, TX",
    "maxResults": 3
};

// Run the Actor and wait for it to finish
const run = await client.actor("samstorm/contractor-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 = {
    "location": "Dallas, TX",
    "searchQuery": "HVAC companies in Dallas, TX",
    "maxResults": 3,
}

# Run the Actor and wait for it to finish
run = client.actor("samstorm/contractor-lead-scraper").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 '{
  "location": "Dallas, TX",
  "searchQuery": "HVAC companies in Dallas, TX",
  "maxResults": 3
}' |
apify call samstorm/contractor-lead-scraper --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "command": "npx",
            "args": [
                "mcp-remote",
                "https://mcp.apify.com/?tools=samstorm/contractor-lead-scraper",
                "--header",
                "Authorization: Bearer <YOUR_API_TOKEN>"
            ]
        }
    }
}

```

## OpenAPI specification

```json
{
    "openapi": "3.0.1",
    "info": {
        "title": "Contractor Lead Scraper — Verified Emails (HVAC, Plumbing)",
        "description": "Scrape HVAC, plumber, roofer & electrician contacts from Google Maps with verified emails & phones. Real-time data from contractor websites. Export to HubSpot, Salesforce, or CSV. Built for home services marketing & SaaS sales.",
        "version": "1.0",
        "x-build-id": "fc6kfFvRT8laRQ8qh"
    },
    "servers": [
        {
            "url": "https://api.apify.com/v2"
        }
    ],
    "paths": {
        "/acts/samstorm~contractor-lead-scraper/run-sync-get-dataset-items": {
            "post": {
                "operationId": "run-sync-get-dataset-items-samstorm-contractor-lead-scraper",
                "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/samstorm~contractor-lead-scraper/runs": {
            "post": {
                "operationId": "runs-sync-samstorm-contractor-lead-scraper",
                "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/samstorm~contractor-lead-scraper/run-sync": {
            "post": {
                "operationId": "run-sync-samstorm-contractor-lead-scraper",
                "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": [
                    "businessType",
                    "location"
                ],
                "properties": {
                    "businessType": {
                        "title": "Business Type",
                        "enum": [
                            "HVAC Company",
                            "Plumber",
                            "Roofer",
                            "Electrician",
                            "General Contractor",
                            "Landscaper",
                            "Painter",
                            "Pest Control",
                            "Custom"
                        ],
                        "type": "string",
                        "description": "Select the contractor trade to search on Google Maps. The actor builds the query automatically — e.g., 'HVAC Company' finds heating, cooling, and air conditioning contractors in your city; 'Plumber' finds licensed plumbing contractors; 'Roofer' finds roofing companies; 'Electrician' finds electrical contractors. Choose 'Custom' to write your own search query for any other trade type.",
                        "default": "HVAC Company"
                    },
                    "location": {
                        "title": "Location",
                        "type": "string",
                        "description": "The city, state, or ZIP code to search for contractors in. Use 'City, ST' format for best results (e.g., 'Dallas, TX', 'Phoenix, AZ', 'Chicago, IL'). ZIP codes and neighborhoods also work. For multi-city coverage, run the actor once per location and merge datasets — each run fully covers one market."
                    },
                    "searchQuery": {
                        "title": "Custom Search Query",
                        "type": "string",
                        "description": "A raw Google Maps search query — only used when Business Type is set to 'Custom'. Use this to target trades not in the dropdown, such as 'concrete contractors in Denver, CO', 'pool builders near Orlando, FL', or 'waterproofing companies in Seattle, WA'. Write the query exactly as you would type it into Google Maps."
                    },
                    "maxResults": {
                        "title": "Max Results",
                        "minimum": 1,
                        "maximum": 500,
                        "type": "integer",
                        "description": "Maximum number of contractor leads to return. The prefill is 3 for a quick quality test — increase to 50–200 for production prospecting. Google Maps caps at ~120 results per search; run multiple locations to build larger datasets. Start small to verify results match your target trade and geography before scaling.",
                        "default": 50
                    },
                    "enrichEmails": {
                        "title": "Find Email Addresses",
                        "type": "boolean",
                        "description": "When enabled, the actor visits each contractor's website and scans contact pages, footers, and about pages to extract email addresses. Disable if you only need phone numbers and addresses, or to run faster without website crawling. Most HVAC, plumbing, and electrical contractor sites publish a contact email in the footer or on a Contact page.",
                        "default": true
                    },
                    "verifyEmails": {
                        "title": "Verify Email Deliverability",
                        "type": "boolean",
                        "description": "When enabled, each extracted email is checked via DNS/MX lookup and SMTP handshake to confirm the mailbox exists and can receive mail — without sending any actual message. Adds ~1 minute per batch but significantly reduces bounce rates on outreach campaigns. Only applies when 'Find Email Addresses' is enabled. Verified emails are flagged with emailVerified: true in the output.",
                        "default": true
                    },
                    "enrichSocials": {
                        "title": "Find Social Media Links",
                        "type": "boolean",
                        "description": "When enabled, the actor scans each contractor website for social media profile links: Facebook, Instagram, LinkedIn, and Twitter/X. Useful for multi-channel outreach, ad targeting (Facebook Custom Audiences), and account research before contacting. Many HVAC and plumbing companies are active on Facebook even when they lack a strong website.",
                        "default": true
                    },
                    "outputFormat": {
                        "title": "Output Format",
                        "enum": [
                            "full",
                            "hubspot",
                            "salesforce"
                        ],
                        "type": "string",
                        "description": "Controls the structure of the output dataset. 'Full' returns all fields for custom pipelines. 'HubSpot Import' maps columns to HubSpot Contact and Company import properties for direct CSV upload with zero remapping. 'Salesforce Import' aligns to the Salesforce Lead object with LeadSource pre-filled. All formats are downloadable from Apify as CSV, JSON, or Excel.",
                        "default": "full"
                    },
                    "proxyUrl": {
                        "title": "Custom Proxy URL (optional)",
                        "type": "string",
                        "description": "Optional HTTP proxy URL for using third-party residential proxies instead of Apify's built-in proxies. Format: http://username:password@host:port. Compatible with IPRoyal, Smartproxy, Bright Data, and other rotating proxy services. Leave empty to use Apify's default residential proxies."
                    }
                }
            },
            "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
                                    }
                                }
                            }
                        }
                    }
                }
            }
        }
    }
}
```
