Yelp Scraper: Business Search & Category Coverage — $4/1k
Pricing
from $4.00 / 1,000 result rows
Yelp Scraper: Business Search & Category Coverage — $4/1k
Yelp Scraper for business search by city and service: ratings, phone, website, hours, claimed status, plus a coverage mode counting businesses per city and service to find market gaps. Yelp caps counts at 240. No login or cookies. MCP-ready for AI agents. $4 per 1,000 records.
Pricing
from $4.00 / 1,000 result rows
Rating
0.0
(0)
Developer
Khrystyna Skotte
Maintained by CommunityActor stats
0
Bookmarked
2
Total users
1
Monthly active users
2 days ago
Last modified
Categories
Share
Yelp Scraper: Business Search, Details & Category Coverage
Search Yelp by city and service and get structured business data back: name, rating, review count, price level, categories, neighborhood, phone, website, address, coordinates, opening hours, claimed status and more. A second mode, coverage, returns one cheap row per city x service with the number of businesses Yelp lists and the top three names, so you can see in minutes where a market is crowded and where it is thin.
No Yelp account, no cookies, no API key. You pay per row, and the cost of getting past Yelp's bot wall is included in that price (see "Proxy and cost" below).
What you get
The actor has two modes.
| Mode | One row is | Use it for |
|---|---|---|
coverage | one city x service pair | Supply checks, market-gap research, territory planning |
listings | one business | Lead lists, directory data, competitor mapping |
The mode is chosen for you: an empty input ({}) runs a small coverage sample, and any input you give runs listings unless you set mode yourself.
Coverage row fields
| Field | Example | Meaning |
|---|---|---|
recordType | coverage | Row type |
marketplace | yelp | Source |
city, service | San Diego, CA, dog grooming | The pair you searched |
categoryExists | true | true when Yelp returns results, false when it says "No results" (a visible gap) |
proCount | 240 | Number of businesses Yelp reports for the search |
proCountCapped | true | true when proCount hit Yelp's 240 ceiling, so the real number is higher |
resultCount | 10 | Organic businesses on the first page |
adCount | 10 | Sponsored results on the first page (not counted in proCount) |
topPros | ["Pet Beloved", ...] | Names of the first three organic businesses |
topProsDetail | [{name, rating, reviewCount, bizUrl}] | The same three with rating, reviews and URL |
pageTitle, pageUrl | Top 10 Best dog grooming Near San Diego... | The Yelp page counted |
matchedSlug | null | Always null on Yelp; kept so the row shape matches the sibling Thumbtack, Angi and Bark coverage actors |
scrapedAt | ISO timestamp | When it was read |
error | text | Only on failure. Error rows are not charged |
Business row fields
Every business row has these from the search page:
recordType, marketplace, searchCity, searchService, position (organic rank), isAd, bizId, alias, name, rating, reviewCount, priceRange ($ to $$$$), categories[], phone (see note), address, city, neighborhoods[], serviceArea, yearsInBusiness, highlights[], verifiedLicenses, yelpGuaranteed, snippet (the review excerpt shown on the card), photoUrl, bizUrl, totalResults, pageUrl, scrapedAt.
With business details (includeDetails: true, or any URL in bizUrls) each row also gets:
website, menuUrl, street, state, postalCode, country, latitude, longitude, hours[] (per day), isClaimed, isClosed, isYelpAdvertiser, yearEstablished, history, specialties, summary, photoCount, amenities[], healthScore, healthInspectedAt, and detailsError if that one page failed.
Detail values that are empty never overwrite what the search card already had.
Phone numbers: Yelp does not put the phone number in organic search cards. Organic rows get a phone only when you turn on includeDetails (or pass bizUrls). Sponsored rows carry their phone on the card.
Real output
Coverage (cloud run, {} input, San Diego)
{"recordType": "coverage","marketplace": "yelp","city": "San Diego, CA","service": "dog grooming","categoryExists": true,"proCount": 240,"proCountCapped": true,"resultCount": 10,"adCount": 10,"topPros": ["Pet Beloved", "Pawadise Grooming", "Wags & Ruffs"],"topProsDetail": [{"name": "Pet Beloved", "rating": 4.9, "reviewCount": 243, "bizUrl": "https://www.yelp.com/biz/pet-beloved-san-diego-2"},{"name": "Pawadise Grooming", "rating": 4.9, "reviewCount": 49, "bizUrl": "https://www.yelp.com/biz/pawadise-grooming-san-diego"},{"name": "Wags & Ruffs", "rating": 4.8, "reviewCount": 164, "bizUrl": "https://www.yelp.com/biz/wags-and-ruffs-san-diego"}],"matchedSlug": null,"pageTitle": "Top 10 Best dog grooming Near San Diego, California (Updated 2026)","pageUrl": "https://www.yelp.com/search?find_desc=dog+grooming&find_loc=San+Diego%2C+CA","scrapedAt": "2026-10-22T02:10:18.402Z"}
Business with details (cloud run, Austin plumbers, includeDetails: true)
{"recordType": "business","marketplace": "yelp","searchCity": "Austin, TX","searchService": "plumbers","position": 1,"isAd": false,"bizId": "TVHztfQAJUIaJDgdJuke-g","alias": "blue-dragon-plumbing-austin-2","name": "Blue Dragon Plumbing","rating": 4.9,"reviewCount": 532,"priceRange": null,"categories": ["Plumbing"],"phone": "(512) 947-2491","address": "Austin, TX 78727","city": "Austin","neighborhoods": ["Milwood"],"verifiedLicenses": 0,"yelpGuaranteed": false,"snippet": "They are fast, reliable and trustworthy. If you're looking for a plumbing service, look no further.","bizUrl": "https://www.yelp.com/biz/blue-dragon-plumbing-austin-2","website": "http://bluedragonplumbing.com","state": "TX","postalCode": "78727","country": "US","hours": [{"day": "Mon", "hours": ["8:00 AM - 5:00 PM"]},{"day": "Sat", "hours": ["9:00 AM - 5:00 PM"]},{"day": "Sun", "hours": ["9:00 AM - 6:00 PM"]}],"isClaimed": true,"isClosed": false,"yearEstablished": "2011","photoCount": 33,"totalResults": 240,"scrapedAt": "2026-10-22T02:11:05.464Z"}
(Hours shortened to three days here; the real row has all seven. history and specialties free text are also returned.)
Business page by URL (cloud run)
A business URL returns the full record, for example Extraordinary Desserts in San Diego: phone (619) 294-2132, website, menuUrl, latitude 32.73536, longitude -117.161405, isClaimed true, photoCount 8197, healthScore "99 out of 100" with healthInspectedAt.
Use cases
- Find category gaps per city. Run
coveragefor 50 cities x 20 services. Rows withcategoryExists: false, or a lowproCountthat is not capped, are underserved markets. Join with the same pairs from the Thumbtack, Angi or Bark coverage actors to see where Yelp has supply and the marketplaces have none. - Local lead lists. Run
listingswithincludeDetailsfor a trade in a metro. You get name, phone, website, address, claimed status and years in business per row, ready for a CRM import. - Franchise and territory planning. Compare
proCount, ratings and review counts across zip codes (Yelp accepts a zip incities). - Competitor mapping. Pull every business in your category within a city, sorted by Yelp's own ranking (
position), with price level and review volume. - Unclaimed-business outreach. Filter detail rows by
isClaimed: falseorisYelpAdvertiser: falseto find businesses that are not managing their Yelp page. - Closure and health checks.
isClosedandhealthScoreon detail rows help clean directories and screen restaurant lists. - Scheduled market tracking. Run
coverageweekly on a schedule and compareproCountover time (while it is below 240).
Input
| Input | Type | Default | What it does |
|---|---|---|---|
mode | coverage / listings | automatic | coverage = one row per city x service. listings = one row per business. Empty: coverage for {}, listings when you give inputs |
cities | string list | none | Locations such as San Diego, CA, Austin, TX, 10001. Every service is searched in every city |
services | string list | none | Search terms such as dog grooming, plumbers, pizza |
listUrl | text | empty | CSV or Google Sheet shared as "anyone with the link". Each row is city,service or a Yelp URL. A header row is skipped |
searchUrls | string list | none | Yelp search URLs with your own filters, kept as given |
bizUrls | string list | none | Yelp business URLs (https://www.yelp.com/biz/...), one full-detail row each |
maxItems | integer | 10 | Businesses per search in listings mode, 1 to 240 |
includeDetails | boolean | false | listings: also open each business page (adds phone, website, hours and more). Extra charge per business, see pricing |
includeAds | boolean | false | listings: also return sponsored rows, flagged isAd: true |
concurrency | integer | 4 | Searches run in parallel, 1 to 10 |
proxyConfiguration | proxy | empty | Leave empty. The actor uses Apify's Unblocker proxy automatically |
Older input names still work: searchTerms, searchTerm, query (services), locations, location (cities), searchLimit (maxItems), directUrls and startUrls (search and business URLs are told apart automatically).
Example: coverage for a list of cities and services
{"mode": "coverage","cities": ["San Diego, CA", "Austin, TX", "Ely, NV"],"services": ["dog grooming", "house cleaning", "chimney sweep"]}
Nine pairs, nine rows.
Example: plumbers in Austin with phone and website
{"mode": "listings","cities": ["Austin, TX"],"services": ["plumbers"],"maxItems": 50,"includeDetails": true}
Example: one business, by URL
{ "bizUrls": ["https://www.yelp.com/biz/extraordinary-desserts-san-diego"] }
Example: your own Yelp filters
{ "searchUrls": ["https://www.yelp.com/search?find_desc=Plumbers&find_loc=Austin%2C+TX"], "maxItems": 30 }
Example: bulk list from a Google Sheet
Share the sheet as "anyone with the link", put city,service in two columns, and pass:
{ "mode": "coverage", "listUrl": "https://docs.google.com/spreadsheets/d/YOUR_SHEET_ID/edit" }
Pricing
Pay per event. You are charged only for rows that are delivered.
| Event | Price | When |
|---|---|---|
| Actor start | $0.001 | once per run |
| Row | $0.004 ($4 per 1,000) | each coverage row and each business row |
| Business details | $0.003 ($3 per 1,000) | each business whose page is opened (includeDetails, or each bizUrls entry) |
What that means in practice:
- 1,000 coverage rows (for example 50 cities x 20 services): about $4.00 plus the $0.001 start.
- 1,000 businesses, search data only: about $4.00. Remember each search returns at most 240, so 1,000 businesses means at least five searches.
- 1,000 businesses with phone, website and hours: about $7.00 ($4 rows + $3 details).
- Coverage rows that fail are marked with
errorand are not charged. If a business page fails to open, the business row is still delivered (withdetailsError) and only the details charge is skipped.
Platform compute is small: the actor needs only 512 MB because it does plain HTTP, no browser.
Proxy and cost
Yelp runs a bot wall (DataDome). In testing, plain requests, datacenter proxies, residential proxies and a real headed browser were all blocked from the cloud. The only route that worked was Apify's Unblocker proxy, which the actor uses by default. Its charges are billed to the actor owner and are already part of the per-row price above, so you do not pay a separate proxy bill. Because the Unblocker is only available inside Apify runs, the actor cannot be run on your own machine; run it on Apify and call it through the API or a schedule.
Each search or business page takes roughly 10 to 30 seconds through the unblocker, so a large listings run with details takes minutes, not seconds. Raising concurrency speeds up multi-search jobs.
Limits you should know about
Stated plainly so there are no surprises:
- Yelp caps every search at 240 results. Popular searches such as "dog grooming" in San Diego return exactly 240, and
proCountCapped: truemarks it. A capped count means "at least 240", not the true total. Counts below 240 are real: in our tests Ely, NV returned 2 for dog grooming and 0 for chimney sweep. To go past 240, split the area (zip codes or neighborhoods incities) and add the results. - Review texts are not included. The row has
rating,reviewCountand one review excerpt (snippet), not the reviews themselves. Use a dedicated Yelp reviews actor for that. - Sponsored results are excluded by default. They are not counted in
proCountorresultCount.adCounttells you how many appeared on page one. WithincludeAds: truethey are returned inlistingsand flaggedisAd: true. - Photos: you get the lead photo URL and the photo count, not the photo gallery with captions.
- Hours:
hoursholds this week's hours as Yelp shows them, with special hours merged in. Alternate business names are not output. - Coordinates and some fields exist only on detail rows, and service-area businesses with no map have no latitude or longitude.
- Fields Yelp does not show for a given business come back
nullor empty. - If Yelp changes its page structure, the search parser fails loudly and the affected pair is marked
errorin the run'sOUTPUTrecord rather than returning wrong data.
How it compares to the other Yelp actors
Measured from the Store pages and actor records on 2026-10-21:
- tri_angle/yelp-scraper (rated 2.7 on 10 ratings) takes search terms, locations and direct URLs. Its README also says "up to 240 results on average", the same Yelp cap. It prices per business in tiers from $0.005 on the free plan down to $0.0008 on the highest plan, plus a charge for photo pages. It has no coverage mode and no bulk list input. Our flat $0.004 row is below its free-plan price; its higher-tier prices are lower than ours, and its rows include photos with captions that ours do not.
- tri_angle/yelp-review-scraper and web_wanderer/yelp-reviews-scraper return review text only. They are a different product from this one and are the right tool if reviews are what you need. This actor is for the business records and market counts.
What this actor adds: a coverage mode with one row even for empty results, proCountCapped and adCount so you know how far to trust a count, a CSV or Google Sheet bulk list, sponsored rows separated from organic ones, and business details (phone, website, claimed status, coordinates, hours) in a single run.
FAQ
Why is my phone column empty? Organic search cards on Yelp do not include the phone. Turn on includeDetails.
Why does every big city show 240? That is Yelp's cap on results per search, flagged by proCountCapped. Use smaller areas to count further.
Does categoryExists: false mean nobody offers the service? It means Yelp returned "No results" for that search at that location. Always check the pageUrl; Yelp may match the term differently from how locals name the service, so try a synonym.
Can I search a zip code? Yes, put it in cities.
Is anything stored between runs? No. Every run reads Yelp fresh. To track change over time, schedule the actor and compare datasets.
What happens if some pages fail? Rows that succeeded are kept. Failed targets are listed in the run's OUTPUT record with a status, and failed coverage rows carry an error and are not charged.
Integrations
- API: start a run with
POST https://api.apify.com/v2/acts/chimerical_quicklime~yelp-business-search-scraper/runs?token=YOUR_TOKENand the input JSON as the body. Fetch rows from/v2/datasets/DATASET_ID/items?format=csv(orjson,xlsx). - Python:
from apify_client import ApifyClientclient = ApifyClient("YOUR_TOKEN")run = client.actor("chimerical_quicklime/yelp-business-search-scraper").call(run_input={"mode": "coverage","cities": ["San Diego, CA"],"services": ["dog grooming", "house cleaning"],})for row in client.dataset(run["defaultDatasetId"]).iterate_items():print(row["city"], row["service"], row["proCount"], row["proCountCapped"])
- JavaScript:
import { ApifyClient } from 'apify-client';const client = new ApifyClient({ token: 'YOUR_TOKEN' });const run = await client.actor('chimerical_quicklime/yelp-business-search-scraper').call({mode: 'listings', cities: ['Austin, TX'], services: ['plumbers'], maxItems: 20, includeDetails: true,});const { items } = await client.dataset(run.defaultDatasetId).listItems();
- Schedules and webhooks: run weekly from the Apify console and send a webhook to your own endpoint when a run finishes.
- Make, Zapier, n8n: use the Apify module or HTTP request with the run API above; push the dataset to Google Sheets, Airtable or a CRM.
- MCP / AI agents: the actor can be called as a tool through Apify's MCP server, so an agent can ask "how many dog groomers does Yelp list in Austin?" and get a coverage row back.
Legal
The actor reads publicly visible Yelp pages. You are responsible for using the data in line with Yelp's terms and the privacy and marketing laws that apply to you, especially when contacting businesses.