Yelp Scraper: Business Search & Category Coverage — $4/1k avatar

Yelp Scraper: Business Search & Category Coverage — $4/1k

Pricing

from $4.00 / 1,000 result rows

Go to Apify Store
Yelp Scraper: Business Search & Category Coverage — $4/1k

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

Khrystyna Skotte

Maintained by Community

Actor stats

0

Bookmarked

2

Total users

1

Monthly active users

2 days ago

Last modified

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.

ModeOne row isUse it for
coverageone city x service pairSupply checks, market-gap research, territory planning
listingsone businessLead 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

FieldExampleMeaning
recordTypecoverageRow type
marketplaceyelpSource
city, serviceSan Diego, CA, dog groomingThe pair you searched
categoryExiststruetrue when Yelp returns results, false when it says "No results" (a visible gap)
proCount240Number of businesses Yelp reports for the search
proCountCappedtruetrue when proCount hit Yelp's 240 ceiling, so the real number is higher
resultCount10Organic businesses on the first page
adCount10Sponsored 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, pageUrlTop 10 Best dog grooming Near San Diego...The Yelp page counted
matchedSlugnullAlways null on Yelp; kept so the row shape matches the sibling Thumbtack, Angi and Bark coverage actors
scrapedAtISO timestampWhen it was read
errortextOnly 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

  1. Find category gaps per city. Run coverage for 50 cities x 20 services. Rows with categoryExists: false, or a low proCount that 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.
  2. Local lead lists. Run listings with includeDetails for a trade in a metro. You get name, phone, website, address, claimed status and years in business per row, ready for a CRM import.
  3. Franchise and territory planning. Compare proCount, ratings and review counts across zip codes (Yelp accepts a zip in cities).
  4. Competitor mapping. Pull every business in your category within a city, sorted by Yelp's own ranking (position), with price level and review volume.
  5. Unclaimed-business outreach. Filter detail rows by isClaimed: false or isYelpAdvertiser: false to find businesses that are not managing their Yelp page.
  6. Closure and health checks. isClosed and healthScore on detail rows help clean directories and screen restaurant lists.
  7. Scheduled market tracking. Run coverage weekly on a schedule and compare proCount over time (while it is below 240).

Input

InputTypeDefaultWhat it does
modecoverage / listingsautomaticcoverage = one row per city x service. listings = one row per business. Empty: coverage for {}, listings when you give inputs
citiesstring listnoneLocations such as San Diego, CA, Austin, TX, 10001. Every service is searched in every city
servicesstring listnoneSearch terms such as dog grooming, plumbers, pizza
listUrltextemptyCSV or Google Sheet shared as "anyone with the link". Each row is city,service or a Yelp URL. A header row is skipped
searchUrlsstring listnoneYelp search URLs with your own filters, kept as given
bizUrlsstring listnoneYelp business URLs (https://www.yelp.com/biz/...), one full-detail row each
maxItemsinteger10Businesses per search in listings mode, 1 to 240
includeDetailsbooleanfalselistings: also open each business page (adds phone, website, hours and more). Extra charge per business, see pricing
includeAdsbooleanfalselistings: also return sponsored rows, flagged isAd: true
concurrencyinteger4Searches run in parallel, 1 to 10
proxyConfigurationproxyemptyLeave 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.

EventPriceWhen
Actor start$0.001once 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 error and are not charged. If a business page fails to open, the business row is still delivered (with detailsError) 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: true marks 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 in cities) and add the results.
  • Review texts are not included. The row has rating, reviewCount and 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 proCount or resultCount. adCount tells you how many appeared on page one. With includeAds: true they are returned in listings and flagged isAd: true.
  • Photos: you get the lead photo URL and the photo count, not the photo gallery with captions.
  • Hours: hours holds 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 null or empty.
  • If Yelp changes its page structure, the search parser fails loudly and the affected pair is marked error in the run's OUTPUT record 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_TOKEN and the input JSON as the body. Fetch rows from /v2/datasets/DATASET_ID/items?format=csv (or json, xlsx).
  • Python:
from apify_client import ApifyClient
client = 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.

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.