# 🔧 Plumber & HVAC Leads Scraper - Contractor Emails & Phones (`renzomacar/plumber-hvac-leads-scraper`) Actor

Get plumber leads and HVAC leads for any city in minutes: company, phone, website, address, emails and social profiles pulled live from each contractor's website. Built for lead-gen agencies and vendors selling to home-service contractors. $8 per 1,000 leads.

- **URL**: https://apify.com/renzomacar/plumber-hvac-leads-scraper.md
- **Developed by:** [Renzo Madueno](https://apify.com/renzomacar) (community)
- **Categories:** Lead generation, Business
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $7.44 / 1,000 leads

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

Learn more: https://docs.apify.com/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

## 🔧 Plumber & HVAC Leads Scraper — Contractor Emails & Phones

Selling to plumbers and HVAC companies — software, lead-gen services, financing, equipment, marketing? Your prospect list is out there on the map, and it changes every month as contractors open, close and rebrand. This Actor turns any city into a fresh contractor list in minutes: business name, phone, website, address, **emails and social profiles pulled live from each contractor's own website** — for $8 per 1,000 leads, no subscription.

### Who this is built for

- **Lead-gen and PPC agencies** selling "we get you booked jobs" to home-service contractors — build your outreach list per metro before you pitch.
- **Home-services SaaS** (field service management, booking, invoicing tools) — feed your SDRs a fresh territory every week.
- **Equipment and parts distributors** — map every HVAC contractor in your delivery radius.
- **Franchise development teams** — find independent shops worth recruiting.

### What each contractor lead contains

| Field | Example |
|---|---|
| `name` | Reliable Rooter & Drain |
| `category` | Plumber |
| `phone` | +1 713-555-0182 |
| `website` | reliablerooterhouston.com |
| `email` + `emails[]` | service@reliablerooterhouston.com |
| `socialProfiles` | Facebook, Instagram, LinkedIn, Twitter |
| `address`, `city`, `country` | 4210 Washington Ave, Houston, United States |
| `rating`, `reviewsCount` | 4.7, 289 |
| `techStack[]` | WordPress, Google Analytics — spot outdated sites to pitch |
| `placeUrl` | Google Maps link for manual verification |

### How a run works

1. Pick a **location** ("Houston, TX") and optionally the **service types** you care about — plumber, emergency plumber, hvac contractor, ac repair, drain cleaning, water heater installation. Leave the list empty and it searches all common types at once.
2. The Actor discovers matching contractors on the live Google Maps business index.
3. It then visits each contractor's website (homepage, /contact, /about) and extracts emails, extra phone numbers and socials.
4. One clean row per contractor lands in the dataset — export CSV/Excel/JSON or pull via API into your CRM or cold-email tool (Instantly, Smartlead, Lemlist).

A 5-lead test run finishes in about a minute; 100 contractors typically take a few minutes.

### Pricing

- **$0.008 per contractor lead** delivered — $8 per 1,000
- $0.01 one-time start fee per run

Every plumbing + HVAC shop in a large metro (often 300–600 businesses) costs **$3–5**. Compare that with buying a static contractor list that was compiled a year ago.

### Example input

```json
{
  "location": "Houston, TX",
  "keywords": ["plumber", "hvac contractor"],
  "maxResults": 100,
  "maxPagesPerSite": 2
}
```

Cover several cities in one run with `searchQueries`: `["emergency plumber in Denver, CO", "hvac contractor in Colorado Springs, CO"]`.

### FAQ

**Do all contractors come with an email?**
No — only what a contractor publishes on their own site can be extracted. In home services, typically 40–65% of contractors with a website list an email. Every row carries an `emailFound` flag so you can filter, and every row still has the phone number, which for contractors is often the better channel anyway.

**Many small plumbers have no website at all. What happens to them?**
By default they are still delivered (name, phone, address, rating) — great for cold-calling lists. Set `onlyWithWebsite: true` to drop them; you are never charged for dropped businesses.

**Can I target only emergency/24-hour plumbers or only commercial HVAC?**
Yes — that's what the `keywords` field is for. "emergency plumber", "commercial hvac", "furnace repair", "sewer line repair" all work as separate searches and the results are tagged with the `searchQuery` that found them.

**How fresh is the data?**
Scraped at run time, not from a database. If a shop changed its phone number or launched a new site last week, that's what you get.

**Is it legal to scrape this?**
The Actor collects publicly listed business information and emails that companies publish on their own websites to be contacted. You are responsible for using the data lawfully — respect CAN-SPAM for US cold email and GDPR if you target the EU.

**How do I find contractors with bad websites to pitch redesigns?**
Check the `techStack` field: contractors still on an old WordPress build with no analytics are your warmest web-design and SEO prospects.

**Can I run this weekly per territory?**
Yes — schedule it on Apify (e.g. every Monday per metro) and diff against your CRM to catch newly opened shops before your competitors call them.

**What does a run that finds nothing cost?**
Just the $0.01 start fee. Broaden the keyword or use a bigger city and rerun.

### Related tools by the same author

- [B2B Leads Finder](https://apify.com/renzomacar/b2b-leads-finder) — same engine, any industry.
- [Website Contact Finder](https://apify.com/renzomacar/website-contact-finder) — already have contractor websites? Extract contacts in bulk.
- [Email Verifier](https://apify.com/renzomacar/email-verifier) — verify before you send.

### Water heater, septic and sewer service companies

The default sweep looks for plumbers and HVAC contractors. The service specialists next door are a distinct buyer segment with their own Maps categories, and they are reached by putting full searches into **Custom search queries** (which then override the keyword list and `location`):

```
water heater installation company in Sacramento, CA
tankless water heater installer in Roseville, CA
septic tank service in Elk Grove, CA
sewer line repair company in Sacramento, CA
drain cleaning service in Folsom, CA
```

Manufacturers and distributors selling tanks, pumps and jetting equipment usually want exactly this slice and nothing else — a general "plumber" sweep buries them under service-call shops that never touch a tank.

### Boilers, radiant heat and hydronics

A northern-market segment that barely exists in Sun Belt data and is invisible in a generic HVAC list:

```
boiler repair company in Buffalo, NY
boiler installation contractor in Rochester, NY
radiant floor heating installer in Syracuse, NY
hydronic heating contractor in Albany, NY
oil furnace service in Utica, NY
```

Two practical notes. Run these in autumn if you want anyone to pick up — hydronics shops are unreachable from the first hard freeze onward. And because many are second-generation family firms on an old website, `techStack` is frequently empty or shows nothing but jQuery: a signal in itself if what you sell is a website.

### Where the emails actually come from

There is no magic list behind this. For every contractor with a website, the actor fetches that site over plain HTTP and reads the pages most likely to carry a mailbox, in this order:

`/` · `/contact` · `/contact-us` · `/about` · `/about-us` · `/contacto` · `/team` · `/impressum`

`maxPagesPerSite` decides how far down that list it goes (1 to 8; the default is 2). Each site gets an 18-second wall and each individual request an 8-second timeout, so one slow server cannot hold up the run — it is dropped and the business is still delivered with its Maps data. Sites whose "website" field points at Facebook, Instagram, TikTok, YouTube or Google are skipped outright, because none of them will ever hand over the contractor's own address.

Addresses are deduplicated per company, obvious placeholders (`name@example.com`, `user@yourdomain.com`, tracking addresses) are discarded, and nothing is ever generated or guessed: if the company does not publish an email, `emailFound` is `false` and `emails` is empty.

# Actor input Schema

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

City, region or country to search in, e.g. 'Houston, TX', 'San Diego, CA', 'London, UK'.

## `keywords` (type: `array`):

Which contractor types to search for, one per line. Good options: 'plumber', 'emergency plumber', 'hvac contractor', 'ac repair', 'drain cleaning', 'water heater installation', 'furnace repair', 'sewer line repair'. Leave empty to search all common plumbing & HVAC types at once.

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

Full searches, one per line (e.g. 'plumber in Houston, TX'). When set, these override Location + service types. Use several queries to cover multiple cities in one run.

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

Maximum number of companies to find per search. One search typically yields up to ~120 companies.

## `maxPagesPerSite` (type: `integer`):

How many pages to check on each company website when hunting for emails (homepage, /contact, /about...). More pages = more emails found, slightly slower run.

## `onlyWithWebsite` (type: `boolean`):

Drop companies that have no website (they can never have an email). You are not charged for dropped companies.

## `includeGenericEmails` (type: `boolean`):

Keep every published address, including shared inboxes like info@, hello@ and contact@. Disable to drop only non-deliverable system addresses (noreply@, no-reply@, donotreply@, mailer-daemon@, postmaster@, webmaster@, hostmaster@, abuse@).

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

Language code for the discovery search (e.g. 'en', 'es', 'fr', 'de').

## Actor input object example

```json
{
  "location": "Houston, TX",
  "keywords": [
    "plumber"
  ],
  "maxResults": 5,
  "maxPagesPerSite": 1,
  "onlyWithWebsite": false,
  "includeGenericEmails": true,
  "language": "en"
}
```

# Actor output Schema

## `leads` (type: `string`):

Plumber & HVAC Leads Scraper results (business, website, phone, address, emails, social profiles), one item per lead in the default dataset.

# 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": "Houston, TX",
    "keywords": [
        "plumber"
    ],
    "maxResults": 5,
    "maxPagesPerSite": 1
};

// Run the Actor and wait for it to finish
const run = await client.actor("renzomacar/plumber-hvac-leads-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": "Houston, TX",
    "keywords": ["plumber"],
    "maxResults": 5,
    "maxPagesPerSite": 1,
}

# Run the Actor and wait for it to finish
run = client.actor("renzomacar/plumber-hvac-leads-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 '{
  "location": "Houston, TX",
  "keywords": [
    "plumber"
  ],
  "maxResults": 5,
  "maxPagesPerSite": 1
}' |
apify call renzomacar/plumber-hvac-leads-scraper --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,renzomacar/plumber-hvac-leads-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/enprHg1jxT77kzUxq/builds/Z6mbs3ZhMVe2QpmQG/openapi.json
