Angi Scraper avatar

Angi Scraper

Pricing

from $0.80 / 1,000 results

Go to Apify Store
Angi Scraper

Angi Scraper

[πŸ’° $0.8 / 1K] Extract contractor and home-service pro listings from Angi.com - business names, phone numbers, addresses, ratings, reviews, hours, and photos. Search by keyword and location, browse by category, paste Angi URLs directly. Optional per-pro reviews extraction.

Pricing

from $0.80 / 1,000 results

Rating

0.0

(0)

Developer

SolidCode

SolidCode

Maintained by Community

Actor stats

0

Bookmarked

29

Total users

4

Monthly active users

10 days ago

Last modified

Share

Extract contractor and home-service pro listings from Angi.com at scale. Get business names, phone numbers, street addresses, ratings, review counts, opening hours, sub-categories, logos, descriptions, and per-pro reviews, for any trade in any US city or ZIP code. Built for lead-gen teams, agencies and market researchers who need structured data on local home-service pros without paying enterprise directory prices.

Why This Scraper?

  • From $0.80 per 1,000 results β€” one flat per-result rate for listings and full profiles alike, with no compute or time-based charges. Records Angi refuses to open are dropped before they reach your bill.
  • 887 trade categories reachable β€” a 30-trade dropdown covering Plumbing, Heating & Cooling (HVAC), Roofing, Junk Removal, Garage Doors, Concrete, Pools & Spas and more, plus automatic mapping of any free-text term to Angi's nearest internal category.
  • Phone, street address and years in business on essentially every full profile β€” plus a website on roughly 2 in 3 pros and 7-day opening hours on roughly 6 in 10, which is every pro who published them to Angi.
  • Multi-borough metros fan out automatically β€” "New York, NY" sweeps Manhattan, Brooklyn, Queens, the Bronx and Staten Island, then de-duplicates pros by profile URL so a cross-borough repeat is never billed twice.
  • Two hard caps you can compute before you run β€” maxResults is enforced across every search term, category, start URL and city combined, so a five-term run cannot quietly bill five times the number you typed; with reviews on, the worst case is exactly maxResults x (1 + maxReviewsPerPro), printed in the log before collection starts, and maxTotalRows turns that into a single hard stop.
  • Two cost tiers in a single actor β€” Listing only returns name, city, ZIP and profile URL for cheap seed lists; Full profile adds phone, hours, street address, sub-categories, logo and description.
  • Per-review rows on demand β€” Include Reviews adds rating, full body text, reviewer name and posted date as their own dataset rows, capped per pro so the total stays predictable.
  • Spreadsheet-ready values β€” city names arrive in one consistent spelling (Angi's own austin and MESA come out as Austin and Mesa), states as 2-letter codes, phones as 10-digit strings, so a pivot table groups each city into one bucket.
  • City or 5-digit ZIP, 50 states β€” paste 78701 or Austin, TX; both resolve to the same Angi coverage.

Use Cases

Lead Generation

  • Build prospect lists of plumbers, electricians, roofers, or any trade in any city.
  • Target newly-listed pros or those with low review counts for outreach.
  • Pull phone and address data into a CRM for cold call campaigns.

Market Research & Competitive Intelligence

  • Map the density of HVAC contractors across a metro area.
  • Compare average ratings by trade between cities or ZIP codes.
  • Track how many years pros in a category have been in business.

Directory & Aggregator Sites

  • Populate a local-services directory with up-to-date pro listings.
  • Enrich existing business records with Angi ratings and review counts.
  • Build geographic coverage data for franchise expansion analysis.

Reputation & Review Analysis

  • Pull per-pro reviews to analyze sentiment, common complaints, or pricing signals.
  • Benchmark a single pro against the rest of their category in their city.
  • Monitor competitor reviews on a recurring schedule via the Apify scheduler.

Real Estate & Property Management

  • Build vendor lists for property managers in new markets.
  • Identify highly-rated pros across multiple service categories in a single ZIP.

Getting Started

Simplest β€” One trade, one city

{
"searchTerms": ["plumber"],
"location": "Austin, TX"
}

Multi-trade in a major city by ZIP

{
"searchTerms": ["plumber", "electrician", "hvac"],
"location": "78701",
"maxResults": 50
}

Cheap bulk discovery (listing-only)

{
"category": "Roofing",
"location": "Phoenix, AZ",
"detailLevel": "listing",
"maxResults": 50
}

With per-pro reviews

{
"searchTerms": ["roofing"],
"location": "Phoenix, AZ",
"includeReviews": true,
"maxReviewsPerPro": 50
}

Direct URL β€” pinpoint a specific listing or category

{
"startUrls": [
"https://www.angi.com/companylist/us/tx/austin/plumbing.htm"
],
"maxResults": 100
}

Single pro profile (with reviews)

{
"startUrls": [
"https://www.angi.com/companylist/us/tx/austin/we-plumb-reviews-10565886.htm"
],
"includeReviews": true
}

Input Reference

ParameterTypeDefaultDescription
searchTermsstring[]["plumber"]Keywords or service names (e.g. "plumber", "roof repair", "HVAC contractor"). Each term runs as its own search and is combined with the location. Mapped to Angi's nearest matching trade category.
locationstring"Austin, TX"City and state (e.g. "Austin, TX") or 5-digit US ZIP code (e.g. "78701"). Combined with each search term and category.
categorystringnullOptional trade to browse instead of (or alongside) free-text search terms. Pick from a dropdown of 30 common trades.

Service categories available in the dropdown

Plumbing, Electrical, Heating & Cooling (HVAC), Roofing, Painting, Landscaping, Lawn Care, Tree Service, Handyman, House Cleaning, Pest Control, Remodeling, Kitchen Remodeling, Bathroom Remodeling, Flooring, Carpet Cleaning, Appliance Repair, Garage Doors, Fencing, Decks & Patios, Pools & Spas, Movers, Junk Removal, Windows, Siding, Gutters, Concrete, Masonry, Drywall, General Contractors.

For trades outside this list, type the keyword into Search Terms β€” it will be auto-mapped to the closest of Angi's 887 internal categories.

Direct URLs

ParameterTypeDefaultDescription
startUrlsstring[][]Paste any Angi URLs directly: pro profile pages, category hubs, city/state hubs, or listing pages. Scraped in addition to the keyword and category search above.

Limits

ParameterTypeDefaultDescription
maxResultsinteger100Total number of pros to return for the whole run, across every search term, category, start URL and city. A hard limit: you are never charged for more than this. Several searches share the total evenly, and unused allowance rolls on to the next search. Set to 0 for unlimited. Reviews are extra, so with reviews on your worst case is maxResults x (1 + maxReviewsPerPro) rows.
maxTotalRowsinteger0Optional single hard stop on the total rows saved, pros and reviews together. 0 means no total cap. Set a number when you want one figure you can count on no matter how the pros and reviews divide up. The run says in its final message when this limit is what stopped it.

Output Detail

ParameterTypeDefaultDescription
detailLevelstring"full""Listing only (faster, cheaper)" returns just what's on the search result card. "Full profile (recommended)" also visits each pro's profile page for hours, photo gallery, full address, description, and the most complete contact info.
keepPartialProfilesbooleanfalseOnce in a while Angi refuses to open a pro's profile page, so that record arrives with no phone, rating or hours. By default those records are dropped and never charged. Turn this on to keep them anyway β€” they come through with detailFetchFailed: true. Only applies under Full profile.
includeReviewsbooleanfalseWhen on, fetches each pro's reviews and emits them as separate rows in the dataset (one row per review). Adds to your billed result count β€” a pro with 50 reviews counts as 51 results.
maxReviewsPerProinteger20Cap on how many reviews to collect per pro. It multiplies: 100 pros at 25 reviews each is 2,500 review rows on top of the 100 pro rows. Set to 0 to fetch every review available, and pair that with maxTotalRows if you want a guaranteed ceiling. Ignored when Include Reviews is off.

Output

Two record types are emitted to the same dataset, distinguished by the recordType field. Pros always come first; reviews (when enabled) follow each pro.

Pro record (recordType: "pro")

{
"recordType": "pro",
"proId": "10565886",
"name": "We Plumb",
"url": "https://www.angi.com/companylist/us/tx/austin/we-plumb-reviews-10565886.htm",
"category": "Plumbing",
"subCategories": ["Plumbing", "Drain Cleaning", "Water Heaters"],
"rating": 4.91,
"reviewCount": 138,
"phone": "5126581400",
"email": null,
"website": "https://weplumb.com",
"address": "641 Arrowood Place",
"city": "Austin",
"state": "TX",
"zip": "78745",
"hours": {
"Monday": "7:00 AM - 6:00 PM",
"Tuesday": "7:00 AM - 6:00 PM",
"Wednesday": "7:00 AM - 6:00 PM",
"Thursday": "7:00 AM - 6:00 PM",
"Friday": "7:00 AM - 6:00 PM",
"Saturday": "Closed",
"Sunday": "Closed"
},
"acceptsAppointments": null,
"yearsInBusiness": 12,
"description": "Family-owned plumbing company serving Austin and surrounding communities since 2014. Drain cleaning, water heater install, repipe, slab leak repair.",
"logoUrl": "https://media.angi.com/s3fs-public/...",
"images": [],
"detailFetchFailed": false,
"searchTerm": "plumber",
"searchLocation": "Austin, TX",
"resolvedLocation": "Austin, TX",
"scrapedAt": "2026-04-26T23:57:06.698355+00:00"
}

Core fields

FieldTypeDescription
recordTypestringAlways "pro".
proIdstringAngi's own pro ID, unique to one business. Under Listing only Angi doesn't publish it, so the short number from the profile link is used instead and can repeat across unrelated businesses β€” url is always a guaranteed-unique key.
namestringBusiness name.
urlstringCanonical Angi profile URL.
categorystringPrimary service category (e.g. "Plumbing").
subCategoriesstring[]Other services the pro offers (full profile only). Empty list under Listing only.
ratingnumber | nullOverall star rating, rounded to 2 decimals (0–5). May be null under Listing only for cards Angi doesn't ship a rating on.
reviewCountinteger | nullTotal number of reviews on Angi. May be null under Listing only for cards without an aggregate rating.

Contact

FieldTypeDescription
phonestring | nullPublic phone number, 10-digit US format with no punctuation (e.g. "5126581400"). Full profile only, and present on essentially every one.
websitestring | nullThe pro's own website or social page, exactly as published on their Angi profile. Roughly 2 in 3 pros list one; the rest come through as null.
emailstring | nullAlways null. Angi routes all contact through its own lead system and never publishes pro email addresses.

Location

FieldTypeDescription
addressstring | nullStreet address, including the suite or unit line when the pro published one (full profile only). Angi occasionally stores a placeholder label rather than an address, or a coverage area such as "Las Vegas, NV"; those come through as null instead of as junk text.
citystring | nullCity, normalised to display casing so one city always groups into one bucket.
statestring | null2-letter state code, always upper-case.
zipstring | null5-digit ZIP code.

Business detail

FieldTypeDescription
hoursobject | nullPer-day opening hours, keyed Monday–Sunday (full profile only). Roughly 6 in 10 pros publish them; the rest come through as null.
yearsInBusinessinteger | nullSelf-reported tenure (full profile only).
descriptionstring | nullBusiness description written by the pro (full profile only).
logoUrlstring | nullLogo image URL.
acceptsAppointmentsboolean | nullReserved field. Angi does not publish this on pro profiles, so it is always null.
imagesstring[]Reserved field. The photo gallery is not published on pro profiles, so this is always empty; the logo arrives in logoUrl.

Run metadata

FieldTypeDescription
detailFetchFailedbooleantrue only when the pro's profile page could not be opened, so the record is listing-level only. These records are dropped, and not charged, unless you turn on Keep incomplete profiles.
searchTermstring | nullThe keyword that surfaced this pro (when from a keyword search).
searchLocationstring | nullThe place you asked for, echoed back (e.g. "Tampa, FL"), so you can join results straight back onto your own input list. A ZIP code comes back as the city it resolves to (33139 β†’ "Miami Beach, FL").
resolvedLocationstring | nullThe listing area Angi actually served. Usually identical to searchLocation; it differs when Angi files a city under its wider metro ("Tampa, FL" β†’ "Tampa Bay, FL") or splits it into boroughs ("New York, NY" β†’ "Manhattan, NY").
scrapedAtstringISO 8601 timestamp.

Review record (recordType: "review")

Emitted only when includeReviews is on. One row per review.

{
"recordType": "review",
"proId": "10565886",
"proName": "We Plumb",
"proUrl": "https://www.angi.com/companylist/us/tx/austin/we-plumb-reviews-10565886.htm",
"reviewId": "10565886-3",
"rating": 5.0,
"title": null,
"text": "Showed up on time, fixed the leak in 30 minutes, and explained exactly what they did. Highly recommend.",
"author": "Sarah M.",
"authorLocation": null,
"serviceDate": null,
"postedAt": "2026-03-14T00:00:00",
"serviceCategory": null,
"cost": null,
"scrapedAt": "2026-04-26T23:57:08.112441+00:00"
}
FieldTypeDescription
recordTypestringAlways "review".
proIdstringAngi's own pro ID. Pair it with proUrl to link the review back to exactly one pro record.
proNamestringConvenience copy of the pro's business name.
proUrlstringConvenience copy of the pro's profile URL.
reviewIdstringStable per-scrape review ID, unique across the whole run ({proId}-{globalIndex}).
ratingnumber | nullReview star rating (0–5).
titlestring | nullReview headline (currently null β€” not exposed by Angi's structured data).
textstring | nullFull review body.
authorstring | nullReviewer display name.
authorLocationstring | nullReviewer city (currently null β€” not in structured data).
serviceDatestring | nullDate the work was performed (currently null).
postedAtstring | nullISO 8601 timestamp of when the review was posted.
serviceCategorystring | nullCategory the review is about (currently null).
coststring | nullReported job cost (currently null).
scrapedAtstringISO 8601 timestamp.

Tips for Best Results

  • Use a 5-digit ZIP for precision β€” "78701" is more targeted than "Austin, TX" and avoids ambiguity for cities that share a name across states.
  • Major metros are auto-expanded β€” searching "New York, NY" fans out across Manhattan, Brooklyn, Queens, the Bronx and Staten Island, then de-duplicates pros so you don't pay twice for cross-borough listings.
  • Pick Listing only for cheap bulk discovery β€” it returns name, city, ZIP and profile URL from each card without opening any profile pages. Great for seed lists you'll enrich later. Switch to Full profile when you need phone, hours, sub-categories and the description.
  • Expect fewer unique pros than you asked for in smaller markets β€” Angi repeats the same featured pros across listing pages, and the scraper de-duplicates them before saving. A maxResults: 100 run on a typical city yields 30–60 unique pros; large metros give 50–150 per trade, small markets often 5–20. Raise maxResults or add a second nearby city when you need volume.
  • Reviews are billed per row β€” turning on Include Reviews adds one billable result per review. A search returning 60 pros, each with 25 reviews kept, costs about 1,560 results (60 x (1 + 25)). Use maxReviewsPerPro to cap the per-pro count, or maxTotalRows to cap the whole run in one number.
  • Use Direct URLs for surgical scrapes β€” paste a single profile URL to grab one pro and its reviews; paste a city or category URL (e.g. https://www.angi.com/companylist/us/tx/austin/plumbing.htm) to walk a known listing without going through the keyword mapper.
  • You only pay for complete records β€” if Angi won't open a pro's profile page, that pro gets a second pass, and if it still won't load the record is dropped rather than saved half-empty. Flip on Keep incomplete profiles if a name plus city is still useful to you.
  • Search terms map to a category, so pick the dropdown when it matters β€” Angi search is category-based, not free-text. "exterminator" maps to Pest Control, "AC" maps to Heating & Cooling (HVAC). For full control over which category is used, choose from the dropdown or use Direct URLs.
  • A few fields are simply not published by Angi β€” email, acceptsAppointments and the photo gallery are never exposed on pro profiles, and review rows carry no headline, reviewer city, service date, service category or job cost. They stay in the schema as null so your column mapping never shifts, and the dataset table hides them by default.

Pricing

From $0.80 per 1,000 results β€” one flat rate whether you pull listing cards or full profiles. No compute or time-based charges: you pay per result, plus a small fixed start fee each time a run begins. Bronze, Silver and Gold subscribers pay progressively less, and the table below shows the total cost at each discount tier.

ResultsNo discountBronzeSilverGold
100$0.096$0.091$0.085$0.080
1,000$0.96$0.91$0.85$0.80
10,000$9.60$9.10$8.50$8.00
100,000$96.00$91.00$85.00$80.00

A "result" is one row in your dataset. Each pro counts as one result; when Include Reviews is on, each review is also one result, so a pro with 50 reviews counts as 51. Standard Apify platform fees apply on top.

Integrations

Export your data in JSON, CSV, Excel, XML, or RSS. Connect to 1,500+ apps via:

  • Zapier / Make / n8n β€” Workflow automation.
  • Google Sheets β€” Direct spreadsheet export.
  • Slack / Email β€” Notifications on new results.
  • Webhooks β€” Custom API integrations.
  • Apify API β€” Full programmatic access.

This scraper is designed for legitimate business intelligence, market research, lead generation, and directory enrichment. You are responsible for complying with applicable laws, Angi's Terms of Service, and any data-protection regulations in your jurisdiction (CCPA, GDPR, etc.). Do not use the data for spam, harassment, or any unlawful purpose. Respect opt-outs and do-not-contact requests.