# 🏗️ Contractor Leads Scraper - Construction Company Emails (`renzomacar/contractor-leads-scraper`) Actor

Construction company leads by trade and city: company name, address, phone, website, emails and social profiles extracted live from each company's own website. $8 per 1,000 contractor leads.

- **URL**: https://apify.com/renzomacar/contractor-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

## 🏗️ Contractor Leads Scraper — Construction Company Emails

Contractors spend money when you can reach them — building-materials suppliers, equipment rental, insurance and bonding agents, construction software, lead-resellers and marketing agencies all live off contractor lists. The problem: construction is fragmented across dozens of trades and thousands of small firms with no central directory. This scraper solves it trade by trade, city by city: **company name, trade category, address, office phone, website, emails extracted from the company's own site, extra phone numbers, social profiles, rating and review count** — $8 per 1,000 construction companies.

### Trades covered out of the box

Select any mix in the input (each becomes its own search):

| Trade | Who buys these leads |
|---|---|
| `general contractor` | Materials suppliers, construction SaaS, bonding agents |
| `roofing contractor` | Shingle/metal manufacturers, storm-restoration lead sellers |
| `plumbing contractor` | Wholesalers, home-warranty networks, dispatch software |
| `electrician` | Electrical suppliers, EV-charger programs |
| `HVAC contractor` | Equipment brands, maintenance-plan platforms |
| `remodeling contractor` | Kitchen/bath brands, financing providers |

Anything else — `excavation contractor in Tulsa, OK`, `concrete contractor in Boise, ID`, `painters in Las Vegas, NV` — goes in the custom-queries box, one search per line.

### Why live scraping beats contractor list vendors

Construction has the highest business churn of any B2B vertical: licenses lapse, LLCs dissolve, crews rebrand after a bad review cycle. A list bought in January is fiction by June. This actor discovers companies from the live Google Maps index the moment you run it, then crawls each company's public website for emails and contacts — so a roofer who registered in March is on your list in April, and the guy who folded isn't.

Extra signal built into every row:

- **`reviewsCount` + `rating`** — a proxy for job volume and quality; 200+ reviews means an established operation with real purchasing power.
- **`techStack`** — contractors on an ancient website are prime targets for web/marketing services.
- **`websitePhones[]`** — office lines beyond the Maps number; often the direct line that isn't answered by an IVR.
- **`latitude`/`longitude`** — territory mapping for field reps and route sales.

### Getting a list in 3 steps

1. Tick the trades you sell to (default: `general contractor`).
2. Location: `"Dallas, TX"` — or any metro, county seat or town Google Maps knows.
3. Run, then export CSV/Excel for your dialer, or feed the JSON into Clay/Smartlead/your CRM through the Apify API. Schedule it monthly to keep territories fresh.

### FAQ

**How many contractors can I get per metro?**
Google Maps caps each search at roughly 120 results, so 6 trades × Dallas ≈ 400–700 unique companies after cross-trade deduplication. Suburb-level custom queries (Plano, Frisco, Arlington...) multiply that several times over.

**What's the email hit rate for construction companies?**
Around 35–60%. Trades skew lower than office industries — many small crews have a Facebook page instead of a website. Rows without email still carry the Maps phone (the number the owner actually answers), and `socialProfiles.facebook` is a reliable fallback channel in this vertical.

**Can I exclude one-truck operations?**
Post-filter on `reviewsCount` (e.g. ≥ 25) and require `emailFound` or a website — that removes most hobby operations. Conversely, web designers targeting contractors *want* `onlyWithWebsite: false` to find the site-less ones.

**Are these residential or commercial contractors?**
Google Maps mixes both; category plus website content is your tell. Commercial GCs usually surface under `general contractor` with "construction company" categories and higher review counts.

**Does it verify licenses?**
No — it delivers contact data. Cross-reference your state's license board (most publish searchable databases) using the company name and city from the output.

