# Angi Scraper - Home Service Pro Leads, Reviews & Contacts (`scrapesage/angi-leads-scraper`) Actor

Scrape Angi (Angie's List) home-service pros by category & city: business name, phone, address, rating, reviews, paid-pro / Super Service Award badges, services, payment methods + lead score & monitoring. No login, no browser.

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

## Pricing

from $8.00 / 1,000 pro lead scrapeds

This Actor is paid per event. You are not charged for the Apify platform usage, but only a fixed price for specific events.

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

## Angi Scraper — Home Service Pro Leads, Reviews & Contacts

Extract **complete home-service-pro data from [Angi](https://www.angi.com)** (formerly Angie's List / HomeAdvisor) by **service category and city** — business name, **phone number**, full address, star rating, review count, **paid-pro / Super Service Award / verified badges**, services offered, payment methods, business facts and every customer review. Each pro comes with a **0–100 lead score** so your best prospects float to the top.

No login, no API key, no browser — fast, reliable extraction of the **richest Angi dataset on the market**, built for **B2B lead generation** across plumbers, electricians, HVAC, roofers, landscapers, cleaners, painters, remodelers and 60+ more trades.

### Why this Angi scraper?

Most "Angi scrapers" grab a name and a rating and stop there. This actor reads Angi's category-listing **and** profile pages directly, merges the public JSON-LD with the page's embedded data, and ships the fields that actually generate revenue — starting with the **phone number** and the **buying-intent badges** (active advertiser / paid pro).

| Data | Generic scrapers | This actor |
|---|---|---|
| Business name, category, city/state | ✅ | ✅ |
| **Phone number** | ❌ | ✅ when listed |
| Full street address + ZIP | partial | ✅ when listed |
| Overall rating + review count | partial | ✅ authoritative |
| **Super Service Award** winner | ❌ | ✅ |
| **Paid pro / active advertiser** (buying-intent) | ❌ | ✅ |
| Verified-business badge | ❌ | ✅ |
| Services offered | ❌ | ✅ when listed |
| Payment methods | ❌ | ✅ |
| Business facts (emergency service, free estimates, warranties) | ❌ | ✅ |
| Years in business | ❌ | ✅ when listed |
| Full customer reviews (rating, text, author, date) | partial | ✅ |
| **0–100 lead score** | ❌ | ✅ |
| Monitoring (only-new pros) | ❌ | ✅ |
| One clean dataset per entity (no empty columns) | ❌ | ✅ |

### Use cases

- **Lead generation for B2B sellers** — home-service pros buy software, insurance, financing, marketing, fleet, uniforms, equipment and SaaS. Export them with phone, address, rating and lead score and feed your CRM or outreach sequence. **Paid-pro / advertiser** flags surface the businesses already spending on growth.
- **Franchise & acquisition prospecting** — find high-rated, established pros (Super Service Award, 10+ years, 100+ reviews) by trade and metro for roll-ups, partnerships and franchising.
- **Competitive & market research** — map who serves a city in any trade, at what rating, with what services and how many reviews.
- **Reputation & review mining** — pull every customer review for sentiment analysis, testimonials, or competitor monitoring.
- **Local SEO & directory building** — build category × city business directories with names, ratings and review counts.

### How to use

1. [Sign up for Apify](https://console.apify.com/sign-up) — the free plan is enough to try this actor.
2. Open the **Angi Scraper**, set the **categories** (e.g. `plumbing`, `roofing`, `hvac`) and **locations** (`Austin, TX`, `Denver, CO`), and a **max pros** cap.
3. Click **Start** and watch results stream into the dataset table.
4. **Export** as JSON, CSV, Excel, XML, or RSS — or pull results programmatically via the [Apify API](https://docs.apify.com/api/v2).

### Input

```json
{
    "categories": ["plumbing", "hvac"],
    "locations": ["Austin, TX", "Denver, CO"],
    "maxResults": 100,
    "includeProfileDetails": true,
    "includeReviews": false,
    "withPhoneOnly": false,
    "monitorMode": false
}
````

- **categories** — home-service categories (friendly names or Angi slugs): `plumbing`, `electrical`, `hvac`, `roofing`, `landscaping`, `house cleaning`, `pest control`, `painting`, `flooring`, `handyman`, `garage doors`, `tree service`, `windows`, `fencing`, `appliance repair`, `foundation repair`, `remodeling`, and 60+ more.
- **locations** — US cities as `City, ST` (a state is required — Angi lists pros by city).
- **startUrls** *(optional)* — paste Angi category-listing URLs (`…/companylist/us/tx/austin/plumbing.htm`) or individual profile URLs (`…-reviews-158736564.htm`) to scrape directly.
- **maxResults** *(default 100)* — cap on pro records emitted (reviews don't count toward it).
- **maxPagesPerListing** *(default 3)* — how many result pages to page through per category+city (duplicates removed automatically).
- **includeProfileDetails** *(default true)* — open each pro's profile for the **phone number**, badges, services, payment methods and business facts. Turn off for a faster name + city + review-snippet scan.
- **includeReviews** *(default false)* — also emit each pro's reviews as separate rows.
- **minRating / minReviews / withPhoneOnly / paidProOnly / superServiceAwardOnly** — quality filters.
- **monitorMode** *(default false)* — remember pros from previous runs and emit only **new** ones (see below).
- **maxConcurrency** *(default 8)* and **proxyConfiguration** — performance & proxy (US residential by default).

### Output

By default you get **one dense table of pros**. A pro record (`type: "pro"`):

```json
{
    "type": "pro",
    "businessName": "We Plumb",
    "category": "plumbing",
    "phone": "(737) 297-5863",
    "street": null,
    "city": "Austin",
    "state": "TX",
    "zipCode": "78702",
    "areaServed": "Austin, TX",
    "rating": 5,
    "reviewCount": 8,
    "isPaidPro": true,
    "isAdvertiser": true,
    "isSuperServiceAward": false,
    "isVerified": true,
    "isCorporateAccount": false,
    "profileType": "PAID_PROFILE",
    "yearsInBusiness": null,
    "services": ["Drain Cleaning", "Water Heater Installation"],
    "paymentMethods": ["Credit Card"],
    "businessFacts": { "Emergency Services": "Yes", "Free Estimates": "Yes", "Warranties": "Yes" },
    "description": "We Plumb provides a wide variety of plumbing services…",
    "logoUrl": "https://cdn.homeadvisor.com/…/original.jpg",
    "angiProviderId": "158736564",
    "profileUrl": "https://www.angi.com/companylist/us/tx/austin/we-plumb-reviews-10565886.htm",
    "leadScore": 51,
    "scrapedAt": "2026-06-23T12:00:00.000Z"
}
```

A review record (`type: "review"`) carries `businessName`, `rating`, `text`, `author`, `datePublished` and `profileUrl`. Use the **Pros**, **Leads** and **Reviews** dataset views to switch between them.

#### What to expect (field coverage)

Angi mixes pro-entered and platform data, so some fields are present only when the pro filled them in. Verified across multiple metros and trades:

| Field | Coverage |
|---|---|
| Business name, category, city/state, rating, review count, profile URL, badges | ✅ ~100% |
| **Phone number** | ✅ on paid/advertiser pros; absent on some free profiles |
| Business facts (emergency / free estimates / warranties), payment methods | ✅ usually present |
| Full street address + ZIP | ✅ when the pro lists a physical address (many are service-area only → city/ZIP) |
| Services offered, years in business, description | ✅ when the pro published them |
| Customer reviews | ✅ the reviews shown on the public profile |

A blank field means Angi didn't publish it for that pro — not that scraping failed. Nothing is dropped, so you always get the richest dataset available.

### Monitoring — only get new pros

Turn on **monitorMode** and the actor remembers every pro it has emitted (in a named key-value store) and returns only **new** pros on each subsequent run. Pair it with a [Schedule](https://docs.apify.com/platform/schedules) to track a metro/trade as new pros join Angi — perfect for a steady drip of fresh leads. Monitor mode is fully **orthogonal to Apify Schedules**: the schedule decides *when* a run starts; monitor mode decides *which* records are new, so the two compose cleanly without conflict.

### Automate & schedule

- **[Apify API](https://docs.apify.com/api/v2)** — start runs, fetch datasets, manage schedules over REST.
- **[apify-client for JavaScript](https://docs.apify.com/api/client/js/)** and **[Python](https://docs.apify.com/api/client/python/)** — official SDKs.
- **[Schedules](https://docs.apify.com/platform/schedules)** — run it daily/weekly with monitor mode to capture newly listed pros.
- **[Webhooks](https://docs.apify.com/platform/integrations/webhooks)** — trigger CRM import, Slack alert or an email sequence the moment a run finishes.

```js
import { ApifyClient } from 'apify-client';

const client = new ApifyClient({ token: 'MY_APIFY_TOKEN' });

const run = await client.actor('scrapesage/angi-leads-scraper').call({
    categories: ['plumbing', 'hvac'],
    locations: ['Austin, TX'],
    maxResults: 100,
    includeProfileDetails: true,
});

const { items } = await client.dataset(run.defaultDatasetId).listItems();
console.log(`Got ${items.length} Angi pros`);
```

### Integrate with any app

Connect the dataset to 5,000+ apps — no code required:

- **[Make](https://docs.apify.com/platform/integrations/make)** — multi-step automation scenarios.
- **[Zapier](https://docs.apify.com/platform/integrations/zapier)** — push new pro leads straight into your CRM.
- **[Slack](https://docs.apify.com/platform/integrations/slack)** — get notified when a monitored city/trade adds pros.
- **[Google Drive / Sheets](https://docs.apify.com/platform/integrations/drive)** — auto-export every run to a spreadsheet.
- **[Airbyte](https://docs.apify.com/platform/integrations/airbyte)** — pipe results into your data warehouse.
- **[GitHub](https://docs.apify.com/platform/integrations/github)** — trigger runs from commits or releases.

### Use with AI assistants (MCP)

The output is clean, LLM-ready JSON. Call this actor from Claude, ChatGPT, or any agent framework through the **[Apify MCP server](https://docs.apify.com/platform/integrations/mcp)** — ask your assistant to "find the top-rated plumbers in Austin with a phone number and a Super Service Award" and let it run the scraper for you.

### More scrapers from scrapesage

Build a complete **home-services & local lead-gen stack**:

- **[Thumbtack Scraper](https://apify.com/scrapesage/thumbtack-scraper)** — home-service pros, reviews, hire counts & leads from Thumbtack.
- **[BuildZoom Scraper](https://apify.com/scrapesage/buildzoom-scraper)** — contractors with license, permit history & project data.
- **[Houzz Scraper](https://apify.com/scrapesage/houzz-scraper)** — remodeling & design pros with phone, website & socials.
- **[Hipages Scraper](https://apify.com/scrapesage/hipages-scraper)** — Australian tradies & home-service leads.
- **[Bark Listing Scraper](https://apify.com/scrapesage/bark-listing-scraper)** — service-provider leads from Bark.
- **[Expertise.com Scraper](https://apify.com/scrapesage/expertise-scraper)** — vetted "best of" local pros by city & category.
- **[Three Best Rated Scraper](https://apify.com/scrapesage/three-best-rated-scraper)** — top-3 hand-picked local businesses.
- **[US Contractor License Scraper](https://apify.com/scrapesage/us-contractor-license-scraper)** — state contractor-license rolls (CA/WA/OR).
- **[Google Maps Scraper](https://apify.com/scrapesage/google-maps-scraper)** — local business leads, emails & reviews.
- **[Website Contact Scraper](https://apify.com/scrapesage/website-contact-scraper)** — emails, phones & socials from any business website.

### Tips

- **Keep `includeProfileDetails` on** — it's the difference between a name and a contactable lead (phone, badges, services). It adds one fast page per pro.
- **Stack categories × cities** for breadth — Angi pins the same sponsored pros at the top of every page, so running more trades and metros yields far more unique pros than paging alone (the actor already pages and dedupes for you).
- **Use `paidProOnly` / `superServiceAwardOnly`** to target the highest-intent or highest-quality pros only.
- **Recurring leads**: combine a [Schedule](https://docs.apify.com/platform/schedules) with **monitorMode** to receive only newly listed pros each run.
- **Proxy**: Angi serves clean pages only to **US residential IPs** — the default proxy is already set correctly; keep it.

### FAQ

**Which trades can I scrape?** 60+ categories including plumbing, electrical, HVAC, roofing, siding, landscaping, lawn care, tree service, house cleaning, carpet/window cleaning, pressure washing, pest control, painting, flooring, handyman, garage doors, windows, doors, fencing, drywall, insulation, concrete, foundation repair, appliance repair, moving, remodeling, home builders, septic and more. Pass a friendly name or an Angi slug.

**Does it return phone numbers?** Yes — when a pro lists one. Angi exposes the phone on active advertiser / paid-pro profiles, which the actor extracts. Use `withPhoneOnly` to keep only pros with a phone.

**Does it need the Angi API or a key?** No. There's no public Angi API; this actor reads the same data the website serves to visitors — no key or login needed.

**How do I monitor a city for new pros?** Turn on **monitorMode** and create a [Schedule](https://docs.apify.com/platform/schedules). Each run emits only pros not seen before; add a [webhook](https://docs.apify.com/platform/integrations/webhooks) or [Zapier zap](https://docs.apify.com/platform/integrations/zapier) to push them into your CRM automatically.

**A field is empty — why?** Some pros are service-area businesses (no street address), some leave services or years-in-business blank, and free profiles may not list a phone. Fields are blank only when Angi didn't publish that data — never because the scraper skipped it.

**Can I export to Google Sheets, CSV, or Excel?** Yes — one click in the dataset view, or automatically on every run via the [Google Drive integration](https://docs.apify.com/platform/integrations/drive).

**Is scraping Angi legal?** This actor collects publicly available data only. You're responsible for using the data in compliance with applicable laws (e.g. GDPR/CCPA for personal data) and Angi's terms.

### Need help?

Open an issue on the actor's **Issues** tab, or visit the [Apify help center](https://help.apify.com/). Feature requests are welcome — this actor is actively maintained.

# Actor input Schema

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

Home-service categories to scrape (friendly names or Angi slugs). Examples: plumbing, electrical, hvac, roofing, landscaping, house cleaning, pest control, painting, flooring, handyman, garage doors, tree service, windows, fencing, appliance repair, foundation repair, remodeling.

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

US cities to scrape, each as "City, ST" or "City, State" (a state is required — Angi lists pros by city). Examples: "Austin, TX", "Denver, CO", "Miami, FL".

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

Paste Angi category-listing URLs (…/companylist/us/tx/austin/plumbing.htm) or individual pro-profile URLs (…-reviews-158736564.htm) to scrape directly instead of, or in addition to, categories × locations.

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

Maximum number of pro records to emit across the whole run. Reviews do not count toward this cap.

## `maxPagesPerListing` (type: `integer`):

How many result pages to page through per category+city (Angi pins sponsored pros at the top but the organic tail paginates; duplicates are removed automatically).

## `includeProfileDetails` (type: `boolean`):

Open each pro's profile page to extract the PHONE NUMBER, authoritative rating & review count, paid-pro / Super Service Award / verified badges, services offered, payment methods and business facts. Turn off for a faster, name + city + review-snippet only scan.

## `includeReviews` (type: `boolean`):

Also emit each pro's customer reviews as separate rows (rating, text, author, date). Requires profile details.

## `maxReviewsPerPro` (type: `integer`):

Cap the number of review rows emitted per pro when "Include customer reviews" is on.

## `minRating` (type: `integer`):

Only keep pros with an overall star rating at or above this value (0 = no filter).

## `minReviews` (type: `integer`):

Only keep pros with at least this many reviews (0 = no filter).

## `withPhoneOnly` (type: `boolean`):

Drop pros for whom no phone number was found (requires profile details).

## `paidProOnly` (type: `boolean`):

Keep only pros that are active Angi advertisers / paid profiles (a buying-intent signal).

## `superServiceAwardOnly` (type: `boolean`):

Keep only pros that have won Angi's Super Service Award.

## `deduplicateResults` (type: `boolean`):

Remove duplicate pros (same Angi provider id) within a run — useful when a pro appears across several categories or cities.

## `monitorMode` (type: `boolean`):

Remember pros from previous runs (in a named key-value store) and emit only NEW ones on each run. Pair with an Apify Schedule to track newly listed pros over time. Leave off for a normal full scrape.

## `monitorStoreName` (type: `string`):

Name of the key-value store that holds the monitor-mode memory. Use different names to track different niches independently. Lowercase letters, digits and hyphens only.

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

How many pages to fetch in parallel. Lower this if you hit blocks.

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

Angi serves clean pages only to US residential IPs. The default (Apify Proxy RESIDENTIAL, US) is strongly recommended — datacenter IPs get Cloudflare-challenged.

## Actor input object example

```json
{
  "categories": [
    "plumbing"
  ],
  "locations": [
    "Austin, TX"
  ],
  "startUrls": [],
  "maxResults": 100,
  "maxPagesPerListing": 3,
  "includeProfileDetails": true,
  "includeReviews": false,
  "maxReviewsPerPro": 20,
  "minRating": 0,
  "minReviews": 0,
  "withPhoneOnly": false,
  "paidProOnly": false,
  "superServiceAwardOnly": false,
  "deduplicateResults": true,
  "monitorMode": false,
  "monitorStoreName": "angi-leads-monitor",
  "maxConcurrency": 8,
  "proxyConfiguration": {
    "useApifyProxy": true,
    "apifyProxyGroups": [
      "RESIDENTIAL"
    ],
    "apifyProxyCountry": "US"
  }
}
```

# Actor output Schema

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

All scraped records in the default dataset. Pro rows carry the business profile, phone, full address, rating, review count, badges, services, payment methods, business facts and lead score; review rows carry their own rating, text, author and date.

# 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": [
        "Austin, TX"
    ],
    "startUrls": [],
    "maxResults": 100,
    "maxPagesPerListing": 3,
    "proxyConfiguration": {
        "useApifyProxy": true,
        "apifyProxyGroups": [
            "RESIDENTIAL"
        ],
        "apifyProxyCountry": "US"
    }
};

// Run the Actor and wait for it to finish
const run = await client.actor("scrapesage/angi-leads-scraper").call(input);

// Fetch and print Actor results from the run's dataset (if any)
console.log('Results from dataset');
console.log(`💾 Check your data here: https://console.apify.com/storage/datasets/${run.defaultDatasetId}`);
const { items } = await client.dataset(run.defaultDatasetId).listItems();
items.forEach((item) => {
    console.dir(item);
});

// 📚 Want to learn more 📖? Go to → https://docs.apify.com/api/client/js/docs

```

## Python example

```python
from apify_client import ApifyClient

# Initialize the ApifyClient with your Apify API token
# Replace '<YOUR_API_TOKEN>' with your token.
client = ApifyClient("<YOUR_API_TOKEN>")

# Prepare the Actor input
run_input = {
    "categories": ["plumbing"],
    "locations": ["Austin, TX"],
    "startUrls": [],
    "maxResults": 100,
    "maxPagesPerListing": 3,
    "proxyConfiguration": {
        "useApifyProxy": True,
        "apifyProxyGroups": ["RESIDENTIAL"],
        "apifyProxyCountry": "US",
    },
}

# Run the Actor and wait for it to finish
run = client.actor("scrapesage/angi-leads-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": [
    "Austin, TX"
  ],
  "startUrls": [],
  "maxResults": 100,
  "maxPagesPerListing": 3,
  "proxyConfiguration": {
    "useApifyProxy": true,
    "apifyProxyGroups": [
      "RESIDENTIAL"
    ],
    "apifyProxyCountry": "US"
  }
}' |
apify call scrapesage/angi-leads-scraper --silent --output-dataset

```

## MCP server setup

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

```

## OpenAPI specification

```json
{
    "openapi": "3.0.1",
    "info": {
        "title": "Angi Scraper - Home Service Pro Leads, Reviews & Contacts",
        "description": "Scrape Angi (Angie's List) home-service pros by category & city: business name, phone, address, rating, reviews, paid-pro / Super Service Award badges, services, payment methods + lead score & monitoring. No login, no browser.",
        "version": "0.1",
        "x-build-id": "ng7b48PZLELir32aZ"
    },
    "servers": [
        {
            "url": "https://api.apify.com/v2"
        }
    ],
    "paths": {
        "/acts/scrapesage~angi-leads-scraper/run-sync-get-dataset-items": {
            "post": {
                "operationId": "run-sync-get-dataset-items-scrapesage-angi-leads-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/scrapesage~angi-leads-scraper/runs": {
            "post": {
                "operationId": "runs-sync-scrapesage-angi-leads-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/scrapesage~angi-leads-scraper/run-sync": {
            "post": {
                "operationId": "run-sync-scrapesage-angi-leads-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": {
                    "categories": {
                        "title": "Service categories",
                        "type": "array",
                        "description": "Home-service categories to scrape (friendly names or Angi slugs). Examples: plumbing, electrical, hvac, roofing, landscaping, house cleaning, pest control, painting, flooring, handyman, garage doors, tree service, windows, fencing, appliance repair, foundation repair, remodeling.",
                        "default": [
                            "plumbing"
                        ],
                        "items": {
                            "type": "string"
                        }
                    },
                    "locations": {
                        "title": "Locations (City, ST)",
                        "type": "array",
                        "description": "US cities to scrape, each as \"City, ST\" or \"City, State\" (a state is required — Angi lists pros by city). Examples: \"Austin, TX\", \"Denver, CO\", \"Miami, FL\".",
                        "default": [
                            "Austin, TX"
                        ],
                        "items": {
                            "type": "string"
                        }
                    },
                    "startUrls": {
                        "title": "Start URLs (optional)",
                        "type": "array",
                        "description": "Paste Angi category-listing URLs (…/companylist/us/tx/austin/plumbing.htm) or individual pro-profile URLs (…-reviews-158736564.htm) to scrape directly instead of, or in addition to, categories × locations.",
                        "items": {
                            "type": "string"
                        }
                    },
                    "maxResults": {
                        "title": "Max pros (results cap)",
                        "minimum": 1,
                        "type": "integer",
                        "description": "Maximum number of pro records to emit across the whole run. Reviews do not count toward this cap.",
                        "default": 100
                    },
                    "maxPagesPerListing": {
                        "title": "Max listing pages per category/city",
                        "minimum": 1,
                        "maximum": 10,
                        "type": "integer",
                        "description": "How many result pages to page through per category+city (Angi pins sponsored pros at the top but the organic tail paginates; duplicates are removed automatically).",
                        "default": 3
                    },
                    "includeProfileDetails": {
                        "title": "Fetch full profile details (phone, badges, services)",
                        "type": "boolean",
                        "description": "Open each pro's profile page to extract the PHONE NUMBER, authoritative rating & review count, paid-pro / Super Service Award / verified badges, services offered, payment methods and business facts. Turn off for a faster, name + city + review-snippet only scan.",
                        "default": true
                    },
                    "includeReviews": {
                        "title": "Include customer reviews",
                        "type": "boolean",
                        "description": "Also emit each pro's customer reviews as separate rows (rating, text, author, date). Requires profile details.",
                        "default": false
                    },
                    "maxReviewsPerPro": {
                        "title": "Max reviews per pro",
                        "minimum": 1,
                        "maximum": 200,
                        "type": "integer",
                        "description": "Cap the number of review rows emitted per pro when \"Include customer reviews\" is on.",
                        "default": 20
                    },
                    "minRating": {
                        "title": "Minimum rating",
                        "minimum": 0,
                        "maximum": 5,
                        "type": "integer",
                        "description": "Only keep pros with an overall star rating at or above this value (0 = no filter).",
                        "default": 0
                    },
                    "minReviews": {
                        "title": "Minimum review count",
                        "minimum": 0,
                        "type": "integer",
                        "description": "Only keep pros with at least this many reviews (0 = no filter).",
                        "default": 0
                    },
                    "withPhoneOnly": {
                        "title": "Only pros with a phone number",
                        "type": "boolean",
                        "description": "Drop pros for whom no phone number was found (requires profile details).",
                        "default": false
                    },
                    "paidProOnly": {
                        "title": "Only paid pros / advertisers",
                        "type": "boolean",
                        "description": "Keep only pros that are active Angi advertisers / paid profiles (a buying-intent signal).",
                        "default": false
                    },
                    "superServiceAwardOnly": {
                        "title": "Only Super Service Award winners",
                        "type": "boolean",
                        "description": "Keep only pros that have won Angi's Super Service Award.",
                        "default": false
                    },
                    "deduplicateResults": {
                        "title": "Deduplicate pros",
                        "type": "boolean",
                        "description": "Remove duplicate pros (same Angi provider id) within a run — useful when a pro appears across several categories or cities.",
                        "default": true
                    },
                    "monitorMode": {
                        "title": "Monitor mode (only new pros)",
                        "type": "boolean",
                        "description": "Remember pros from previous runs (in a named key-value store) and emit only NEW ones on each run. Pair with an Apify Schedule to track newly listed pros over time. Leave off for a normal full scrape.",
                        "default": false
                    },
                    "monitorStoreName": {
                        "title": "Monitor store name",
                        "type": "string",
                        "description": "Name of the key-value store that holds the monitor-mode memory. Use different names to track different niches independently. Lowercase letters, digits and hyphens only.",
                        "default": "angi-leads-monitor"
                    },
                    "maxConcurrency": {
                        "title": "Max concurrency",
                        "minimum": 1,
                        "maximum": 20,
                        "type": "integer",
                        "description": "How many pages to fetch in parallel. Lower this if you hit blocks.",
                        "default": 8
                    },
                    "proxyConfiguration": {
                        "title": "Proxy configuration",
                        "type": "object",
                        "description": "Angi serves clean pages only to US residential IPs. The default (Apify Proxy RESIDENTIAL, US) is strongly recommended — datacenter IPs get Cloudflare-challenged.",
                        "default": {
                            "useApifyProxy": true,
                            "apifyProxyGroups": [
                                "RESIDENTIAL"
                            ],
                            "apifyProxyCountry": "US"
                        }
                    }
                }
            },
            "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
                                    }
                                }
                            }
                        }
                    }
                }
            }
        }
    }
}
```
