# Angi Email Scraper (`leads-scraper/angi-email-scraper`) Actor

Angi Email Scraper SD - Angi Email Scraper is a lead generation tool that extracts leads with public contact emails, account names and profile URLs from Angi results by keyword, location and email domain - Angi email extractor.

- **URL**: https://apify.com/leads-scraper/angi-email-scraper.md
- **Developed by:** [Leads Scraper](https://apify.com/leads-scraper) (community)
- **Stats:** 1 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $2.49 / 1,000 results

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

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

## What's an Apify Actor?

An Actor is a serverless cloud program that runs on the Apify platform. It has two run modes.
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.

Apify vocabulary and the platform model are defined once, in the agent quickstart at https://apify.com/agents.md.

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

Do not guess an integration path. Every one of them is in the agent quickstart at https://apify.com/agents.md: the Apify MCP server, Agent Skills with the Apify CLI, the JavaScript and Python clients, the REST API, and the account-free path for an agent with no human to sign in. It also carries the rule on stating cost before the first paid run.

For examples already wired to this Actor's own input schema, see the [API](#api) section below.

Each client library has reference documentation the quickstart does not restate: [JavaScript/TypeScript](https://docs.apify.com/api/client/js/docs.md) (`npm install apify-client`) and [Python](https://docs.apify.com/api/client/python/docs.md) (`pip install apify-client`).

# README

### Angi Email Scraper

The Angi Email Scraper extracts publicly indexed contractor contacts from Angi and its sister sites using Google search.
It queries three domains in one run: `angi.com`, `homeadvisor.com` and `angieslist.com`.
That triple coverage is what separates this Actor from every other home-services scraper in the category.

You supply keywords, an optional location and the email domains you care about.
It returns a deduplicated dataset with the company name, the Angi handle, the company-list URL and a listing snippet.
No login, no Angi API and no visit to angi.com is involved at any point.

Everything comes from publicly available Google search results: titles, snippets and site labels.
There is no browser, no JavaScript rendering, no authentication and no cookies.
That is what keeps the Angi Email Scraper cheap to run and stable across the platform's own redesigns.

In a measured live run, the Angi Email Scraper returned 10 result blocks, 10 identity matches, 10 profile URLs and 8 unique emails.
Every block resolved to a named contractor with a working profile URL, and eight of ten carried a usable address.
That is a strong result, matched in this category only by Porch, Clutch and the three top performers.

#### Why three-domain coverage makes the Angi Email Scraper different

HomeAdvisor and Angie's List were folded into the Angi brand, but their old URLs still carry indexed contractor pages.
A scraper pointed only at `angi.com` therefore misses a large body of still-live listings.
The Angi Email Scraper searches all three domains in the same run and deduplicates the results globally.

That also means a single contractor can appear under more than one domain.
Global email deduplication ensures you get one row per unique address regardless of which domain produced it.
The `query` field records exactly which search found each lead if you need to audit that later.

### Key features of the Angi Email Scraper

Everything below is behaviour the Angi Email Scraper actually implements, shared with every Actor in this family.

| Feature | What it does |
|---|---|
| Triple-domain `site:` targeting | Queries `angi.com`, `homeadvisor.com` and `angieslist.com` in the same run |
| Query expansion | Base, quoted and `intitle:` variants plus one variant per query modifier |
| Trade-intent modifiers | Defaults of `email`, `contact`, `enquiries`, `owner` and `get a quote` |
| Domain filtering | Keeps only emails ending in the domains you list |
| Global deduplication | One row per unique email across every query, page and platform domain |
| Email normalisation | Understands `name [at] domain [dot] com`, `name (at) domain`, `name @ domain.com`, `domain .com`, zero-width characters and the full-width `＠` sign |
| Junk filter | Rejects `email@`, `yourname@`, `test@`, `xxx@` and single-character locals |
| Boundary-correct matching | `@gmail.com` does not match inside `@gmail.company` or `@gmail.com.br` |
| Soft-wrap repair | Drops a hit that is only the tail of another email in the same block |
| Structural block parsing | Locates the `<h3>` title and the smallest surrounding block instead of relying on CSS class names |
| Whole-page fallback parser | A Google markup change degrades to emails without account details, not to zero results |
| Concurrency | `asyncio` worker pool with a shared stop signal once `maxEmails` is reached |
| Retries and block detection | Three attempts per page with exponential backoff; CAPTCHA and consent pages are retried, not counted as empty |
| Re-queue pass | Blocked or failed queries are retried once at the end of the run |
| Resumable state | Key-value store state keyed by an input hash, saved on `PERSIST_STATE`, `MIGRATING` and `ABORTING` |
| Immediate dataset writes | Each lead is pushed as soon as it is found |
| Run summary | Logs pages fetched, blocked pages, retries and emails per page |

### How the Angi Email Scraper works

The Angi Email Scraper reads your input, builds Google queries, fetches result pages and parses each block structurally.
Emails are extracted from block text with a domain-filtered regex, normalised, junk-filtered and deduplicated globally.
Each surviving lead is pushed to the Apify dataset immediately, so a partial run is still usable.

A query looks like `site:angi.com roofer "@gmail.com" "Columbus"`, with parallel queries against the two sister domains.
Pages are fetched through the Apify GOOGLE_SERP proxy over async HTTP with a fresh proxy session per request.
Structural parsing means a Google layout change degrades the run rather than breaking it.

#### Query expansion in the Angi Email Scraper

Google caps a single query at roughly 300 results, and three domains of contractor listings vastly exceed that.
Query expansion multiplies each keyword by each email domain and by several phrasings, with base queries running first.
Because three platform domains are in play, the expanded query set is larger here than on single-domain Actors.

#### Location is the strongest lever in the Angi Email Scraper

`location` matters more on Angi than almost anywhere else in this category.
Contractors are matched to homeowners by service area, so every listing carries a city, county or metro in its text.
Run the same keyword set once per metro and merge the datasets afterwards rather than attempting one national sweep.

#### Choosing trade keywords for the Angi Email Scraper

Angi's own service categories are the highest-yield keywords because they match the platform taxonomy.
`roofer`, `hvac contractor`, `plumber`, `deck builder`, `siding contractor` and `remodeling contractor` all map to real categories.
Six to ten trade keywords per metro is a sensible working range.

### Input reference for the Angi Email Scraper

The Angi Email Scraper takes nine inputs and only `keywords` is required.

| Field | Type | Default | Meaning |
|---|---|---|---|
| `keywords` | array (required) | `["contractor", "roofer"]` | Search terms describing the contractors you want |
| `location` | string | `""` | Optional location phrase added to every query |
| `customDomains` | array | `["@gmail.com", "@yahoo.com"]` | Only emails on these domains are kept; `@` optional |
| `maxEmails` | integer 1-10000 | `20` | Stop after this many unique emails |
| `countryCode` | string | `""` | Two-letter country code for the search proxy (US, GB, DE) |
| `expandQueries` | boolean | `true` | Search each keyword x domain pair in several phrasings |
| `queryModifiers` | array | `["email", "contact", "enquiries", "owner", "get a quote"]` | Extra words combined with each keyword when expansion is on |
| `maxPagesPerQuery` | integer 1-50 | `30` | Page cap per query |
| `maxConcurrency` | integer 1-20 | `5` | Parallel queries |

#### Example input

```json
{
  "keywords": ["roofer", "hvac contractor", "siding contractor", "deck builder"],
  "location": "Columbus",
  "customDomains": ["@gmail.com", "@yahoo.com", "@outlook.com", "@aol.com"],
  "maxEmails": 400,
  "countryCode": "US",
  "expandQueries": true,
  "queryModifiers": ["email", "contact", "enquiries", "owner", "get a quote"],
  "maxPagesPerQuery": 30,
  "maxConcurrency": 5
}
```

#### Tuning the Angi Email Scraper

Trade plus metro is the winning combination on this platform.
`roofer` with `location` set to `Columbus` will out-produce `contractor` with no location by a wide margin.
Three to eight trade keywords per metro keeps runs manageable.

Independent contractors overwhelmingly use free-mail addresses.
Keep `@gmail.com`, `@yahoo.com`, `@outlook.com` and `@aol.com` in `customDomains` for US runs.
Each extra domain multiplies the query count across all three platform domains, so raise `maxEmails` alongside.

### Output reference for the Angi Email Scraper

Every dataset item produced by the Angi Email Scraper carries all fourteen fields below.

| Field | Meaning |
|---|---|
| `network` | Platform name |
| `keyword` | The keyword that produced the lead |
| `query` | The exact Google query used, including which platform domain it targeted |
| `title` | Raw result title |
| `accountName` | Account label Google prints |
| `fullName` | Display name parsed from a profile-style title; empty for non-profile results |
| `username` | URL-safe handle when the platform exposes one; otherwise `null` |
| `profileUrl` | Canonical account URL when a handle is known; otherwise empty |
| `url` | Direct platform link when exposed, else the profile URL |
| `description` | Listing snippet, cleaned of labels and counters |
| `email` | Lower-cased email address |
| `emailDomain` | The matched domain |
| `possiblyTruncated` | `true` when Google's snippet ellipsis touched the email |
| `foundAt` | ISO 8601 UTC timestamp |

#### Example output

```json
[
  {
    "network": "Angi",
    "keyword": "roofer",
    "query": "site:angi.com roofer \"@gmail.com\" \"Columbus\"",
    "title": "Buckeye Ridge Roofing - Columbus, OH | Angi",
    "accountName": "Buckeye Ridge Roofing",
    "fullName": "Buckeye Ridge Roofing",
    "username": "buckeye-ridge-roofing",
    "profileUrl": "https://www.angi.com/companylist/buckeye-ridge-roofing",
    "url": "https://www.angi.com/companylist/buckeye-ridge-roofing",
    "description": "Asphalt shingle and metal roof replacement across central Ohio. Get a quote: buckeyeridgeroofing@gmail.com",
    "email": "buckeyeridgeroofing@gmail.com",
    "emailDomain": "@gmail.com",
    "possiblyTruncated": false,
    "foundAt": "2025-11-04T18:03:44Z"
  },
  {
    "network": "Angi",
    "keyword": "hvac contractor",
    "query": "site:homeadvisor.com hvac contractor owner \"@yahoo.com\" \"Columbus\"",
    "title": "Scioto Comfort Heating & Cooling - Columbus, OH | HomeAdvisor",
    "accountName": "Scioto Comfort Heating & Cooling",
    "fullName": "Scioto Comfort Heating & Cooling",
    "username": "scioto-comfort-heating-cooling",
    "profileUrl": "https://www.angi.com/companylist/scioto-comfort-heating-cooling",
    "url": "https://www.angi.com/companylist/scioto-comfort-heating-cooling",
    "description": "Furnace and AC installation, 24 hour emergency service. Owner enquiries: sciotocomfort@yahoo.com",
    "email": "sciotocomfort@yahoo.com",
    "emailDomain": "@yahoo.com",
    "possiblyTruncated": true,
    "foundAt": "2025-11-04T18:05:02Z"
  }
]
```

The Apify dataset view shows email, account, name, username, profile, keyword, snippet and the truncation flag.
Export as CSV, JSON or XLSX, or read the dataset through the Apify API.
Because identity resolution is strong here, the profile column is genuinely useful for manual verification.

### Use cases for the Angi Email Scraper

The Angi Email Scraper is built for suppliers and service providers selling into the US home improvement trades.

| Use case | Suggested keywords | Suggested location |
|---|---|---|
| Selling building materials to contractors | `roofer`, `siding contractor` | one metro per run |
| Contractor insurance, bonding and workers comp | `general contractor`, `hvac contractor` | state capital or metro |
| Lead-generation and CRM software sales | `remodeling contractor`, `plumber` | metro area |
| Franchise and territory recruitment | `gutter installation`, `pressure washing` | target territory |
| Fleet, tool and equipment finance | `deck builder`, `concrete contractor` | metro area |
| Trade distribution and dealer recruitment | `window installer`, `flooring contractor` | regional hub city |
| Market research on contractor supply | `contractor`, `roofer` | leave empty |

#### Selling into the trades with the Angi Email Scraper

Suppliers benefit most because Angi contractors are their end customers.
Use Angi's own trade category names, one metro at a time, and keep the free-mail domains wide.
The `description` field states the trade and the service area, which is enough to segment a list quickly.

#### HomeAdvisor and Angie's List legacy listings in the Angi Email Scraper

Some older contractor records survive only on `homeadvisor.com` or `angieslist.com`.
Because the Angi Email Scraper searches all three domains together, you pick those up without configuring anything.
Check the `query` field if you need to know which domain produced a given lead.

### Practical recipes for the Angi Email Scraper

A Midwest sweep might use `roofer`, `hvac contractor` and `siding contractor` with `location` set to `Columbus` and `countryCode` to `US`.
A Sun Belt campaign might repeat the same keyword set for `Phoenix`, `Dallas`, `Atlanta` and `Tampa` as separate runs.
Keep `expandQueries` on throughout, because one query cannot reach past Google's result cap.

For breadth, drop `location`, keep `maxPagesPerQuery` at 30 and raise `maxEmails`.
For precision, name one metro, use three or four trade keywords and set `maxEmails` to a couple of hundred.
Both modes run identical code; only query volume differs.

### How many results the Angi Email Scraper returns

A measured live run of the Angi Email Scraper produced 10 blocks, 10 identity matches, 10 profile URLs and 8 unique emails.
Identity resolution was perfect and email yield was high, which puts Angi in the strong tier of this category.
Only Bark, CallUpContact and Crunchbase measured higher, and Porch and Clutch matched it.

Your own numbers will vary with trade, metro, domain list and how much of the three platform domains Google currently indexes.
Free Apify plans stop at 100 emails per run and paid plans are uncapped.
No specific volume is guaranteed by the Angi Email Scraper or by any Actor in this family.

### Limitations of the Angi Email Scraper

- The Angi Email Scraper only finds contractors whose email is publicly visible in Google's index. Angi routes many enquiries through its own lead system, so some contractors publish no address.
- Google caps a single query at roughly 300 results. Query expansion exists to work around that cap, and disabling it reduces yield sharply.
- `possiblyTruncated: true` means Google's snippet ellipsis touched the email, so the address may be incomplete. Verify those rows before sending.
- `username` and `profileUrl` are populated only when Google exposes a handle. Category and city landing pages can leave those blank while keeping `accountName` and `fullName`; that is a Google limitation, not a bug.
- The Angi Email Scraper requires the Apify GOOGLE_SERP proxy and cannot run without Apify proxy credentials.
- Free Apify plans are capped at 100 emails per run; paid plans have no cap.
- Results vary with keywords, domains and location, and no volume is guaranteed.

The Angi Email Scraper is not affiliated with, endorsed by or officially supported by Angi, HomeAdvisor or Angie's List.
It reads public search results only and does not access private or gated data.

### Responsible use, GDPR and CAN-SPAM

Most Angi contractors are small businesses or sole traders, so a free-mail address is often personal data in practice as well as in law.
For US recipients, CAN-SPAM expects accurate headers, a valid postal address and a working unsubscribe path.
For EU and UK recipients, GDPR expects a lawful basis, a clear sender identity, a genuine business reason and an easy way to object.

Keep the `query`, `profileUrl` and `foundAt` provenance that every row carries.
Honour opt-outs immediately and suppress them in later runs of the Angi Email Scraper.
This is general information about common obligations rather than legal advice, so check the rules that apply to you.

### FAQ about the Angi Email Scraper

#### How many results should I expect?

A measured live run returned 10 blocks, 10 identity matches, 10 profile URLs and 8 unique emails, which is a strong result. Your numbers depend on trade, metro, domains and index coverage, and no volume is guaranteed.

#### Does the Angi Email Scraper cover HomeAdvisor and Angie's List?

Yes. It queries `angi.com`, `homeadvisor.com` and `angieslist.com` in the same run and deduplicates emails across all three.

#### Does the Angi Email Scraper log into Angi?

No. It never logs in, never uses an Angi API and never opens angi.com. All data comes from publicly indexed Google results.

#### How important is the location field in the Angi Email Scraper?

Very. Contractors are matched by service area, so one run per metro will beat a single national run every time.

#### Why do some contractors have no email?

Angi is built to route homeowner enquiries through its own lead system, so plenty of contractors never publish an address. The Angi Email Scraper can only surface the ones that do.

#### Why are some `username` and `profileUrl` values empty?

The Angi Email Scraper fills those only when Google exposes a handle. City and category landing pages sometimes show a title without one, so the row keeps `accountName` and leaves the handle blank.

#### What does `possiblyTruncated` mean?

Google's snippet ellipsis touched the email, so the address may be cut short. Verify those rows before sending.

#### How do I raise the Angi Email Scraper email count?

Widen `customDomains` to four or more free-mail providers, raise `maxEmails`, keep `expandQueries` on and run more metros.

#### Does it need the Apify proxy?

Yes. The Angi Email Scraper runs on the Apify GOOGLE_SERP proxy and cannot operate without Apify proxy credentials.

#### Can I run it on the free plan?

Yes, capped at 100 emails per run. Paid plans remove the cap.

#### Are the emails verified?

No. The Angi Email Scraper extracts and normalises what Google shows. Run your own verification before any campaign.

#### Which other home-services Actors should I run alongside?

The [Thumbtack Email Scraper](https://apify.com/leads-scraper/thumbtack-email-scraper) and [Porch Email Scraper](https://apify.com/neuro-scraper/porch-email-scraper) for more US trades, and the [Houzz Email Scraper](https://apify.com/leads-scraper/houzz-email-scraper) for design-led remodelling.

### Related Actors

Thirty-six sibling Actors cover the rest of the Business and Professional Directories category that the Angi Email Scraper belongs to.
They share the same input schema, output schema and behaviour, so anything you learn here transfers directly.
For UK trades try the [Bark Email Scraper](https://apify.com/leads-scraper/bark-email-scraper), and for a general local fallback the [Yellow Pages Email Scraper](https://apify.com/leads-scraper/yellow-pages-email-scraper).

| Actor | What it collects |
|---|---|
| [Angi Email and Phone Number Scraper](https://apify.com/neuro-scraper/angi-email-and-phone-number-scraper) | Emails and phone numbers from Angi |
| [Angi Phone Number Scraper](https://apify.com/neuro-scraper/angi-phone-number-scraper) | Public phone numbers from Angi |
| [Bark Email Scraper](https://apify.com/leads-scraper/bark-email-scraper) | Public contact emails from Bark |
| [Better Business Bureau Email Scraper](https://apify.com/leads-scraper/better-business-bureau-email-scraper) | Public contact emails from Better Business Bureau |
| [Bizapedia Email Scraper](https://apify.com/neuro-scraper/bizapedia-email-scraper) | Public contact emails from Bizapedia |
| [Brownbook Email Scraper](https://apify.com/neuro-scraper/brownbook-email-scraper) | Public contact emails from Brownbook |
| [Callupcontact Email Scraper](https://apify.com/neuro-scraper/callupcontact-email-scraper) | Public contact emails from CallUpContact |
| [Capterra Email Scraper](https://apify.com/leads-scraper/capterra-email-scraper) | Public contact emails from Capterra |
| [Clutch Email Scraper](https://apify.com/leads-scraper/clutch-email-scraper) | Public contact emails from Clutch |
| [Crunchbase Email Scraper](https://apify.com/leads-scraper/crunchbase-email-scraper) | Public contact emails from Crunchbase |
| [Cybo Email Scraper](https://apify.com/neuro-scraper/cybo-email-scraper) | Public contact emails from Cybo |
| [Cylex Email Scraper](https://apify.com/neuro-scraper/cylex-email-scraper) | Public contact emails from Cylex |
| [EC21 Email Scraper](https://apify.com/neuro-scraper/ec21-email-scraper) | Public contact emails from EC21 |
| [Europages Email Scraper](https://apify.com/leads-scraper/europages-email-scraper) | Public contact emails from Europages |
| [ExportHub Email Scraper](https://apify.com/neuro-scraper/exporthub-email-scraper) | Public contact emails from ExportHub |
| [FindUsLocal Email Scraper](https://apify.com/neuro-scraper/finduslocal-email-scraper) | Public contact emails from FindUsLocal |
| [Foursquare Email Scraper](https://apify.com/neuro-scraper/foursquare-email-scraper) | Public contact emails from Foursquare |
| [Fyple Email Scraper](https://apify.com/neuro-scraper/fyple-email-scraper) | Public contact emails from Fyple |
| [G2 Email Scraper](https://apify.com/neuro-scraper/g2-email-scraper) | Public contact emails from G2 |
| [Hotfrog Email Scraper](https://apify.com/leads-scraper/hotfrog-email-scraper) | Public contact emails from Hotfrog |
| [Houzz Email Scraper](https://apify.com/leads-scraper/houzz-email-scraper) | Public contact emails from Houzz |
| [Infobel Email Scraper](https://apify.com/neuro-scraper/infobel-email-scraper) | Public contact emails from Infobel |
| [Kompass Email Scraper](https://apify.com/leads-scraper/kompass-email-scraper) | Public contact emails from Kompass |
| [Lacartes Email Scraper](https://apify.com/neuro-scraper/lacartes-email-scraper) | Public contact emails from Lacartes |
| [Manta Email Scraper](https://apify.com/leads-scraper/manta-email-scraper) | Public contact emails from Manta |
| [MapQuest Email Scraper](https://apify.com/neuro-scraper/mapquest-email-scraper) | Public contact emails from MapQuest |
| [N49 Email Scraper](https://apify.com/neuro-scraper/n49-email-scraper) | Public contact emails from N49 |
| [Porch Email Scraper](https://apify.com/neuro-scraper/porch-email-scraper) | Public contact emails from Porch |
| [Scoot Email Scraper](https://apify.com/neuro-scraper/scoot-email-scraper) | Public contact emails from Scoot |
| [Thomasnet Email Scraper](https://apify.com/leads-scraper/thomasnet-email-scraper) | Public contact emails from Thomasnet |
| [Thumbtack Email Scraper](https://apify.com/leads-scraper/thumbtack-email-scraper) | Public contact emails from Thumbtack |
| [Touch Local Email Scraper](https://apify.com/leads-scraper/touch-local-email-scraper) | Public contact emails from Touch Local |
| [TradeIndia Email Scraper](https://apify.com/leads-scraper/tradeindia-email-scraper) | Public contact emails from TradeIndia |
| [Trustpilot Email Scraper](https://apify.com/leads-scraper/trustpilot-email-scraper) | Public contact emails from Trustpilot |
| [Tupalo Email Scraper](https://apify.com/leads-scraper/tupalo-email-scraper) | Public contact emails from Tupalo |
| [Yalwa Email Scraper](https://apify.com/leads-scraper/yalwa-email-scraper) | Public contact emails from Yalwa |
| [Yellow Pages Email Scraper](https://apify.com/leads-scraper/yellow-pages-email-scraper) | Public contact emails from Yellow Pages |
| [Bark Email and Phone Number Scraper](https://apify.com/neuro-scraper/bark-email-and-phone-number-scraper) | Emails and phone numbers from Bark |
| [Better Business Bureau Email and Phone Number Scraper](https://apify.com/leads-scraper/better-business-bureau-email-and-phone-number-scraper) | Emails and phone numbers from Better Business Bureau |
| [Bizapedia Email and Phone Number Scraper](https://apify.com/neuro-scraper/bizapedia-email-and-phone-number-scraper) | Emails and phone numbers from Bizapedia |
| [Brownbook Email and Phone Number Scraper](https://apify.com/neuro-scraper/brownbook-email-and-phone-number-scraper) | Emails and phone numbers from Brownbook |
| [CallUpContact Email and Phone Number Scraper](https://apify.com/neuro-scraper/callupcontact-email-and-phone-number-scraper) | Emails and phone numbers from CallUpContact |

### Leave a review

If the Angi Email Scraper saved you time, please leave a star rating and a short review on the
Actor page.

Reviews are how other buyers judge whether a tool works, and they tell us which features to
build next.

If something did not work, email <neurodata.apify@gmail.com>
instead - bugs get fixed faster than they get complained about.

### Support

Questions, bug reports or a custom build request for the Angi Email Scraper: contact neurodata.apify@gmail.com.

# Actor input Schema

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

Search terms describing the Angi accounts you want (niche, job title, industry).

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

Optional location phrase added to every query (e.g. "New York").

## `customDomains` (type: `array`):

Only emails ending with one of these domains are collected. With or without the leading @. Each domain is searched separately, so more domains means more results but a longer run - remove some for a faster, narrower search, or add your own (e.g. @company.com).

## `maxEmails` (type: `integer`):

Stop once this many unique emails have been collected.

## `countryCode` (type: `string`):

Two-letter country code for the search proxy (e.g. US, GB, DE). Empty for any.

## `expandQueries` (type: `boolean`):

Search each keyword x domain pair with several phrasings. Recommended - Google caps a single query at ~300 results.

## `queryModifiers` (type: `array`):

Extra words combined with each keyword when Expand queries is on. Tuned for Angi.

## `maxPagesPerQuery` (type: `integer`):

Google rarely returns more than ~30 pages for one query.

## `maxConcurrency` (type: `integer`):

How many queries run in parallel.

## Actor input object example

```json
{
  "keywords": [
    "contractor",
    "roofer"
  ],
  "location": "",
  "customDomains": [
    "@gmail.com",
    "@yahoo.com"
  ],
  "maxEmails": 20,
  "countryCode": "",
  "expandQueries": true,
  "queryModifiers": [
    "email",
    "contact",
    "enquiries",
    "owner",
    "get a quote"
  ],
  "maxPagesPerQuery": 30,
  "maxConcurrency": 5
}
```

# Actor output Schema

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

Records produced by Angi Email Scraper, stored in the run's 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 = {
    "keywords": [
        "contractor",
        "roofer"
    ],
    "location": "",
    "customDomains": [
        "@gmail.com",
        "@yahoo.com"
    ],
    "countryCode": "",
    "queryModifiers": [
        "email",
        "contact",
        "enquiries",
        "owner",
        "get a quote"
    ]
};

// Run the Actor and wait for it to finish
const run = await client.actor("leads-scraper/angi-email-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 = {
    "keywords": [
        "contractor",
        "roofer",
    ],
    "location": "",
    "customDomains": [
        "@gmail.com",
        "@yahoo.com",
    ],
    "countryCode": "",
    "queryModifiers": [
        "email",
        "contact",
        "enquiries",
        "owner",
        "get a quote",
    ],
}

# Run the Actor and wait for it to finish
run = client.actor("leads-scraper/angi-email-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 '{
  "keywords": [
    "contractor",
    "roofer"
  ],
  "location": "",
  "customDomains": [
    "@gmail.com",
    "@yahoo.com"
  ],
  "countryCode": "",
  "queryModifiers": [
    "email",
    "contact",
    "enquiries",
    "owner",
    "get a quote"
  ]
}' |
apify call leads-scraper/angi-email-scraper --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,leads-scraper/angi-email-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/uPfvuxvpL32sUtjjq/builds/wiRhl7GhcNd6plWn8/openapi.json