**Can I run it for Canada, UK or Australia?**
Yes — `builder in Leeds, UK`, `plombier in Montréal` (`language: "fr"`), `electrician in Brisbane, Australia` all work through custom queries.

**What does a full-territory pull cost?**
600 leads = $0.02 start + $4.80 = **$4.82**. That's less than one PPC click in the roofing niche.

### Pricing

Pay-per-event, no subscription: **$0.02 per run start** (2 GB memory) + **$0.008 per construction company lead** delivered. Filtered-out companies cost nothing.

### Data sourcing & compliance

All data originates from public sources contractors use to advertise themselves: their Google Maps business profile and their own public website. Nothing is accessed behind logins, and no consumer/homeowner data is collected. Use of the contact data for outreach must follow your jurisdiction's rules (e.g. CAN-SPAM, TCPA for calls/SMS in the US, GDPR in the EU).

### Foundation repair, waterproofing and structural trades

The six presets cover the trades most people ask for first. The specialty trades — often the ones with the biggest ticket sizes — come from **Custom search queries**, which override both the trade picker and `location`:

```
foundation repair contractor in Kansas City, MO
basement waterproofing company in Overland Park, KS
crawl space encapsulation contractor in Kansas City, MO
structural engineer contractor in Independence, MO
```

These companies typically run a single truck-based crew with one office phone and a lead-gen landing page, so `phone` and `contactPageUrl` land on almost every row while `emailFound` runs lower than it does for remodelers.

### Pool builders, insulation crews and garage door installers

Three trades that never appear in generic "contractor" lists because Maps files them under their own categories:

```
pool builder in Sarasota, FL
spa and hot tub installer in Sarasota, FL
insulation contractor in Bradenton, FL
spray foam insulation company in Bradenton, FL
garage door installer in Venice, FL
```

Seasonality matters when you buy this list: pool and hardscape crews book out in spring and answer the phone in autumn, insulation crews are the reverse. `reviewsCount` is your proxy for crew size — under about 15 reviews is usually an owner-operator who will take the call himself.

### Excavation, demolition and site work

```
excavation contractor in Nashville, TN
demolition contractor in Nashville, TN
grading and site work contractor in Murfreesboro, TN
septic installation contractor in Franklin, TN
land clearing company in Lebanon, TN
```

Heavy-civil outfits are the least likely of any trade to publish an email — many still run a one-page site or none at all. Leave `onlyWithWebsite` off for this segment: a row with only a name, address and phone is still a usable lead here, and you are charged the same whether the email was found or not, so filtering these out costs you coverage without saving money.

# Actor input Schema

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

Which construction trades to find. Each selected trade runs as its own search in your location; companies found under several trades are deduplicated.

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

City, region or country to search in, e.g. 'Dallas, TX', 'Austin, TX', 'London, UK'.

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

Full searches, one per line (e.g. 'concrete contractor in Boise, ID'). When set, these override the category picker + location. Use several queries to cover multiple cities or neighborhoods 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
{
  "searchTerms": [
    "general contractor"
  ],
  "location": "Dallas, TX",
  "maxResults": 5,
  "maxPagesPerSite": 1,
  "onlyWithWebsite": false,
  "includeGenericEmails": true,
  "language": "en"
}
```

# Actor output Schema

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

Complete B2B leads (company, 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 = {
    "searchTerms": [
        "general contractor"
    ],
    "location": "Dallas, TX",
    "maxResults": 5,
    "maxPagesPerSite": 1
};

// Run the Actor and wait for it to finish
const run = await client.actor("renzomacar/contractor-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 = {
    "searchTerms": ["general contractor"],
    "location": "Dallas, TX",
    "maxResults": 5,
    "maxPagesPerSite": 1,
}

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

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,renzomacar/contractor-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/0Ct5yf88b6c2QilTd/builds/JYXqR24SezJnzqenp/openapi.json
