# Angi Contractors & Reviews Scraper (`automation-lab/angi-contractors-reviews-scraper`) Actor

🏠 Discover Angi contractors by city and trade. Export public profiles, ratings, reviews, services, badges, locations, phones, websites, and photos.

- **URL**: https://apify.com/automation-lab/angi-contractors-reviews-scraper.md
- **Developed by:** [Stas Persiianenko](https://apify.com/automation-lab) (community)
- **Categories:** Lead generation, Business
- **Stats:** 3 total users, 2 monthly users, 100.0% runs succeeded, 0 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 web data automations that power AI and operations. They run on the Apify platform to scrape websites, process data, connect APIs, and automate workflows.
In Batch mode, an Actor accepts a well-defined JSON input, performs an action which can take anything from a few seconds to a few hours,
and optionally produces a well-defined JSON output, datasets with results, or files in key-value store.
In Standby mode, an Actor provides a web server which can be used as a website, API, or an MCP server.
Actors are written with capital "A".

## How to integrate an Actor?

If asked about integration, you help developers integrate Actors into their projects.
You adapt to their stack and deliver integrations that are safe, well-documented, and production-ready.
The best way to integrate Actors is as follows.

In JavaScript/TypeScript projects, use official [JavaScript/TypeScript client](https://docs.apify.com/api/client/js/docs.md):

```bash
npm install apify-client
```

In Python projects, use official [Python client library](https://docs.apify.com/api/client/python/docs.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/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 Contractors & Reviews Scraper

Find home-service businesses on Angi by city and trade, then export their public contractor profiles as clean JSON, CSV, Excel, XML, or API-ready records.

The Actor collects business names, profile URLs, service areas, addresses, ratings, review counts and excerpts, service categories, badges, response signals, descriptions, photos, phone numbers, and websites when Angi publishes them.

Use it for local lead generation, market mapping, contractor sales research, and reputation monitoring without copying data by hand.

### What does Angi Contractors & Reviews Scraper do?

The scraper accepts either:

- 🔎 an Angi city-and-trade directory URL;
- 🏢 a public Angi contractor profile URL; or
- 📍 a city, two-letter state code, and service such as `plumbing`.

It loads Angi's public Next.js pages in a browser session, reads structured application data, and falls back to rendered profile links and structured markup when page internals change.

Each dataset row represents one contractor. Review excerpts stay attached to their contractor so exports remain easy to join and analyze.

### Who is it for?

#### Local lead-generation agencies

Create a current list of contractors in a target city and trade before qualification, outreach, or CRM import.

#### Home-services sales teams

Discover public phone numbers, websites, locations, services, and reputation signals for market-specific prospecting.

#### Contractor-market researchers

Compare provider density, ratings, review volume, categories, advertiser badges, and service areas across markets.

#### Reputation and competitive-intelligence teams

Refresh public Angi ratings and review excerpts on a schedule and detect meaningful changes downstream.

#### Developers and data teams

Call the Actor through the Apify API, webhooks, integrations, or MCP and receive predictable typed records.

### Why use this Angi scraper?

- ✅ **City × trade discovery:** turn a location and service into an Angi directory request.
- ✅ **Direct URL support:** scrape known directory or contractor URLs.
- ✅ **Useful profile depth:** collect more than names and links.
- ✅ **Public reviews:** retain bounded review excerpts with their business.
- ✅ **Fail-closed validation:** unsupported hosts and incomplete location inputs stop with a clear error.
- ✅ **Bounded anti-bot recovery:** sessions rotate without creating unlimited retries.
- ✅ **Structured exports:** use the Apify dataset in JSON, CSV, Excel, XML, RSS, or API workflows.

### What Angi contractor data can I extract?

| Field | Description |
|---|---|
| `contractorId` | Angi provider/profile identifier when exposed |
| `businessName` | Public business or provider name |
| `profileUrl` | Canonical public Angi contractor page |
| `sourceUrl` | Directory or profile URL that produced the record |
| `phone` | Public business phone number when present |
| `website` | Public business website when present |
| `address` | Public street address when present |
| `city`, `state`, `postalCode` | Structured location fields |
| `serviceArea` | Market or service area published by Angi |
| `rating` | Public average rating |
| `reviewCount` | Public review total |
| `reviews` | Bounded public review excerpts with author, rating, date, and featured flag |
| `serviceCategories` | Services or trade categories |
| `badges` | Public awards, certifications, or featured indicators |
| `isAdvertiser` | Paid/advertiser signal when exposed |
| `responseSignals` | Public response-time or reply indicators |
| `description` | Public business description |
| `logoUrl`, `photoUrls` | Public media URLs |
| `scrapedAt` | UTC extraction timestamp |

Fields may be `null` or empty when Angi does not publish them for a particular contractor.

### How to scrape Angi contractors by city and service

1. Open the Actor input page.
2. Enter `city`, `state`, and `service` together.
3. Keep `maxItems` at 10 for a low-cost first run.
4. Choose whether to include public review excerpts.
5. Start the run.
6. Open the Dataset tab to inspect and export contractors.

Example:

```json
{
  "city": "San Francisco",
  "state": "CA",
  "service": "plumbing",
  "maxItems": 10,
  "includeReviews": true,
  "maxReviewsPerContractor": 3
}
````

### How to scrape an Angi directory URL

Paste one or more public Angi URLs into `startUrls`:

```json
{
  "startUrls": [
    { "url": "https://www.angi.com/companylist/us/ca/san-francisco/plumbing.htm" }
  ],
  "maxItems": 25,
  "includeReviews": true
}
```

Only public `angi.com` company-list, company-review, and business paths are accepted. This keeps explicit URLs within the product's promised contractor scope.

### Input reference

| Input | Type | Default | Purpose |
|---|---|---:|---|
| `startUrls` | array | sample directory | Angi directory or contractor profile URLs |
| `city` | string | — | US city for directory discovery |
| `state` | string | — | Two-letter US state code |
| `service` | string | — | Trade slug such as plumbing or roofing |
| `maxItems` | integer | 10 | Maximum unique contractors |
| `includeReviews` | boolean | true | Include public review excerpts |
| `maxReviewsPerContractor` | integer | 3 | Maximum nested reviews per contractor |
| `proxyConfiguration` | object | US residential | Advanced connection settings |

`city`, `state`, and `service` must be supplied as a complete group. You can also omit them and use `startUrls` alone.

### Output example

```json
{
  "contractorId": "1234567",
  "businessName": "Example Plumbing Inc",
  "profileUrl": "https://www.angi.com/companylist/us/ca/example/example-plumbing-inc-reviews-1234567.htm",
  "sourceUrl": "https://www.angi.com/companylist/us/ca/san-francisco/plumbing.htm",
  "phone": "(415) 555-0100",
  "website": "https://example.com/",
  "city": "Example",
  "state": "CA",
  "serviceArea": "San Francisco",
  "rating": 4.8,
  "reviewCount": 127,
  "reviews": [{ "author": "Customer", "rating": 5, "text": "Public review excerpt", "date": null, "isFeatured": true }],
  "serviceCategories": ["Plumbing"],
  "badges": ["Angi Certified"],
  "scrapedAt": "2026-07-22T00:00:00.000Z"
}
```

This example shows the shape, not a promise that every field appears on every page.

### How much does it cost to scrape Angi contractors?

The Actor uses pay-per-event pricing:

- a small one-time run-start charge;
- one `contractor` event for each dataset row saved;
- automatic tier discounts for higher Apify plans.

The exact live prices appear in the Actor pricing tab before every run. Browser and residential-proxy costs are included in the event price; you do not need a separate proxy subscription when using the default Apify Proxy configuration.

Start with 10 contractors to validate your market and output needs before scaling.

### Tips for better contractor datasets

- 🎯 Use one city and one specific trade per source for focused results.
- 🧪 Test with `maxItems: 10` before a larger scheduled workflow.
- 🧹 Deduplicate downstream by `contractorId`, then by `profileUrl`.
- 📅 Store `scrapedAt` when comparing ratings over time.
- 💬 Increase review limits only when text analysis needs them.
- 🔗 Keep the source URL so analysts can trace every contractor.

### Scheduling and monitoring

Apify schedules can refresh the same city-and-trade input daily, weekly, or monthly.

A practical reputation workflow is:

1. run the Actor on a schedule;
2. export the dataset to your database or Google Sheets;
3. compare `rating`, `reviewCount`, `reviews`, and `badges` with the prior snapshot;
4. notify a channel or CRM when a tracked value changes.

For lead discovery, schedule separate tasks by city and trade so failures and exports remain easy to audit.

### Integrations

#### Google Sheets

Send new contractor rows to a sheet for manual qualification and territory assignment.

#### Webhooks

Trigger a webhook when a run succeeds, then ingest the dataset into your CRM or warehouse.

#### Zapier and Make

Build no-code flows that route qualified contractors by city, rating, or review volume.

#### Airbyte and database exports

Move dataset records into a warehouse for market-size, service-density, or reputation analysis.

#### Slack and email alerts

Notify teams when a scheduled comparison detects a rating, review-count, or badge change.

### JavaScript API example

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

const client = new ApifyClient({ token: process.env.APIFY_TOKEN });
const run = await client.actor('automation-lab/angi-contractors-reviews-scraper').call({
  city: 'Austin',
  state: 'TX',
  service: 'roofing',
  maxItems: 20,
  includeReviews: true,
});
const { items } = await client.dataset(run.defaultDatasetId).listItems();
console.log(items);
```

### Python API example

```python
from apify_client import ApifyClient

client = ApifyClient("YOUR_APIFY_TOKEN")
run = client.actor("automation-lab/angi-contractors-reviews-scraper").call(run_input={
    "city": "Austin",
    "state": "TX",
    "service": "roofing",
    "maxItems": 20,
    "includeReviews": True,
})
items = client.dataset(run["defaultDatasetId"]).list_items().items
print(items)
```

### cURL API example

```bash
curl -X POST \
  "https://api.apify.com/v2/acts/automation-lab~angi-contractors-reviews-scraper/runs?token=$APIFY_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"city":"Austin","state":"TX","service":"roofing","maxItems":20}'
```

Fetch results from the run's `defaultDatasetId` through the Apify Dataset API.

### Use Angi data with Apify MCP

Connect AI clients to Apify MCP with this Actor selected:

`https://mcp.apify.com?tools=automation-lab/angi-contractors-reviews-scraper`

#### Claude Code setup

```bash
claude mcp add --transport http apify-angi "https://mcp.apify.com?tools=automation-lab/angi-contractors-reviews-scraper"
```

#### Claude Desktop setup

Add this HTTP server to the Claude Desktop MCP configuration:

```json
{
  "mcpServers": {
    "apify-angi": {
      "url": "https://mcp.apify.com?tools=automation-lab/angi-contractors-reviews-scraper"
    }
  }
}
```

#### Cursor setup

Use the same `mcpServers` JSON block in Cursor MCP settings and enable `apify-angi`.

#### VS Code setup

Add the same `mcpServers` JSON block through VS Code MCP server settings, then select the Angi tool in agent mode.

Example prompts:

- “Run the Angi contractor scraper for plumbers in San Francisco and summarize rating distribution.”
- “Extract 20 roofers in Austin, then identify businesses with strong review volume.”
- “Compare the new Angi contractor dataset with last week's snapshot.”

### Data quality and deduplication

The Actor prefers stable provider IDs. When an ID is unavailable, it uses the canonical profile URL and business name to prevent duplicate rows within one run.

Angi may expose richer data for paid profiles than basic profiles. Missing values remain `null` instead of being guessed.

Review excerpts are public page content and may represent only a featured or bounded subset. `reviewCount` is the better field for total-volume analysis.

### Reliability and anti-bot handling

Angi protects pages with Cloudflare and browser checks. The Actor therefore uses a conservative browser route with US residential sessions, concurrency one, media blocking, and bounded rotation.

If all sessions receive a challenge or no structured contractor data, the run fails non-zero instead of reporting misleading success with zero records.

A successful run can still return fewer than `maxItems` when the selected directory has naturally limited public listings.

### Limitations

- Angi can change page internals, field names, directory slugs, and profile availability.
- Public contact fields are not present for every contractor.
- This v1 does not purchase, infer, or enrich email addresses.
- Review excerpts are bounded and are not guaranteed to represent every review.
- The Actor targets US Angi city/trade and public contractor pages.
- A challenge-heavy period may require another session and increase run time.
- Results reflect what Angi publicly displayed at extraction time.

### Responsible and legal use

This Actor extracts publicly accessible business information. It does not bypass login walls or request private homeowner/project data.

You are responsible for your use of the data. Review Angi's terms, applicable database rights, privacy rules, telemarketing requirements, and local laws before outreach or redistribution.

Use reasonable schedules, collect only fields needed for a legitimate purpose, and honor deletion or suppression obligations in downstream systems.

### Troubleshooting

#### Why did my run reject the URL?

The Actor accepts only public `angi.com` contractor-related paths. Use a company-list directory, company-review page, business page, or city/state/service discovery input.

#### Why must city, state, and service be entered together?

All three values are needed to construct an unambiguous Angi directory URL. Remove all three when supplying `startUrls` instead.

#### Why are phone or website fields null?

Angi does not publish those fields for every profile. The Actor does not guess or buy missing contact data.

#### Why did the run fail after retries?

Angi may have served browser challenges to every bounded session or changed its structured data. Retry later with a small input and inspect the run log. Persistent failures should be reported with the source URL and run ID.

#### Why did I receive fewer contractors than `maxItems`?

`maxItems` is a ceiling, not a guarantee. The directory may contain fewer public listings or duplicate links.

### Frequently asked questions

#### Does the Actor require an Angi login?

No. It targets the public no-login contractor and directory surface.

#### Can it extract emails?

No. Paid or inferred email enrichment is intentionally excluded from v1. Public phone and website fields are returned when present.

#### Can I scrape one contractor profile?

Yes. Supply its public Angi company-review or business URL in `startUrls` and set `maxItems` to 1.

#### Can I export to CSV or Excel?

Yes. Open the dataset and choose the desired export format, or use the Dataset API.

#### Can I monitor ratings over time?

Yes. Schedule repeat runs and compare `contractorId`, `rating`, `reviewCount`, `reviews`, and `scrapedAt` in your datastore.

#### Is `maxItems` a pagination guarantee?

No. It limits the output. Available records depend on the public directory and page state.

### Related scrapers

- [HomeAdvisor Contractors & Reviews Scraper](https://apify.com/automation-lab/homeadvisor-contractors-reviews-scraper) — use a different home-services marketplace for complementary contractor coverage.
- [Google Maps Lead Finder](https://apify.com/automation-lab/google-maps-lead-finder) — discover broader local businesses and optionally enrich public websites.
- [Yellow Pages Scraper](https://apify.com/automation-lab/yellowpages-scraper) — compare directory coverage and public business contacts.

These actors target different public sources. Combining them can improve market coverage, but deduplicate by normalized business name, address, phone, and website.

### Support

If a run fails, share the run ID, exact input, and expected Angi page. Do not include private credentials or personal homeowner data.

For the fastest diagnosis, keep the failed run available and note whether the same URL opens publicly in a normal US browser.

# Actor input Schema

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

Public angi.com company list, company review, or business URLs.

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

US city used to construct an Angi trade directory URL.

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

Two-letter US state code.

## `service` (type: `string`):

Angi directory trade such as plumbing, roofing, or landscaping.

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

Stop after this many unique contractor records.

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

Extract review text embedded in public Angi pages.

## `maxReviewsPerContractor` (type: `integer`):

Maximum nested public review excerpts per contractor.

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

US residential Apify Proxy is used by default because Angi blocks ordinary datacenter requests.

## Actor input object example

```json
{
  "startUrls": [
    {
      "url": "https://www.angi.com/companylist/us/ca/san-francisco/plumbing.htm"
    }
  ],
  "maxItems": 10,
  "includeReviews": true,
  "maxReviewsPerContractor": 3,
  "proxyConfiguration": {
    "useApifyProxy": true,
    "apifyProxyGroups": [
      "RESIDENTIAL"
    ],
    "apifyProxyCountry": "US"
  }
}
```

# Actor output Schema

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

Open the default dataset overview containing one typed record per unique contractor.

# 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 = {
    "startUrls": [
        {
            "url": "https://www.angi.com/companylist/us/ca/san-francisco/plumbing.htm"
        }
    ],
    "maxItems": 10,
    "maxReviewsPerContractor": 3
};

// Run the Actor and wait for it to finish
const run = await client.actor("automation-lab/angi-contractors-reviews-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 = {
    "startUrls": [{ "url": "https://www.angi.com/companylist/us/ca/san-francisco/plumbing.htm" }],
    "maxItems": 10,
    "maxReviewsPerContractor": 3,
}

# Run the Actor and wait for it to finish
run = client.actor("automation-lab/angi-contractors-reviews-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 '{
  "startUrls": [
    {
      "url": "https://www.angi.com/companylist/us/ca/san-francisco/plumbing.htm"
    }
  ],
  "maxItems": 10,
  "maxReviewsPerContractor": 3
}' |
apify call automation-lab/angi-contractors-reviews-scraper --silent --output-dataset

```

## MCP server setup

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

```

## OpenAPI specification

```json
{
    "openapi": "3.0.1",
    "info": {
        "title": "Angi Contractors & Reviews Scraper",
        "description": "🏠 Discover Angi contractors by city and trade. Export public profiles, ratings, reviews, services, badges, locations, phones, websites, and photos.",
        "version": "0.1",
        "x-build-id": "X43u4DKlE9c1ucUev"
    },
    "servers": [
        {
            "url": "https://api.apify.com/v2"
        }
    ],
    "paths": {
        "/acts/automation-lab~angi-contractors-reviews-scraper/run-sync-get-dataset-items": {
            "post": {
                "operationId": "run-sync-get-dataset-items-automation-lab-angi-contractors-reviews-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/automation-lab~angi-contractors-reviews-scraper/runs": {
            "post": {
                "operationId": "runs-sync-automation-lab-angi-contractors-reviews-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/automation-lab~angi-contractors-reviews-scraper/run-sync": {
            "post": {
                "operationId": "run-sync-automation-lab-angi-contractors-reviews-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": {
                    "startUrls": {
                        "title": "Angi directory or profile URLs",
                        "type": "array",
                        "description": "Public angi.com company list, company review, or business URLs.",
                        "items": {
                            "type": "object",
                            "required": [
                                "url"
                            ],
                            "properties": {
                                "url": {
                                    "type": "string",
                                    "title": "URL of a web page",
                                    "format": "uri"
                                }
                            }
                        }
                    },
                    "city": {
                        "title": "City",
                        "type": "string",
                        "description": "US city used to construct an Angi trade directory URL."
                    },
                    "state": {
                        "title": "State",
                        "minLength": 2,
                        "maxLength": 2,
                        "type": "string",
                        "description": "Two-letter US state code."
                    },
                    "service": {
                        "title": "Service or trade",
                        "type": "string",
                        "description": "Angi directory trade such as plumbing, roofing, or landscaping."
                    },
                    "maxItems": {
                        "title": "Maximum contractors",
                        "minimum": 1,
                        "maximum": 5000,
                        "type": "integer",
                        "description": "Stop after this many unique contractor records.",
                        "default": 10
                    },
                    "includeReviews": {
                        "title": "Include public review excerpts",
                        "type": "boolean",
                        "description": "Extract review text embedded in public Angi pages.",
                        "default": true
                    },
                    "maxReviewsPerContractor": {
                        "title": "Reviews per contractor",
                        "minimum": 0,
                        "maximum": 25,
                        "type": "integer",
                        "description": "Maximum nested public review excerpts per contractor.",
                        "default": 3
                    },
                    "proxyConfiguration": {
                        "title": "Proxy configuration",
                        "type": "object",
                        "description": "US residential Apify Proxy is used by default because Angi blocks ordinary datacenter requests.",
                        "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
                                    }
                                }
                            }
                        }
                    }
                }
            }
        }
    }
}
```
