How to scrape Yelp at scale in 2026 with proxies that work
Yelp sits on one of the richest local business datasets on the internet: ratings, review text, categories, hours, price ranges, photo counts, response rates. If you’re doing local SEO competitor tracking, lead gen for a local services agency, or building a reputation-monitoring tool, Yelp is usually the first source you reach for and the first one that blocks you.
Yelp runs active bot detection on its search and business pages, rate-limits its official Fusion API hard enough that it’s not usable for bulk collection, and has a legal history (the hiQ Labs v. LinkedIn litigation, which Yelp itself has cited in its own anti-scraping arguments) that makes operators nervous about doing this at all. This guide is for people who already understand the legal grey zone they’re operating in and want a scraping setup that survives more than a few hundred requests before getting IP banned or served CAPTCHAs on every page.
By the end you’ll have a working Playwright-based scraper behind a rotating proxy pool, a sense of where the Fusion API is still the better tool, and a realistic picture of what changes when you go from scraping 500 listings a day to 50,000.
what you need
- A residential or mobile proxy plan. Datacenter IPs get flagged on Yelp within minutes at any real volume. I’ve had decent mileage with Decodo (formerly Smartproxy) and Oxylabs residential pools, both billed by bandwidth. Budget $8-15/GB for residential.
- A headless browser automation library. Playwright is the current standard, it renders JS-heavy pages the way Puppeteer used to, and has better built-in stealth ergonomics.
- A Yelp Fusion API key (free, register at the Yelp developer portal) for anything you can get through the official API rather than scraping. Always check the API first, it’s less work and zero ban risk for what it covers.
- A fingerprint/antidetect layer if you’re running more than a handful of concurrent sessions. I cover the tooling landscape for this in more depth on antidetectreview.org if you need a dedicated browser fingerprinting stack.
- Storage: Postgres or even SQLite for anything under a few hundred thousand rows. CSV is fine for a one-off pull.
- A CAPTCHA-solving fallback (2Captcha or CapSolver) for when Yelp serves you one, budget roughly $1-3 per 1,000 solves.
- Time budget: a working single-threaded scraper takes an afternoon. A resilient, multi-proxy, monitored pipeline takes a few days.
step by step
1. Check whether the Fusion API covers your need first
Before writing a scraper, register for a Yelp Fusion API key and test the /businesses/search and /businesses/{id}/reviews endpoints. The API gives you clean structured business data (name, category, rating, coordinates, hours) without any scraping risk. Its main limitation is the review endpoint, which historically returns only a handful of review excerpts per business rather than the full review corpus you can see on the website.
Expected output: JSON responses with rate-limit headers telling you your current tier.
If it breaks: a 401 usually means your key wasn’t activated yet, this can take a few minutes after registration. A 429 means you’re over your daily quota, check the limits documented on your developer dashboard rather than assuming last year’s numbers still apply.
2. Decide what actually needs scraping
Map your data requirements against what the API returns. In practice, most operators end up scraping only the full review text and photo/response metadata, and pull everything else (name, address, category, star rating) from the API. This cuts your scrape volume dramatically and reduces ban exposure.
Expected output: a short spec, e.g. “API gets business metadata for 10,000 businesses, scraper gets full reviews for the top 500 by review count.”
If it breaks: if you find yourself scraping fields the API already gives you, stop, you’re taking on risk for no reason.
3. Set up your proxy pool
Configure a rotating residential proxy endpoint. Most providers give you a single gateway host/port and rotate the exit IP automatically per request or per session.
proxy_config = {
"server": "https://gate.decodo.com:10001",
"username": "your_username",
"password": "your_password",
}
Expected output: a proxy that returns a different IP on each curl -x test call to https://ipinfo.io/json.
If it breaks: if you get the same IP repeatedly, check whether your plan is “sticky session” by default, most providers let you force rotation by appending a session ID string to the username.
4. Build the scraper with Playwright
from playwright.sync_api import sync_playwright
def scrape_business(url, proxy_config):
with sync_playwright() as p:
browser = p.chromium.launch(proxy=proxy_config, headless=True)
context = browser.new_context(
user_agent="Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36",
viewport={"width": 1366, "height": 768},
)
page = context.new_page()
page.goto(url, wait_until="networkidle", timeout=30000)
reviews = page.query_selector_all("[data-testid='review']")
data = [r.inner_text() for r in reviews]
browser.close()
return data
Expected output: a list of raw review text blocks per business page.
If it breaks: if query_selector_all returns an empty list, Yelp’s DOM structure or data-testid attributes have changed, they update these periodically specifically to break scrapers. Re-inspect the page in devtools and update your selectors.
5. Handle pagination and rate limiting
Yelp paginates reviews at 10-20 per page. Add a delay of 3-8 seconds (randomized, not fixed) between page loads, and cap concurrent sessions per proxy at 1-2.
Expected output: consistent successful page loads across a full pagination run without a CAPTCHA appearing.
If it breaks: if CAPTCHAs start appearing after page 3-4 consistently, your delay is too tight or too regular. Add jitter and randomize your viewport/user-agent per session rather than reusing one context for the whole run.
6. Detect and handle blocks gracefully
Check response status and page content for block indicators (a CAPTCHA challenge page, a 403, or a suspiciously empty result set) before parsing.
if "Please verify you are a human" in page.content():
proxy_pool.rotate()
retry_queue.append(url)
Expected output: failed URLs get requeued with a fresh IP instead of silently producing empty data.
If it breaks: if your retry queue keeps growing and never clears, your proxy pool is too small or too hot already, meaning Yelp has flagged the whole subnet range, not just individual IPs. Switch providers or pool tiers.
7. Store and deduplicate
Write to Postgres with a unique constraint on (business_id, review_id) so reruns don’t duplicate rows.
Expected output: idempotent runs, rerunning the scraper on the same business list doesn’t inflate your row count.
If it breaks: if you see duplicates, check whether Yelp’s review IDs are stable across page loads (they usually aren’t exposed directly, so hash the review author + timestamp + first 100 characters as a fallback key).
8. Schedule and monitor
Run on a cron schedule (daily or weekly depending on how fast the target businesses’ reviews change) and log your success rate per run.
Expected output: a success-rate metric you can track over time, e.g. 95% of target URLs returned valid data.
If it breaks: a sudden drop below 70-80% success rate usually means Yelp shipped a detection update. Check for DOM changes first, then check whether your proxy pool’s IP reputation has degraded.
common pitfalls
- Treating the free Fusion API and scraping as interchangeable. They’re not. Mixing structured API data with unstructured scraped text without a clean join key (business ID) creates data quality problems fast.
- Running scrapes from datacenter IPs to “test first.” Yelp’s detection doesn’t meaningfully differentiate a test run from a production one, you’ll burn your test IPs and think your scraper is broken when it’s actually just blocked.
- Ignoring the Yelp Terms of Service. Yelp explicitly prohibits automated scraping in its terms. This isn’t legal advice, but you should read the terms yourself and understand that scraping in violation of a site’s ToS has been the subject of real litigation, including the long-running hiQ Labs v. LinkedIn case that shaped how courts think about the Computer Fraud and Abuse Act in this context (see the DOJ’s own CFAA guidance for the statute operators most often get cited under). Know your exposure before you scale this commercially.
- Not rotating fingerprints alongside IPs. A residential proxy with a stale, reused browser fingerprint still gets flagged. IP and fingerprint rotation need to move together.
- Scraping review text you then republish verbatim. Aggregating ratings and metadata for internal analysis is one thing, republishing full review text elsewhere raises separate copyright questions on top of the ToS issue.
scaling this
At 10x (a few hundred businesses a day): a single machine, one proxy provider, sequential Playwright runs. Your bottleneck is patience, not infrastructure.
At 100x (a few thousand a day): you need a proper job queue (Redis or SQS), parallel workers each bound to a different proxy session, and active success-rate monitoring so you catch detection changes within hours, not days. This is also the point where CAPTCHA-solving costs start showing up as a real line item.
At 1000x (tens of thousands a day): you’re running a distributed worker fleet, likely across multiple proxy providers to avoid concentrating risk in one subnet range, with fingerprint rotation managed by dedicated antidetect browser profiles rather than raw Playwright contexts. At this scale, most operators I know also run parallel account/session isolation if they’re touching any logged-in Yelp surfaces, which is where a tool like the ones covered on multiaccountops.com becomes relevant. Your cost per record drops, but your legal and reputational exposure scales with volume too, so this is also the point to have an actual conversation with a lawyer if this is a commercial operation.
where to go next
If Yelp is one piece of a broader local-data pull, read best proxies for scraping local search results in 2026 for how the proxy choice changes across Google Maps, Yelp, and other local platforms. For the proxy provider I used in the code above, see my Decodo review for current pricing and pool performance. And if you’re building out a broader scraping stack beyond Yelp, browse the rest of the tutorials on the blog for platform-specific guides.
Written by Xavier Fok
disclosure: this article may contain affiliate links. if you buy through them we may earn a commission at no extra cost to you. verdicts are independent of payouts. last reviewed by Xavier Fok on 2026-07-17.