# Angi Scraper - US Home Service Pros & Contractors (`haketa/angi-scraper`) Actor

Angi (Angie's List) scraper & data API: find US home-service pros & contractors by category and city — export business name, category, phone, full address, rating, review count, reviews, years in business & verification. Home-services lead generation & local market research — fast.

- **URL**: https://apify.com/haketa/angi-scraper.md
- **Developed by:** [Haketa](https://apify.com/haketa) (community)
- **Categories:** Lead generation, Real estate
- **Stats:** 5 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $3.00 / 1,000 results

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

## Angi Scraper — US Home-Service Pros, Contractors & Reviews

Extract **US home-service professionals and contractors** from Angi (formerly Angie's List) at scale. Search by service category and city — plumbers, electricians, roofers, HVAC, cleaners, landscapers, and more — and export clean, structured data: **business name, category, phone, full address, rating, review count, verification status, and description**.

No login. Just give it a category and a location, and get back a ready-to-use dataset in JSON, CSV, Excel, or via API.

> Built for home-services lead generation, contractor outreach, and local market research. Pairs perfectly with contractor-license data for full verification + reputation coverage.

***

### 🧭 Table of contents

- [What this scraper does](#what-this-scraper-does)
- [Why use it](#why-use-it)
- [Who it's for](#who-its-for)
- [What data you get](#what-data-you-get)
- [Input options](#input-options)
- [Input examples](#input-examples)
- [Output example](#output-example)
- [How to use (step by step)](#how-to-use-step-by-step)
- [Tips for best results](#tips-for-best-results)
- [Use cases](#use-cases)
- [Integrations & export](#integrations--export)
- [Pricing](#pricing)
- [FAQ](#faq)

***

### What this scraper does

Angi is one of the largest US directories of home-service professionals. This actor turns its listings into structured data you can act on.

Give it one or more **service categories** (e.g. `plumbing`, `electrician`, `roofing`) and **locations** (e.g. `ny/new-york`, `ca/los-angeles`), and it collects the matching pros — each with contact details, rating, review count, and verification status. You can also paste Angi listing or company URLs directly.

***

### Why use it

- ⚡ **Reliable at scale** — built to handle Angi's protections and page reliably through results.
- 📞 **Contact-ready** — business name, phone, and full address for outreach and CRM import.
- ⭐ **Reputation data** — rating, review count, and verification status per pro.
- 🧱 **Flexible inputs** — search by category + location, or paste Angi URLs directly.
- 🏗️ **Pairs with license data** — combine reputation (Angi) with licensing (state boards) for full vetting.
- 📦 **Export anywhere** — JSON, CSV, Excel, HTML table, or RSS, plus a full REST API and integrations.

***

### Who it's for

- **Home-services lead-gen** building contractor and pro contact lists by trade and city.
- **SaaS & marketplaces** onboarding or enriching service-provider data.
- **Sales teams** targeting contractors with tools, insurance, materials, or financing.
- **Market researchers** analyzing pro density, ratings, and competition by metro.
- **Agencies** auditing local listings and reputation for clients.

***

### What data you get

Each pro includes (when available):

| Field | Description |
| --- | --- |
| `businessName` | Company / pro name |
| `url` | Angi profile URL |
| `category` | Service category |
| `phone` | Phone number |
| `address` | Street address |
| `city` | City |
| `state` | State |
| `zip` | ZIP / postal code |
| `country` | Country |
| `rating` | Average star rating |
| `reviewCount` | Number of reviews |
| `bestRating` | Maximum rating scale |
| `yearsInBusiness` | Years in business (when listed) |
| `isVerified` | Whether the pro is verified |
| `description` | Business description |
| `image` | Profile / logo image |
| `scrapedAt` | When the record was scraped |

***

### Input options

| Option | Type | Description |
| --- | --- | --- |
| `categories` | array | Service category slugs (e.g. `plumbing`, `electrician`, `roofing`). |
| `locations` | array | `state/city` slugs (e.g. `ny/new-york`, `ca/los-angeles`). |
| `startUrls` | array | Angi listing or company URLs to scrape directly. |
| `maxPagesPerList` | integer | Result pages to paginate per category+location (default: 3). |
| `maxItems` | integer | Maximum pros to save (0 = no limit). |
| `maxConcurrency` | integer | Parallel profile requests (default: 5). |
| `proxyConfiguration` | object | US residential proxy required (default provided). |

***

### Input examples

#### 1. Plumbers in a city

```json
{
  "categories": ["plumbing"],
  "locations": ["ny/new-york"],
  "maxItems": 100,
  "proxyConfiguration": { "useApifyProxy": true, "apifyProxyGroups": ["RESIDENTIAL"], "apifyProxyCountry": "US" }
}
```

#### 2. Multiple trades across multiple cities

```json
{
  "categories": ["plumbing", "electrician", "roofing"],
  "locations": ["ca/los-angeles", "tx/houston", "il/chicago"],
  "maxPagesPerList": 5,
  "maxItems": 1000,
  "proxyConfiguration": { "useApifyProxy": true, "apifyProxyGroups": ["RESIDENTIAL"], "apifyProxyCountry": "US" }
}
```

#### 3. From Angi URLs

```json
{
  "startUrls": [
    "https://www.angi.com/companylist/us/ny/new-york/plumbing.htm"
  ]
}
```

***

### Output example

```json
{
  "businessName": "Trejos Plumbing & Rooter",
  "url": "https://www.angi.com/companylist/us/ca/canoga-park/trejos-plumbing-rooter-reviews-1.htm",
  "category": "plumbing",
  "phone": "8183210915",
  "city": "Canoga Park",
  "state": "CA",
  "zip": "91303",
  "country": "United States",
  "rating": 5,
  "reviewCount": 4,
  "bestRating": 5,
  "isVerified": true,
  "description": "All American Plumbing is committed to excellence ...",
  "scrapedAt": "2026-06-09T10:00:00.000Z"
}
```

***

### How to use (step by step)

1. Open the actor and click **Try for free**.
2. Add **categories** (e.g. `plumbing`) and **locations** (e.g. `ny/new-york`).
3. Set **Max pages per listing** and **Max items** to control how many pros you collect.
4. Keep the **US residential proxy** (required).
5. Click **Save & Start**.
6. When the run finishes, open the **Dataset** tab and export to JSON, CSV, or Excel, or pull it via API.

***

### Tips for best results

- **Location format is `state/city`.** Use the two-letter state abbreviation and a hyphenated city, e.g. `ny/new-york`, `ca/los-angeles`, `tx/houston`.
- **Category slugs are hyphenated.** Examples: `plumbing`, `electrician`, `roofing`, `hvac`, `house-cleaning`, `landscaping`, `pest-control`.
- **Keep the US residential proxy** — it's required for reliable access.
- **Moderate concurrency** keeps runs stable; raise it gradually if needed.
- **Combine with contractor-license data** for full vetting (reputation + licensing).

***

### Use cases

- 🧲 **Lead generation** — build contractor contact lists (name, phone, city) by trade and metro.
- 🤝 **Sales prospecting** — target pros for tools, insurance, materials, software, or financing.
- 📊 **Market research** — analyze pro density, ratings, and competition across cities.
- ✅ **Vetting & verification** — combine Angi reputation with license data for due diligence.
- 🤖 **AI & data products** — feed structured home-services data into apps and assistants.

***

### Integrations & export

Export as **JSON, CSV, Excel, HTML table, or RSS**, or fetch results through the **API**. Connect to **Make, Zapier, n8n, Google Sheets, Slack, GitHub**, and more, or schedule runs to keep your dataset fresh.

***

### Pricing

This actor runs on a simple pay-per-result model — you only pay for the pros you collect. Start small with the free tier and scale up as needed.

***

### FAQ

**How do I specify a location?**
As `state/city`, using the two-letter state code and a hyphenated city name, e.g. `ny/new-york`.

**Which categories can I use?**
Any Angi home-service category slug — `plumbing`, `electrician`, `roofing`, `hvac`, `house-cleaning`, `landscaping`, `pest-control`, and many more. Browse angi.com to discover available categories in your target city.

**Do I get phone numbers?**
Yes — phone numbers are included when listed on Angi profiles, making this ideal for lead generation. Note: Angi hides phone numbers on approximately 50% of profiles. When hidden, the `phone` field will be null — this is a platform limitation, not a scraper issue.

**Do I need an account?**
No login is required. A US residential proxy is required and provided by default.

**How many pros can I scrape?**
As many as your categories and locations return — increase `maxPagesPerList` and `maxItems` to collect more. Each category+location combination typically returns 100-500 pros. Use multiple categories and cities for larger datasets.

**Can I scrape specific companies?**
Yes — paste their Angi URLs into `startUrls`. Profile URLs follow the pattern `/companylist/us/{state}/{city}/{business-name}-reviews-{id}.htm`.

**Why is a US residential proxy required?**
Angi uses Cloudflare protection that blocks non-US and datacenter IPs. A US residential proxy ensures reliable access by making requests appear as real US household visitors. The default is preconfigured.

**What's the difference between rating, reviewCount, and bestRating?**
`rating` is the average star rating (1-5), `reviewCount` is the total number of reviews, and `bestRating` is the maximum possible rating (typically 5). These come from Angi's schema.org LocalBusiness structured data.

**Can I combine this with contractor license data?**
Yes — this is a powerful pattern. Scrape Angi for reputation data (rating, reviews, verification), then cross-reference with state contractor license databases for compliance data (license status, insurance, bond). Together they give you a complete pro-vetting picture.

**How many profiles return phone numbers?**
Approximately 44% of Angi profiles publicly display phone numbers in the schema.org LocalBusiness JSON. The rest show phone only after user interaction (click-to-reveal). This is an Angi platform design choice — no scraper can access those hidden numbers.

**Is there rate limiting?**
Yes — Angi rate-limits burst requests. We handle this automatically with exponential backoff (0.8s–8s) and up to 6 retries per request. Keep `maxConcurrency` at 3-4 for best results.

***

Need another home-services data source or a custom field? Open an issue on the actor's **Issues** tab — feedback and feature requests are welcome.

***

### Anti-Bot Strategy

Angi is protected by **Cloudflare** which challenges non-browser requests. Our approach:

- **Browser-fingerprinted HTTP** — `got-scraping` with Chrome TLS fingerprint mimics real browser connections
- **US residential proxy** — each request gets a fresh US residential IP, making it appear as a real US household visitor
- **Exponential backoff on 429/403** — Angi rate-limits bursts; we back off from 0.8s to 8s across up to 6 retry attempts
- **Low concurrency** — 3 parallel requests by default to stay under rate-limit thresholds
- **Session rotation** — new proxy session per attempt to clear stale Cloudflare challenges

***

### Performance & Memory

| Setting | Value | Notes |
|---------|-------|-------|
| **Memory** | 512–1024 MB | Pure HTTP, no browser needed |
| **Speed** | ~10-15 pros/minute | With moderate concurrency (3-5) |
| **Proxy** | US Residential (required) | Included in run cost |
| **Retries** | Up to 6 attempts | Exponential backoff on blocks |

**Typical run**: 50 pros in ~5-8 minutes. Keep `maxConcurrency: 3-4` for stability — higher values trigger Angi's burst rate-limiting.

***

### Category & Location Format

#### Category slugs (hyphenated):

`plumbing`, `electrician`, `roofing`, `hvac`, `house-cleaning`, `landscaping`, `pest-control`, `handyman`, `painting`, `carpentry`, `flooring`, `fencing`, `tree-service`, `moving`, `windows`, `gutters`, `siding`, `masonry`, `paving`, `excavating`, `concrete`, `drywall`, `insulation`, `appliance-repair`, `garage-doors`, `home-inspection`, `pressure-washing`, `water-damage`, `mold-remediation`, `asbestos`, `radon`, `chimney`, `fireplace`

#### Location format (`state/city`):

`ny/new-york`, `ca/los-angeles`, `tx/houston`, `il/chicago`, `az/phoenix`, `pa/philadelphia`, `fl/miami`, `ga/atlanta`, `ma/boston`, `wa/seattle`, `co/denver`, `or/portland`, `nv/las-vegas`, `dc/washington`, `nc/charlotte`, `mi/detroit`, `mn/minneapolis`, `oh/columbus`, `mo/kansas-city`, `tn/nashville`

Use two-letter state abbreviation + hyphenated city name from the Angi URL pattern.

***

### Integration

#### JavaScript / TypeScript

```javascript
import { ApifyClient } from 'apify-client';
const client = new ApifyClient({ token: 'YOUR_TOKEN' });
const run = await client.actor('haketa/angi-scraper').call({
    categories: ['plumbing', 'electrician'],
    locations: ['ny/new-york'],
    maxItems: 100,
});
const { items } = await client.dataset(run.defaultDatasetId).listItems();
```

#### Python

```python
from apify_client import ApifyClient
client = ApifyClient(token='YOUR_TOKEN')
run = client.actor('haketa/angi-scraper').call(run_input={
    'categories': ['plumbing', 'electrician'],
    'locations': ['ny/new-york'],
    'maxItems': 100,
})
items = client.dataset(run['defaultDatasetId']).list_items().items
```

#### CLI

```bash
apify call haketa/angi-scraper \
    --input '{"categories":["plumbing"],"locations":["ny/new-york"],"maxItems":100}'
```

***

### Use Case: Contractor License + Reputation Cross-Reference

One of the most powerful applications is cross-referencing Angi reputation data with state contractor license databases:

1. **Scrape Angi** for pros in a category + city → get business name, phone, rating, reviews, years in business
2. **Cross-reference with license data** (e.g. state license board scrapers) → verify license status, insurance, bond
3. **Score each pro** on both reputation (Angi) and compliance (license)
4. **Target the best** — verified, licensed, highly-rated, and established

This gives you a complete picture no single data source can provide: who is trustworthy AND who is legal.

***

### Common Search Patterns

#### Find all plumbers across a metro

```json
{
    "categories": ["plumbing"],
    "locations": ["ny/new-york", "ny/brooklyn", "ny/queens", "ny/bronx"],
    "maxPagesPerList": 5,
    "maxItems": 500
}
```

#### Compare ratings across trades in a city

```json
{
    "categories": ["plumbing", "electrician", "hvac", "roofing", "landscaping"],
    "locations": ["ca/los-angeles"],
    "maxPagesPerList": 3,
    "maxItems": 300
}
```

#### Deep-dive: full detail on top-rated pros

```json
{
    "categories": ["plumbing"],
    "locations": ["fl/miami"],
    "maxPagesPerList": 10,
    "maxItems": 1000
}
```

***

### Legal & Responsible Use

This actor extracts publicly available business listings from Angi.com. Users are responsible for:

- Complying with Angi's Terms of Service
- Respecting data usage rights and copyright
- Adhering to TCPA and CAN-SPAM regulations for any outreach
- Using the data for legitimate business intelligence, market research, and B2B lead generation

***

*The most reliable Angi scraper on Apify — US home-service pros with phone, ratings, and verification at scale.*

### 📅 Changelog & Maintenance

**Last updated:** 2026-07-02 — Actor verified and maintained. Data pipeline tested for quality, structure and freshness; selectors/endpoints confirmed against the live site.

# Actor input Schema

## `categories` (type: `array`):

Pick one or more home-service categories to collect pros for. Each selected category is combined with each selected location. Leave empty to use a popular default mix.

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

Pick one or more US cities to search in. Each selected location is combined with each selected category. Leave empty to use a popular default mix.

## `customLocations` (type: `array`):

Optional: add cities not in the dropdown, written as state-abbreviation/city-slug (e.g. ca/long-beach, tx/plano). Combined with each selected category.

## `startUrls` (type: `array`):

Optional: paste Angi listing or pro-profile URLs to scrape directly (e.g. a category list page or a company page). Most users can leave this empty and use the dropdowns above.

## `maxPagesPerList` (type: `integer`):

How many result pages to paginate per category + location listing. More pages = more pros.

## `maxItems` (type: `integer`):

Maximum number of pros to save. 0 = no limit.

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

Maximum parallel profile requests. Keeping this low gives the most reliable results.

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

Angi works best with a US residential proxy. Keep the default unless you supply your own US residential proxy.

## Actor input object example

```json
{
  "categories": [
    "plumbing"
  ],
  "locations": [
    "ca/los-angeles"
  ],
  "customLocations": [
    "ca/long-beach",
    "tx/plano"
  ],
  "startUrls": [
    "https://www.angi.com/companylist/us/ca/los-angeles/plumbing.htm"
  ],
  "maxPagesPerList": 3,
  "maxItems": 100,
  "maxConcurrency": 3,
  "proxyConfiguration": {
    "useApifyProxy": true,
    "apifyProxyGroups": [
      "RESIDENTIAL"
    ],
    "apifyProxyCountry": "US"
  }
}
```

# Actor output Schema

## `businessName` (type: `string`):

Company/business name

## `url` (type: `string`):

Angi pro profile URL

## `category` (type: `string`):

Service category (plumbing, electrician, etc.)

## `phone` (type: `string`):

Business phone number

## `address` (type: `string`):

Street address

## `city` (type: `string`):

City

## `state` (type: `string`):

State (e.g. NY, CA, TX)

## `zip` (type: `string`):

ZIP / postal code

## `country` (type: `string`):

Country (US)

## `rating` (type: `string`):

Average rating (1-5)

## `reviewCount` (type: `string`):

Number of reviews

## `bestRating` (type: `string`):

Best possible rating (typically 5)

## `yearsInBusiness` (type: `string`):

Years since establishment

## `isVerified` (type: `string`):

Angi verified/certified pro

## `description` (type: `string`):

Business description from profile

## `image` (type: `string`):

Business logo/image URL

## `scrapedAt` (type: `string`):

ISO scrape timestamp

# 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 = {
    "categories": [
        "plumbing"
    ],
    "locations": [
        "ca/los-angeles"
    ],
    "maxItems": 100,
    "proxyConfiguration": {
        "useApifyProxy": true,
        "apifyProxyGroups": [
            "RESIDENTIAL"
        ],
        "apifyProxyCountry": "US"
    }
};

// Run the Actor and wait for it to finish
const run = await client.actor("haketa/angi-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 = {
    "categories": ["plumbing"],
    "locations": ["ca/los-angeles"],
    "maxItems": 100,
    "proxyConfiguration": {
        "useApifyProxy": True,
        "apifyProxyGroups": ["RESIDENTIAL"],
        "apifyProxyCountry": "US",
    },
}

# Run the Actor and wait for it to finish
run = client.actor("haketa/angi-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 '{
  "categories": [
    "plumbing"
  ],
  "locations": [
    "ca/los-angeles"
  ],
  "maxItems": 100,
  "proxyConfiguration": {
    "useApifyProxy": true,
    "apifyProxyGroups": [
      "RESIDENTIAL"
    ],
    "apifyProxyCountry": "US"
  }
}' |
apify call haketa/angi-scraper --silent --output-dataset

```

## MCP server setup

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

```

## OpenAPI specification

Download the OpenAPI definition: https://api.apify.com/v2/acts/bBcxl723Dt71bNqpv/builds/7ViV3WcGNqteG3A1q/openapi.json
