# Angi (Angie's List) Contractor & Reviews Scraper (`parseforge/angies-list-scraper`) Actor

Extract verified home service contractor profiles, ratings, reviews, services, addresses, and business hours from Angi (Angie's List). Used by contractors, insurance, and lead-gen teams.

- **URL**: https://apify.com/parseforge/angies-list-scraper.md
- **Developed by:** [ParseForge](https://apify.com/parseforge) (community)
- **Categories:** Business, Lead generation
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, NaN bookmarks
- **User rating**: No ratings yet

## Pricing

Pay per event

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

![ParseForge Banner](https://raw.githubusercontent.com/ParseForge/apify-assets/main/banner.jpg)

## 🛠️ Angi (Angie's List) Contractor Scraper

> 🚀 **Pull verified home service contractors in seconds.** Filter by city and service. No API key, no membership card, no manual copy-paste from profile after profile.

> 🕒 **Last updated:** 2026-05-08 · **📊 18 fields** per record · **49 service categories** · **All 50 US states** · **Profiles, ratings, services, hours**

Angi (formerly Angie's List) is one of the largest home services directories in the United States, with millions of contractor profiles, customer reviews, and Super Service Award winners across plumbing, electrical, roofing, HVAC, remodeling, and dozens of other trades. This Actor turns any public Angi listing or profile URL into a clean, structured dataset of verified pros, ready for spreadsheets, CRMs, and lead-gen pipelines, without you ever touching a browser.

The scraper takes one or more Angi search URLs (city + service or state + service or category-only "near me" pages), walks each listing, and visits every contractor profile to enrich the record with the about-us copy, address, website, business hours, services offered, and the freshest review excerpts. Output is a flat **JSON / CSV / Excel** dataset with **18 fields** per contractor, including business name, Angi rating, review count, service categories, badges, and review highlights. Data quality is the priority: fields that Angi does not surface publicly (such as direct phone numbers gated behind contact forms) are not included, so you never end up with rows full of nulls.

| 🎯 Target audience | 🔧 Primary use cases |
|---|---|
| Home service marketers and lead-gen agencies | Build a contractor lead list filtered by city and trade |
| Insurance adjusters and underwriters | Pre-qualify pros for claims partner programs |
| Real estate teams and property managers | Sourcing reliable maintenance and remodel contractors |
| Researchers and journalists | Local-market analysis on home service supply and quality |
| Franchise developers | Map local-market saturation by service category |
| Reputation analysts | Track ratings, reviews, and Super Service Award trends |

---

### 📋 What the Angi Scraper does

- 🏙️ **Search by category and location.** Drop in any Angi listing URL: a city + service page, a state-wide page, or a `/nearme/{service}/` page.
- 🔎 **Aggregates every visible profile.** The scraper walks the listing, deduplicates by profile URL, and follows pagination when present.
- 🧾 **Enriches each record from the profile page.** Angi's profile schema-org JSON, contact panel, services pills, and review highlights are all extracted in one pass.
- 🛡️ **Cloudflare and DataDome handled.** Camoufox over a residential US proxy clears the bot challenges that block plain HTTP scrapers.
- 🧹 **No always-null columns.** Fields that Angi gates (such as the public phone number, which sits behind their contact form) are omitted, so you can ship the dataset straight to Excel or your CRM.

Each record contains identity (business name, profile URL, businessId, logo image), trust signals (Angi rating, review count, badges, review highlights), location (street, city, state, ZIP), reach (services offered, website, business hours), and the about-us description the contractor wrote on Angi.

> 💡 **Why it matters:** Angi reviews are widely seen as higher signal than generic Yelp or Google posts because Angi gates them through paid membership history. Pair an Angi-derived list with skip-trace or licensing data and you get a verified, ranked contractor universe in minutes.

---

### 🎬 Full Demo

🚧 Coming soon: a 3-minute walkthrough showing how to point the scraper at an Angi search URL, pull a city's plumber roster, and export the results to Google Sheets.

---

### ⚙️ Input

<table>
<tr><th>Field</th><th>Type</th><th>Required</th><th>Description</th></tr>
<tr><td><code>searchUrls</code></td><td>array&lt;string&gt;</td><td>No</td><td>One or more Angi listing URLs. Use a city + service URL (<code>/companylist/us/ca/los-angeles/...</code>), a state-level service URL (<code>/companylist/us/ca/plumbing.htm</code>), or a national category page (<code>/nearme/plumbers/</code>). When omitted the scraper runs against three default urban service pages.</td></tr>
<tr><td><code>maxItems</code></td><td>integer</td><td>No</td><td>Hard cap on the number of contractor records returned. Free plan is auto-limited to 10 for previewing. Paid plan supports up to 1,000,000.</td></tr>
<tr><td><code>fetchProfileDetails</code></td><td>boolean</td><td>No</td><td>When true (default) the scraper visits each contractor profile to add description, address, services, badges, business hours, and review highlights. Disable to run a faster listing-only pass.</td></tr>
<tr><td><code>proxyConfiguration</code></td><td>object</td><td>No</td><td>Apify proxy configuration. Residential US is recommended and used by default. Datacenter proxies are blocked by Angi's bot protection.</td></tr>
</table>

Example: city + service search.

```json
{
  "searchUrls": [
    "https://www.angi.com/nearme/plumbers/",
    "https://www.angi.com/nearme/electrician/"
  ],
  "maxItems": 50,
  "fetchProfileDetails": true
}
````

Example: state-wide audit, listing-only for speed.

```json
{
  "searchUrls": [
    "https://www.angi.com/companylist/us/ca/plumbing.htm",
    "https://www.angi.com/companylist/us/tx/plumbing.htm"
  ],
  "maxItems": 500,
  "fetchProfileDetails": false
}
```

> ⚠️ **Good to Know:** Angi gates direct phone numbers behind a contact form, so the scraper does not return them. Website, address, ZIP, and Angi rating are public and are returned in full.

***

### 📊 Output

Each row in the dataset is one contractor profile. Output formats: JSON, CSV, Excel, RSS, and HTML.

#### 🧾 Schema

| Field | Type | Example |
|---|---|---|
| 🖼️ `imageUrl` | string | `https://cdn.homeadvisor.com/files/eid/12700000/12703198/12993646_logo.png` |
| 🏢 `name` | string | `Bath Planet of Rochester` |
| 🔗 `profileUrl` | string | `https://www.angi.com/companylist/us/ny/henrietta/bath-planet-of-rochester-reviews-1.htm` |
| 🆔 `businessId` | string | `7491831` |
| ⭐ `rating` | number | `4.8` |
| 💬 `reviewCount` | integer | `99` |
| 🛠️ `services` | array | `["Bathroom Remodel","Walk In Tub Installation and Replacement"]` |
| 📍 `address` | string | `535 Summit Point Drive, Suite 4` |
| 🏙️ `city` | string | `Henrietta` |
| 🇺🇸 `state` | string | `NY` |
| 📮 `zip` | string | `14467` |
| 🌐 `website` | string | `http://www.bathplanetlocal.com` |
| 📝 `description` | string | `You deserve a bathroom that is more than just your everyday shower or tub...` |
| 🏅 `badges` | array | `["21 years of experience","Free Estimates","Warranties"]` |
| ⏰ `businessHours` | string | `Sunday:Closed; Monday:9:00 AM - 5:00 PM; ...` |
| 💭 `reviewHighlights` | array | Three short customer review excerpts. |
| 🔍 `sourceUrl` | string | `https://www.angi.com/nearme/plumbers/` |
| 🕒 `scrapedAt` | string (ISO) | `2026-05-08T00:29:29.609Z` |

#### 📦 Sample records

<details>
<summary><strong>Typical contractor (full profile)</strong></summary>

```json
{
  "imageUrl": "https://cdn.homeadvisor.com/files/eid/12700000/12703198/12993646_logo.png",
  "name": "Bath Planet of Rochester",
  "profileUrl": "https://www.angi.com/companylist/us/ny/henrietta/bath-planet-of-rochester-reviews-1.htm",
  "businessId": "1",
  "rating": 4.8,
  "reviewCount": 99,
  "services": [
    "Bathroom Remodel",
    "Bathtub Installation and Replacement",
    "Shower Installation and Replacement",
    "Walk In Tub Installation and Replacement"
  ],
  "address": "535 Summit Point Drive, Suite 4",
  "city": "Henrietta",
  "state": "NY",
  "zip": "14467",
  "website": "http://www.bathplanetlocal.com",
  "description": "You deserve a bathroom that is more than just your everyday shower or tub. At Bath Planet, we put our expertise to work to create a spa-like retreat in the comfort of your own home, all without disrupting your daily routine! Our innovative process is engineered to transform your bathroom in as little as a day...",
  "badges": ["21 years of experience", "Free Estimates", "Warranties"],
  "businessHours": "Sunday:Closed; Monday:9:00 AM - 5:00 PM; Tuesday:9:00 AM - 5:00 PM; Wednesday:9:00 AM - 5:00 PM; Thursday:9:00 AM - 5:00 PM; Friday:9:00 AM - 5:00 PM; Saturday:Closed",
  "reviewHighlights": [
    "i had a wonderful experience with bath planet from the initial sales and design consultation, to the very prompt and professional installation...",
    "The customer 1st when it came to getting the work done one day job he finished it in one day. Happy customer.",
    "The installers were pros, did the work, removed the old tub and tiles, and cleaned up."
  ],
  "sourceUrl": "https://www.angi.com/nearme/plumbers/",
  "scrapedAt": "2026-05-08T00:29:29.609Z"
}
```

</details>

<details>
<summary><strong>Small shop (limited services list, no business hours published)</strong></summary>

```json
{
  "imageUrl": "https://cdn.homeadvisor.com/files/eid/158810000/158811665/20365151_original.jpg",
  "name": "Nick's Kitchen & Bathroom Remodeling",
  "profileUrl": "https://www.angi.com/companylist/us/ny/liverpool/nick%27s-kitchen-and-bathroom-remodeling-reviews-7491831.htm",
  "businessId": "7491831",
  "rating": 4.9,
  "reviewCount": 44,
  "services": [],
  "address": "4802 Joyce Pl",
  "city": "Liverpool",
  "state": "NY",
  "zip": "13090",
  "website": "http://www.lozanovremodeling.com",
  "description": "Kitchen and bathroom remodeling, custom installations, cabinetry, ceramic tile, floor, wall, countertops, formica, granite, fireplace, hardwood, laminate, shower doors, glass & radiant heat flooring.",
  "badges": ["26 years of experience", "Free Estimates", "Warranties"],
  "businessHours": null,
  "reviewHighlights": [
    "Nick and his team were amazing. We had our bathroom remodeled and they went above and beyond to make it beautiful...",
    "Nick and his crew did an AMAZING job in our bathroom. The quality of his workmanship was outstanding...",
    "Perfectly. I have 2 updated bathrooms and an amazing huge tile shower in the master."
  ],
  "sourceUrl": "https://www.angi.com/nearme/plumbers/",
  "scrapedAt": "2026-05-08T00:30:03.438Z"
}
```

</details>

<details>
<summary><strong>Sparse profile (no listed website, minimal badges)</strong></summary>

```json
{
  "imageUrl": "https://media.angi.com/s3fs-public/Angi-logo-Orange.svg",
  "name": "Afford-A-Rooter",
  "profileUrl": "https://www.angi.com/companylist/us/ny/smyrna/afford-a-rooter-reviews-1.htm",
  "businessId": "1",
  "rating": 4.9,
  "reviewCount": 83,
  "services": ["Drain Clog or Blockage Clearing", "Sewer Main Clearing"],
  "address": "750 Boos Law Rd",
  "city": "Smyrna",
  "state": "NY",
  "zip": "13464",
  "website": null,
  "description": "With 15+ years of experience and unmatched expertise, Afford-A-Rooter can help you with any and all of your plumbing, drain, and sewer needs.",
  "badges": ["Emergency services offered", "11 years of experience", "Emergency Services", "Free Estimates"],
  "businessHours": null,
  "reviewHighlights": [
    "Quick to respond, professional, and got the clog cleared in under an hour.",
    "Reasonable price, friendly service, will use again.",
    "Showed up the same day I called and fixed the main line. Highly recommend."
  ],
  "sourceUrl": "https://www.angi.com/nearme/plumbers/",
  "scrapedAt": "2026-05-08T00:24:14.506Z"
}
```

</details>

***

### ✨ Why choose this Actor

| | Capability |
|---|---|
| 🎯 | **Listing + profile in one pass.** Aggregates the listing card AND the deeper profile page into a single tidy row, so you do not need to chain two scrapers. |
| 🛡️ | **Cloudflare and DataDome cleared.** Camoufox + residential US proxy handles Angi's bot protection out of the box. |
| 📦 | **Real, audited fields.** Phone is gated by Angi behind a contact form, so the scraper omits it instead of shipping a column full of nulls. |
| 🔧 | **Schema-org friendly.** Pulls structured `LocalBusiness` JSON-LD when available for the cleanest possible city, state, and ZIP. |
| 🧭 | **Flexible URL inputs.** City + service, state + service, or `/nearme/{category}/` pages all work. |
| 🚦 | **Pagination aware.** Walks the next-page link until the cap is reached. |
| 💰 | **Pay only for what you need.** Free preview at 10 records, paid up to 1,000,000 per run. |

> 📊 49 home service categories supported, **all 50 US states**, and over **3 million** public Angi profiles eligible for scraping.

***

### 📈 How it compares to alternatives

| Approach | Cost | Coverage | Refresh | Filters | Setup |
|---|---|---|---|---|---|
| **⭐ Angi (Angie's List) Contractor Scraper** *(this Actor)* | Pay per run | All US states, 49 categories | Live, on demand | URL based, any city/state/category | 1 click in Apify Console |
| Manual copy-paste from angi.com | Free, slow | Whatever you visit | Manual | Whatever the UI exposes | Hours per project |
| Generic browser scraper templates | Cheap | Anything you configure | DIY | DIY | Days of work, breaks on Cloudflare |
| Paid lead-gen vendor lists | Expensive recurring fee | Vendor-curated subset | Vendor cadence | Vendor-defined | Slow procurement cycle |
| Internal scraping team | High fixed cost | Team-defined | Team-defined | Team-defined | Months to first useful output |

This Actor sits in the sweet spot: cheap, fast to start, you control the URLs, and the bot-protection stack is already solved.

***

### 🚀 How to use

1. 🔐 **Sign up.** Create an Apify account at [console.apify.com](https://console.apify.com/sign-up?fpr=vmoqkp) and open this Actor.
2. 🔗 **Pick your search URLs.** Visit angi.com, browse to a city + service or `/nearme/{category}/` page, and copy the URL. Paste one or more into `searchUrls`.
3. 🔢 **Set `maxItems`.** Start with 10 to preview. Bump to 100 or 1,000+ once happy.
4. ▶️ **Run.** The Actor handles Cloudflare, residential proxy, and pagination automatically.
5. 📥 **Download.** Export the dataset as JSON, CSV, or Excel, or pull it through the [Apify API](https://docs.apify.com/api/v2#/reference/datasets).

> ⏱️ **Total time:** under 2 minutes from sign-up to first export for a 10-record preview.

***

### 💼 Business use cases

<table>
<tr>
<td width="50%">

#### 🧰 Lead-gen agencies

- Build niche home-service contractor lists by city and trade
- Filter by Angi rating threshold for quality-only outreach
- Re-run nightly to catch new entrants in target metros
- Power CRM enrichment with verified business names and websites

</td>
<td width="50%">

#### 🏠 Real estate and property management

- Source vetted contractors for portfolio properties
- Compare ratings across multiple metros at once
- Map service-category coverage in a new market entry
- Build preferred-vendor shortlists with one export

</td>
</tr>
<tr>
<td width="50%">

#### 🛡️ Insurance and claims

- Pre-qualify contractors for partner program eligibility
- Flag low-rated or low-volume providers in claim networks
- Audit service coverage in disaster-recovery markets
- Track Super Service Award winners year over year

</td>
<td width="50%">

#### 🏗️ Franchise development

- Quantify local-market saturation by service category
- Identify low-coverage metros with high search volume
- Spot top-rated competitors before site selection
- Benchmark new franchisee performance against local pros

</td>
</tr>
</table>

***

### 🌟 Beyond business use cases

Data like this powers more than commercial workflows. The same structured records support research, education, civic projects, and personal initiatives.

<table>
<tr>
<td width="50%">

#### 🎓 Research and academia

- Empirical datasets for papers, thesis work, and coursework
- Longitudinal studies tracking changes across snapshots
- Reproducible research with cited, versioned data pulls
- Classroom exercises on data analysis and ethical scraping

</td>
<td width="50%">

#### 🎨 Personal and creative

- Side projects, portfolio demos, and indie app launches
- Data visualizations, dashboards, and infographics
- Content research for bloggers, YouTubers, and podcasters
- Hobbyist collections and personal trackers

</td>
</tr>
<tr>
<td width="50%">

#### 🤝 Non-profit and civic

- Transparency reporting and accountability projects
- Advocacy campaigns backed by public-interest data
- Community-run databases for local issues
- Investigative journalism on public records

</td>
<td width="50%">

#### 🧪 Experimentation

- Prototype AI and machine-learning pipelines with real data
- Validate product-market hypotheses before engineering spend
- Train small domain-specific models on niche corpora
- Test dashboard concepts with live input

</td>
</tr>
</table>

***

### 🔌 Automating Angi Contractor Scraper

You can call this Actor from any system that speaks HTTP, including your own backend, a notebook, or a workflow tool.

- [**Node.js / TypeScript**](https://docs.apify.com/sdk/js/) using the official Apify client
- [**Python**](https://docs.apify.com/sdk/python/) using the official Apify client
- [**Apify API reference**](https://docs.apify.com/api/v2) for direct REST calls

Schedules: configure a recurring run (daily, weekly, on a cron expression) so your contractor list always reflects the latest Angi state, no babysitting required.

***

### ❓ Frequently Asked Questions

<details>
<summary><strong>🧾 Can I use the data commercially?</strong></summary>
Yes, the scraped data is yours to use within your own commercial workflows. You are responsible for complying with Angi's terms of service and any applicable data-protection laws (GDPR, CCPA, and similar) when storing, sharing, or contacting the businesses listed.
</details>

<details>
<summary><strong>💳 Do I need a paid Apify plan?</strong></summary>
No. The free tier lets you preview up to 10 records per run, which is plenty for testing. Paid plans unlock up to 1,000,000 records per run and faster compute.
</details>

<details>
<summary><strong>⚠️ The run failed. What now?</strong></summary>
Most failures are caused by datacenter proxies or by an Angi page that has been moved. Make sure `proxyConfiguration` is set to residential US (the default) and that your URL still loads in a browser. If it persists, [open a contact-form ticket](https://tally.so/r/BzdKgA) with the run ID.
</details>

<details>
<summary><strong>⚖️ Is scraping Angi legal?</strong></summary>
The Actor only collects data that Angi exposes publicly without authentication. Public-data scraping has been repeatedly upheld by US courts (hiQ v. LinkedIn). You are still responsible for using the data responsibly under Angi's terms and applicable law.
</details>

<details>
<summary><strong>📞 Where is the phone number?</strong></summary>
Angi gates direct phone numbers behind a contact-form workflow, so they are not part of the public profile and the scraper does not return them. Website URLs (when listed) are public and ARE returned.
</details>

<details>
<summary><strong>🔍 What URLs can I pass in?</strong></summary>
Three shapes work: `/nearme/{service}/` national category pages, `/companylist/us/{state}/{service}.htm` state pages, and `/companylist/us/{state}/{city}/...` city pages. Provide as many as you like - the scraper aggregates all of them and deduplicates by profile.
</details>

<details>
<summary><strong>🧭 How do I find the right URL for a category?</strong></summary>
Visit angi.com, scroll to "Find Pros in Your State" or use the search bar with a service slug. Copy the URL from the address bar and paste it as a `searchUrls` entry.
</details>

<details>
<summary><strong>🔁 How often should I rerun?</strong></summary>
Daily is overkill for most workflows since contractor profiles change slowly. Weekly or biweekly is a good default. Use Apify Schedules to automate it.
</details>

<details>
<summary><strong>📦 What output formats are available?</strong></summary>
JSON, CSV, Excel (XLSX), HTML table, and RSS. Choose any of them in the dataset Export tab or via the Apify API.
</details>

<details>
<summary><strong>🚦 Why do some records have empty `services`?</strong></summary>
Angi populates the services list from review filter pills, which means newer pros with few reviews may not yet have a populated list. The basic profile fields (name, address, rating) are still present.
</details>

<details>
<summary><strong>🧹 What happens with duplicates across multiple URLs?</strong></summary>
The scraper deduplicates by profile URL, so the same contractor cannot appear twice even if they show up on both `/nearme/plumbers/` and `/companylist/us/ny/plumbing.htm`.
</details>

<details>
<summary><strong>🤖 Can I run this from my own code?</strong></summary>
Yes, just call the Actor through the [Apify API](https://docs.apify.com/api/v2) or one of the official client libraries (Node, Python). Each run gets its own dataset URL you can fetch programmatically.
</details>

***

### 🔌 Integrate with any app

Wire the dataset into the rest of your stack with no glue code.

- [**Zapier**](https://apify.com/integrations/zapier) - kick off a run when a Google Form is submitted
- [**Make**](https://apify.com/integrations/make) - move records into Airtable or HubSpot on a schedule
- [**Slack**](https://apify.com/integrations/slack) - drop the run summary into a channel when it finishes
- [**Google Drive**](https://apify.com/integrations/google-drive) - auto-export the CSV to a shared folder
- [**Webhooks**](https://docs.apify.com/platform/integrations/webhooks) - call your own backend when a run finishes
- [**Apify API**](https://docs.apify.com/api/v2) - native REST integration with everything you build

***

### 🔗 Recommended Actors

- [**🏗️ California State Licensed Contractor CSLB Scraper**](https://apify.com/parseforge/cslb-california-scraper) - cross-check Angi pros against California's official contractor license database.
- [**🛠️ Texas State Licensed Contractor Scraper**](https://apify.com/parseforge/tdlr-texas-scraper) - the same official-license cross-check for Texas-based pros.
- [**📒 Manta Business Directory Scraper**](https://apify.com/parseforge/manta-scraper) - widen lead-gen lists with another national small-business directory.
- [**🩺 RateMDs Physician Review Scraper**](https://apify.com/parseforge/ratemds-scraper) - the same review-and-rating workflow, applied to healthcare providers.
- [**🧮 NASBA CPA Directory Scraper**](https://apify.com/parseforge/nasba-cpa-directory-scraper) - certified-professional directory data for finance and accounting workflows.

> 💡 **Pro Tip:** browse the complete [ParseForge collection](https://apify.com/parseforge) for more home-services, licensing, and business-directory scrapers.

***

**🆘 Need Help?** [**Open our contact form**](https://tally.so/r/BzdKgA) and we will get back within one business day.

***

> ⚠️ **Disclaimer:** This Actor scrapes only public data from Angi. It is not affiliated with, endorsed by, or sponsored by Angi Inc. or its parent or subsidiaries. Use the data in compliance with Angi's terms of service and any applicable data-protection laws in your jurisdiction.

# Actor input Schema

## `searchUrls` (type: `array`):

One or more Angi listing URLs. Use a city + service URL (e.g. https://www.angi.com/companylist/us/ca/los-angeles/plumbers.htm), a state-wide service URL (https://www.angi.com/companylist/us/ny/electricians.htm), or a directory page (https://www.angi.com/companylist/us/tx/). The scraper visits each URL and aggregates contractor profiles.

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

Free users: Limited to 10 items (preview). Paid users: Optional, max 1,000,000.

## `fetchProfileDetails` (type: `boolean`):

When enabled the scraper visits each contractor's profile page to enrich records with description, address, phone, badges, and review highlights. Disable for a faster, listing-only run.

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

Apify residential US proxy is recommended to bypass Cloudflare and DataDome challenges reliably.

## Actor input object example

```json
{
  "searchUrls": [
    "https://www.angi.com/companylist/us/ca/los-angeles/plumbers.htm",
    "https://www.angi.com/companylist/us/ny/new-york/electricians.htm",
    "https://www.angi.com/companylist/us/il/chicago/roofers.htm"
  ],
  "maxItems": 10,
  "fetchProfileDetails": true,
  "proxyConfiguration": {
    "useApifyProxy": true,
    "apifyProxyGroups": [
      "RESIDENTIAL"
    ],
    "apifyProxyCountry": "US"
  }
}
```

# Actor output Schema

## `contractors` (type: `string`):

Complete dataset of contractor profile records.

## `overview` (type: `string`):

Tabular overview of contractor profiles.

# 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 = {
    "searchUrls": [
        "https://www.angi.com/companylist/us/ca/los-angeles/plumbers.htm",
        "https://www.angi.com/companylist/us/ny/new-york/electricians.htm",
        "https://www.angi.com/companylist/us/il/chicago/roofers.htm"
    ],
    "maxItems": 10,
    "proxyConfiguration": {
        "useApifyProxy": true,
        "apifyProxyGroups": [
            "RESIDENTIAL"
        ],
        "apifyProxyCountry": "US"
    }
};

// Run the Actor and wait for it to finish
const run = await client.actor("parseforge/angies-list-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 = {
    "searchUrls": [
        "https://www.angi.com/companylist/us/ca/los-angeles/plumbers.htm",
        "https://www.angi.com/companylist/us/ny/new-york/electricians.htm",
        "https://www.angi.com/companylist/us/il/chicago/roofers.htm",
    ],
    "maxItems": 10,
    "proxyConfiguration": {
        "useApifyProxy": True,
        "apifyProxyGroups": ["RESIDENTIAL"],
        "apifyProxyCountry": "US",
    },
}

# Run the Actor and wait for it to finish
run = client.actor("parseforge/angies-list-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 '{
  "searchUrls": [
    "https://www.angi.com/companylist/us/ca/los-angeles/plumbers.htm",
    "https://www.angi.com/companylist/us/ny/new-york/electricians.htm",
    "https://www.angi.com/companylist/us/il/chicago/roofers.htm"
  ],
  "maxItems": 10,
  "proxyConfiguration": {
    "useApifyProxy": true,
    "apifyProxyGroups": [
      "RESIDENTIAL"
    ],
    "apifyProxyCountry": "US"
  }
}' |
apify call parseforge/angies-list-scraper --silent --output-dataset

```

## MCP server setup

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

```

## OpenAPI specification

```json
{
    "openapi": "3.0.1",
    "info": {
        "title": "Angi (Angie's List) Contractor & Reviews Scraper",
        "description": "Extract verified home service contractor profiles, ratings, reviews, services, addresses, and business hours from Angi (Angie's List). Used by contractors, insurance, and lead-gen teams.",
        "version": "1.0",
        "x-build-id": "BSCcaOb422Bb9Dtif"
    },
    "servers": [
        {
            "url": "https://api.apify.com/v2"
        }
    ],
    "paths": {
        "/acts/parseforge~angies-list-scraper/run-sync-get-dataset-items": {
            "post": {
                "operationId": "run-sync-get-dataset-items-parseforge-angies-list-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/parseforge~angies-list-scraper/runs": {
            "post": {
                "operationId": "runs-sync-parseforge-angies-list-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/parseforge~angies-list-scraper/run-sync": {
            "post": {
                "operationId": "run-sync-parseforge-angies-list-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",
                "properties": {
                    "searchUrls": {
                        "title": "Angi search URLs",
                        "type": "array",
                        "description": "One or more Angi listing URLs. Use a city + service URL (e.g. https://www.angi.com/companylist/us/ca/los-angeles/plumbers.htm), a state-wide service URL (https://www.angi.com/companylist/us/ny/electricians.htm), or a directory page (https://www.angi.com/companylist/us/tx/). The scraper visits each URL and aggregates contractor profiles.",
                        "items": {
                            "type": "string"
                        }
                    },
                    "maxItems": {
                        "title": "Max Items",
                        "minimum": 1,
                        "maximum": 1000000,
                        "type": "integer",
                        "description": "Free users: Limited to 10 items (preview). Paid users: Optional, max 1,000,000."
                    },
                    "fetchProfileDetails": {
                        "title": "Fetch full contractor profile details",
                        "type": "boolean",
                        "description": "When enabled the scraper visits each contractor's profile page to enrich records with description, address, phone, badges, and review highlights. Disable for a faster, listing-only run.",
                        "default": true
                    },
                    "proxyConfiguration": {
                        "title": "Proxy configuration",
                        "type": "object",
                        "description": "Apify residential US proxy is recommended to bypass Cloudflare and DataDome challenges reliably."
                    }
                }
            },
            "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
                                    }
                                }
                            }
                        }
                    }
                }
            }
        }
    }
}
```
