Auf 8,4 Millionen aktiven Unternehmensprofilen liegen bei Yelp inzwischen 330 Millionen Bewertungen — ein riesiger Datenschatz, an den heranzukommen aber so schwer ist wie nie zuvor. Mit seiner Anti-Bot-Aufrüstung der Jahre 2024 und 2025 hat Yelp ziemlich geräuschlos fast alle bekannten Python-Tutorials zum Scraping unbrauchbar gemacht.
Wer in den letzten Wochen einen Yelp Scraper laufen ließ und statt Daten nur 403-Fehler, leere HTML-Antworten oder CAPTCHAs kassiert hat, die es vor einem halben Jahr noch nicht gab — der täuscht sich nicht. Yelp arbeitet mittlerweile mit TLS-/JA3-Fingerprinting, ständig wechselnden, verschleierten CSS-Klassennamen und einer harten Bewertung der IP-Reputation. Konkret heißt das: Der klassische requests + BeautifulSoup-Ansatz, den nahezu jede Anleitung weiterhin propagiert, fliegt oft schon beim allerersten Request raus. Ich habe über Wochen die verschiedenen Methoden gegen Yelps aktuellen Stack geprüft, und dieser Leitfaden bündelt, was 2025 tatsächlich trägt: die offizielle Fusion API (und warum sie meist zu kurz greift), einen kompletten Python-Workflow samt mehrstufiger Anti-Block-Strategie und — für alle, die einfach nur die Daten brauchen und keine Debugging-Odyssee — eine 2-Klick-No-Code-Variante mit Thunderbit.
Thunderbit für Yelp-Scraping ausprobieren
Warum Yelp mit Python scrapen? Und wer profitiert wirklich davon?
Eine Frage gehört vor die erste Codezeile: Wofür genau brauchst du die Yelp-Daten? Yelp ist eben nicht bloß ein Bewertungsportal für Restaurants, sondern faktisch eine ständig aktualisierte Datenbank lokaler Unternehmen — mit strukturierten Kontaktdaten, Bewertungen, Kategorien, Öffnungszeiten und Hunderten Millionen Kundenstimmen.

Wer am meisten davon hat und was dabei typischerweise herausgezogen wird, zeigt diese Übersicht:
| Anwendungsfall | Wichtige Datenfelder | Warum das wichtig ist |
|---|---|---|
| Vertrieb & Lead-Generierung | Firmenname, Telefonnummer, Website, Adresse, Kategorie, Bewertung | Zielgerichtete Prospect-Listen für lokale KMU aufbauen — 4 von 5 Yelp-Nutzern sind bei Ankunft kaufbereit |
| Wettbewerbsanalyse | Bewertungen, Sternebewertungen, Anzahl der Rezensionen, Stimmungsbild | Reputation der Konkurrenz beobachten, Service-Lücken erkennen, Trends verfolgen |
| Marktforschung & NLP | Vollständiger Rezensionstext, Datum, Metadaten der Rezensenten | Sentiment-Analysen, Topic Modeling — Yelp-Bewertungen gehören zu den am häufigsten verwendeten NLP-Korpora in der Forschung |
| Immobilien & Standortwahl | Unternehmensdichte, Kategorienmix, Bewertungsqualität nach Gebiet | Standortwahl für Filialen und Handel — Yelp verkauft dafür mit Location Intelligence sogar ein lizenziertes B2B-Produkt |
| E-Commerce & Operations | Preissignale, Kundenbeschwerden, Servicezeiten | Beobachten, wie Wettbewerber bewertet werden, operative Muster erkennen |
Allen Fällen gemeinsam ist eines: Es geht um strukturierte Daten, und Python ist nur einer von mehreren Wegen dorthin. Manche brauchen volle programmatische Kontrolle, andere lediglich eine Tabelle mit den Kontaktdaten von Handwerkern in Austin. Beides deckt dieser Leitfaden ab.
Yelp Fusion API vs. Python Web Scraping: Was solltest du verwenden?
Die meisten Anleitungen springen direkt in den Code und überspringen genau die Frage, ob nicht die offizielle Yelp Fusion API — heute als „Yelp Places API“ vermarktet — schon gereicht hätte. Diese kurze Abwägung spart nach meiner Erfahrung Stunden, denn für manches taugt die API stark, für anderes überhaupt nicht.
Was die Fusion API tatsächlich liefert
Die Fusion API bietet strukturierte Unternehmenssuche, Unternehmensdetails, Autovervollständigung und einen Reviews-Endpunkt. Sie ist autorisiert, ordentlich dokumentiert und kommt ganz ohne Anti-Bot-Tricks aus.
Genau beim Reviews-Endpunkt aber zerbricht das Modell — und das hat Yelp selbst auf GitHub eingeräumt:
„Die Yelp API liefert keinen vollständigen Rezensionstext. Standardmäßig werden drei Rezension-Auszüge mit jeweils 160 Zeichen bereitgestellt." — Antwort von Yelp-Mitarbeitern, GitHub Issue #163
Das ist kein Bug, sondern Absicht. Die API gibt pro Unternehmen physisch nur 3 Auszüge heraus (7 im Premium-Tarif), jeder davon auf rund 160 Zeichen gekappt. Keine Review-Metadaten (also keine Votes wie useful/funny/cool), keine Rezensenten-Historie, keine Antworten des Betreibers. Dazu kommt: Das tägliche Rate Limit wurde für Neukunden nach Mai 2023 von 5.000 auf 300–500 Aufrufe gesenkt. Der Einstieg kostet $29/Monat (ca. 27 €/Monat).
Die Entscheidungsgrundlage
| Faktor | Yelp Fusion API | Python Web Scraping | Thunderbit (No-Code) |
|---|---|---|---|
| Vollständige Reviews | ❌ Nur 3 Auszüge (~160 Zeichen je Auszug) | ✅ Alle Reviews über GraphQL | ✅ Alle sichtbaren Reviews |
| Rate Limits | 300–500/Tag (neu); 5.000 (Legacy) | Selbst verwaltet (Proxy-Budget) | Credit-basiert |
| Einrichtungsaufwand | ~15 Min. (API-Key + SDK) | Stunden bis Tage | ~2 Min. |
| Geschäftsdaten | ~20 strukturierte Felder | Unbegrenzt (HTML/JSON parsen) | KI-empfohlene Felder |
| Anti-Bot-Handling | N/A (autorisiert) | Muss selbst gebaut werden | Automatisch abgedeckt |
| Rechtliches Risiko | ✅ Autorisiert | ⚠️ Graubereich der ToS | ⚠️ Gleich wie Scraping |
| Kosten | Ab $29/Monat | Kostenlos (+ Proxy-Kosten von $0,75–$4/GB) | Kostenloser Tarif verfügbar |
| Wartung | Niedrig (API stabil) | Hoch (Selektoren brechen, Anti-Bot wird härter) | Niedrig (KI passt sich neu an) |
Zur Fusion API greifst du, wenn: dir grundlegende Unternehmensinfos, kleine Abfragen oder eine autorisierte Integration genügen — und 3 Review-Auszüge pro Unternehmen ausreichen.
Python Scraping lohnt sich, wenn: du vollständige Review-Texte willst, alle Bewertungen eines Unternehmens, Review-Metadaten, mehr als 240 Ergebnisse pro Suche oder ein Budget unter 29 US-Dollar im Monat hast.
Thunderbit passt, wenn: du die Daten schnell brauchst, ohne Code zu schreiben oder zu warten. Dazu unten mehr im No-Code-Abschnitt.
Der No-Code-Shortcut: Yelp mit Thunderbit scrapen, ganz ohne Python
Bevor es tief in Python geht, hier der schnellste Weg für alle, denen es um die Daten geht und nicht ums Programmieren. Konkurrierende Anleitungen setzen fast immer Python-Kenntnisse voraus. In meiner Arbeit bei Thunderbit sehe ich dagegen ständig, dass ein Großteil derer, die nach „scrape Yelp" suchen, im Vertrieb, im Operations-Management oder in kleinen Betrieben sitzt — Leute, die eine Tabelle mit lokalen Firmen wollen und keinen Crashkurs in TLS-Fingerprinting.
Thunderbit bringt fertige Yelp-Vorlagen gleich mit:
- Yelp Business Web Scraper — extrahiert Firmenname, Bewertung, Kontaktdaten, Adresse, Öffnungszeiten, Kategorie
- Yelp Review Scraper — extrahiert Benutzername des Rezensenten, Rezensionstext, Bewertung, Datum, Standort des Rezensenten
So funktioniert es in der Praxis
- Öffne in Chrome eine Yelp-Suchergebnisseite oder eine Unternehmensseite
- Klicke in der Thunderbit-Erweiterung auf KI-Felder vorschlagen — die KI liest die Seite und schlägt Spalten vor (Firmenname, Bewertung, Anzahl der Rezensionen, Preisniveau, Kategorie, Adresse, Telefonnummer, URL)
- Klicke auf Scrape — fertig
Mit den fertigen Yelp-Vorlagen geht es noch flotter: Vorlage öffnen, Scrape klicken.
Subpage-Scraping erledigt den Anreicherungs-Loop von selbst: Du startest auf einer Yelp-Suchergebnisseite, schaltest Subpage-Scraping ein, und Thunderbit klappert jede Unternehmensseite ab, um Öffnungszeiten, vollständige Reviews, Website, Fotos und Ausstattungsmerkmale mitzunehmen. Zusätzliche Einrichtung entfällt.
Pagination läuft automatisch — per Klick wie per Scrollen, beides direkt eingebaut. (Details dazu in unserem Pagination-Leitfaden.)
Exporte sind in jedem Tarif kostenlos — Excel, Google Sheets, Airtable, Notion, CSV, JSON. Kein pandas, kein Code zum Schreiben von CSV-Dateien.
Zeitvergleich
| Zeit | Python Scraper | Thunderbit |
|---|---|---|
| Erster Lauf | Stunden bis Tage (Selektoren schreiben, Pagination, Proxies, Retry-Logik) | ~30 Sekunden mit der fertigen Yelp-Vorlage |
| Wenn Yelp das Markup ändert | Selektoren manuell neu schreiben | KI-Felder erneut vorschlagen klicken — passt sich automatisch an |
| Wenn die IP gesperrt wird | Debuggen, Proxy-Pools rotieren, erneut testen | Cloud-Modus übernimmt die IP-Rotation |
| Export nach Google Sheets | OAuth + pandas-Integration schreiben | Ein Klick, kostenlos |
Reicht dir Thunderbit nach dem ersten Test schon aus, kannst du dir den Rest des Artikels sparen. Wer volle programmatische Kontrolle, eigene Felder oder Volumen jenseits einiger tausend Datensätze pro Monat braucht, liest weiter.
Python-Bibliotheken fürs Yelp-Scraping: Welche solltest du wählen?
„Scrapy, BS4+requests oder Selenium?" gehört in den Yelp-Threads auf r/webscraping zu den Dauerbrennern. Trotzdem greift fast jedes Tutorial einfach zur Lieblingsbibliothek und macht weiter, ohne das Warum zu erklären. Hier die ehrliche Einordnung.
Die Realität 2025: requests + BeautifulSoup ist für Yelp kaputt
Der Stack aus jedem klassischen Yelp-Tutorial — pip install requests beautifulsoup4 — führt 2025 schon beim ersten Request zur Blockierung. Nicht beim 50., beim ersten.
Der Grund liegt im TLS-/JA3-Fingerprint der Python-requests-Bibliothek: Er passt zu keinem echten Browser. Yelps Anti-Bot-Schicht erkennt das bereits auf Ebene des TLS-Handshakes, also noch bevor dein User-Agent-Header überhaupt gelesen wird. Ich habe das wieder und wieder durchgespielt — frische IP, realistische Header, zufällige Pausen — und kassierte mit normalem requests trotzdem sofort einen 403 Forbidden.
Die Bibliotheks-Matrix
| Bibliothek | Am besten für | JS-fähig? | Anti-Bot? | Lernkurve | Geschwindigkeit |
|---|---|---|---|---|---|
requests + BeautifulSoup | ❌ | ❌ | Sehr gering | Schnell (bis zur Blockade) | |
httpx async + parsel | Groß angelegtes asynchrones Scraping | ❌ | ❌ | Gering | Sehr schnell |
curl_cffi + parsel | Yelp-spezifisch: TLS-Impersonation | ❌ | ✅ TLS/JA3/HTTP2 | Gering | Sehr schnell |
Scrapy 2.14 | Komplette Crawl-Pipelines mit Pagination | Teilweise (via scrapy-playwright) | AutoThrottle, Retry-Middleware | Mittel bis hoch | Schnell |
Selenium 4.43 / Playwright 1.58 | JS-lastige Seiten, CAPTCHA-Workarounds | ✅ | Teilweise | Mittel | Langsam (~10–30 Seiten/Min.) |
| Thunderbit | Nicht-Techniker, schnelle Extraktion | ✅ (Browser) | Integriert (Cloud-Modus) | Sehr gering | Schnell |
Die curl_cffi-Erkenntnis
Die Bibliothek, die meinen Yelp-Workflow umgekrempelt hat, heißt curl_cffi — ein Python-Binding für curl-impersonate. Sie erzeugt exakt denselben TLS-/JA3- und HTTP/2-Fingerprint wie echter Chrome, und ihre API lässt sich nahtlos für requests einsetzen:
from curl_cffi import requests
r = requests.get(
"https://www.yelp.com/biz/some-restaurant",
impersonate="chrome131",
)
print(r.status_code, len(r.text))
Diese eine Änderung — from curl_cffi import requests plus impersonate="chrome131" — hebelt Yelps größte Anti-Bot-Schicht aus, ganz ohne Browser-Start. In meinen Tests liegt genau hier der Unterschied zwischen sofortigen 403s und sauberen 200-Antworten.
Mein empfohlener Stack für Yelp 2025: curl_cffi + parsel + jmespath + Residential Proxies. Brauchst du eine komplette Crawl-Pipeline mit Scheduling, packst du das Ganze in Scrapy 2.14 mit einer Downloader-Middleware auf curl_cffi-Basis.
So richtest du deine Python-Umgebung für Yelp-Scraping ein
- Schwierigkeitsgrad: Mittel
- Benötigte Zeit: ~15 Minuten für die Einrichtung, 1–2 Stunden für einen funktionierenden Scraper
- Was du brauchst: Python 3.10+ (empfohlen: 3.12), ein Terminal und optional einen Anbieter für Residential Proxies
Schritt 1: Virtuelle Umgebung erstellen und Pakete installieren
python3.12 -m venv .venv
source .venv/bin/activate # Unter Windows: .venv\Scripts\activate
pip install "curl_cffi>=0.11" "parsel>=1.9" "jmespath>=1.0" pandas
Was die einzelnen Pakete machen:
curl_cffi— sendet HTTP-Requests mit Chromes TLS-Fingerprint (der Anti-Bot-Bypass)parsel— CSS-/XPath-Selektoren zum Parsen von HTML (die gleiche Engine wie Scrapy, nur leichter)jmespath— deklarative JSON-Abfragen (sauberer als verschachtelter Dict-Zugriff für eingebettetes Yelp-JSON)pandas— Datenexport nach CSV/Excel
Optional, aber hilfreich:
pip install fake-useragent # Hinweis: Repo im April 2026 archiviert, aber noch installierbar
Schritt für Schritt: So scrapest du Yelp mit Python
Jetzt zum Kern. Der größte Hebel für robuste Scraper: Finger weg von CSS-Selektoren, ran ans versteckte JSON. Yelp würfelt seine CSS-Klassennamen beim Build durch (y-css-14xwok2 diese Woche, y-css-hcq7b9 nächste Woche), weshalb jeder fest darauf verdrahtete Scraper binnen weniger Wochen bricht. Die eingebetteten JSON-Payloads dagegen — application/ld+json-Schema und react-root-props — bleiben stabil.
Schritt 2: Yelp-Suchergebnisse scrapen
Yelp-Such-URLs folgen einem vorhersehbaren Muster: https://www.yelp.com/search?find_desc={term}&find_loc={location}. Die Suchergebnisdaten stecken als JSON in einem <script data-id="react-root-props">-Tag — und nicht in einem CSS-Klassen-Wirrwarr.
import re, json, jmespath
from curl_cffi import requests
from parsel import Selector
HEADERS = {
"user-agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) "
"AppleWebKit/537.36 (KHTML, like Gecko) "
"Chrome/124.0.0.0 Safari/537.36",
"accept": "text/html,application/xhtml+xml,application/xml;q=0.9,"
"image/avif,image/webp,image/apng,*/*;q=0.8",
"accept-language": "en-US,en;q=0.9",
"accept-encoding": "gzip, deflate, br",
"cookie": "intl_splash=false",
}
def scrape_search(term: str, location: str, max_pages: int = 3):
results = []
for page in range(max_pages):
url = (f"https://www.yelp.com/search?"
f"find_desc={term}&find_loc={location}&start={page * 10}")
r = requests.get(url, headers=HEADERS, impersonate="chrome131")
if r.status_code != 200:
print(f"Blocked on page {page}: {r.status_code}")
break
sel = Selector(text=r.text)
script = sel.xpath(
"//script[@data-id='react-root-props']/text()"
).get() or ""
m = re.search(r"react_root_props\s*=\s*(\{.*?\});", script, re.S)
if not m:
print(f"No react-root-props found on page {page} — possible soft block")
break
data = json.loads(m.group(1))
businesses = jmespath.search(
"legacyProps.searchAppProps.searchPageProps"
".mainContentComponentsListProps"
"[?searchResultBusiness].searchResultBusiness.{"
"name: name, url: businessUrl, rating: rating, "
"reviews: reviewCount, phone: phone, "
"neighborhoods: neighborhoods}",
data,
) or []
results.extend(businesses)
import time, random
time.sleep(random.uniform(3, 7))
return results
Zurück kommt eine Liste von Dicts mit Firmennamen, URLs, Bewertungen und Review-Anzahlen. Fehlt react-root-props in der Antwort, hast du eine Block-Seite erwischt — IP wechseln und neu versuchen.
Der Header Cookie: intl_splash=false ist ein Standard-Trick gegen Yelps Länder-Splash-Redirect. Ohne ihn landen Nicht-US-IPs auf einer Splash-Seite, die wie ein Soft-Block aussieht, aber keiner ist.
Schritt 3: Yelp-Unternehmensseiten scrapen
Jede Unternehmens-URL aus den Suchergebnissen führt auf eine Detailseite mit reicheren Daten. Das stabilste Extraktionsziel ist hier der <script type="application/ld+json">-Block — er enthält strukturierte schema.org-Daten, die Yelp für SEO pflegt und deshalb nicht verschleiert.
def scrape_business(biz_url: str) -> dict:
url = f"https://www.yelp.com{biz_url}" if biz_url.startswith("/") else biz_url
r = requests.get(url, headers=HEADERS, impersonate="chrome131")
if r.status_code != 200:
return {"url": url, "error": r.status_code}
sel = Selector(text=r.text)
biz_id = sel.css('meta[name="yelp-biz-id"]::attr(content)').get()
for raw in sel.css('script[type="application/ld+json"]::text').getall():
try:
data = json.loads(raw)
except json.JSONDecodeError:
continue
for node in (data if isinstance(data, list) else [data]):
if node.get("@type") in (
"Restaurant", "LocalBusiness", "FoodEstablishment",
"HealthAndBeautyBusiness", "HomeAndConstructionBusiness",
):
return {
"biz_id": biz_id,
"name": node.get("name"),
"rating": (node.get("aggregateRating") or {}).get("ratingValue"),
"review_count": (node.get("aggregateRating") or {}).get("reviewCount"),
"address": node.get("address"),
"telephone": node.get("telephone"),
"price_range": node.get("priceRange"),
"hours": node.get("openingHours"),
"url": url,
}
return {"biz_id": biz_id, "url": url}
Der Wert von meta[name="yelp-biz-id"] ist die kodierte Unternehmens-ID, die du für den Reviews-Endpunkt brauchst. Hol sie dir hier — im nächsten Schritt kommt sie zum Einsatz.
Schritt 4: Yelp-Reviews mit Pagination scrapen
Hier zeigt sich, warum Scraping der Fusion API überlegen ist. Yelps interner GraphQL-Batch-Endpunkt rückt vollständige Rezensionstexte, Rezensenteninfos, Daten, Bewertungen und Vote-Zahlen heraus — also genau das, was die API zurückhält.
Der Endpunkt heißt https://www.yelp.com/gql/batch und nutzt für die Operation GetBusinessReviewFeed eine statische documentId. Paginiert wird über einen base64-kodierten Cursor.
import base64
GQL_URL = "https://www.yelp.com/gql/batch"
DOC_ID = "ef51f33d1b0eccc958dddbf6cde15739c48b34637a00ebe316441031d4bf7681"
def fetch_reviews(enc_biz_id: str, num_pages: int = 5):
all_reviews = []
for page in range(num_pages):
offset = page * 10
cursor = base64.b64encode(
json.dumps({"version": 1, "offset": offset}).encode()
).decode()
payload = [{
"operationName": "GetBusinessReviewFeed",
"variables": {
"encBizId": enc_biz_id,
"reviewsPerPage": 10,
"after": cursor,
"sortBy": "DATE_DESC",
"language": "en",
},
"extensions": {
"operationType": "query",
"documentId": DOC_ID,
},
}]
r = requests.post(
GQL_URL,
json=payload,
headers={
**HEADERS,
"content-type": "application/json",
"x-apollo-operation-name": "GetBusinessReviewFeed",
"apollographql-client-name": "yelp-main-frontend",
},
impersonate="chrome131",
)
if r.status_code != 200:
print(f"Review fetch failed at offset {offset}: {r.status_code}")
break
data = r.json()
# Zur Extraktion der Reviews die Antwortstruktur durchlaufen
try:
reviews = data[0]["data"]["business"]["reviews"]["edges"]
for edge in reviews:
node = edge.get("node", {})
all_reviews.append({
"reviewer": node.get("author", {}).get("displayName"),
"rating": node.get("rating"),
"date": node.get("localizedDate"),
"text": node.get("text", {}).get("full"),
})
except (KeyError, IndexError, TypeError):
break
import time, random
time.sleep(random.uniform(3, 7))
return all_reviews
Jede Seite bringt 10 Reviews. Zum Paginieren erhöhst du den offset im base64-Cursor. Der Parameter sortBy versteht DATE_DESC (neueste zuerst), RATING_ASC, RATING_DESC und weitere.
Schritt 5: Deine gescrapten Yelp-Daten exportieren
import pandas as pd
# Angenommen, du hast businesses und reviews bereits gesammelt
df_businesses = pd.DataFrame(businesses)
df_businesses.to_csv("yelp_businesses.csv", index=False)
df_reviews = pd.DataFrame(all_reviews)
df_reviews.to_csv("yelp_reviews.csv", index=False)
# Oder als JSON speichern, wenn du mehr Flexibilität willst
import json
with open("yelp_data.json", "w") as f:
json.dump({"businesses": businesses, "reviews": all_reviews}, f, indent=2)
Wer den No-Code-Pfad nimmt: Thunderbit schiebt dieselben Daten direkt nach Excel, Google Sheets, Airtable oder Notion — ohne pandas und ohne Code zum Schreiben von Dateien.
Das Anti-Blocking-Playbook: So scrapest du Yelp, ohne geblockt zu werden
Dieser Abschnitt ist der eigentliche Daseinszweck des Artikels. Yelps Abwehr hat seit Ende 2024 deutlich angezogen — TLS-Fingerprinting, IP-Reputation-Prüfungen, CAPTCHAs und Verhaltensanalysen greifen alle ineinander. Die meisten bestehenden Guides hinken hinterher, weil sie vor dieser Verschärfung entstanden sind.

Die Strategie ist mehrschichtig. Jede Ebene drückt deine Blockrate; zusammen machen sie dauerhaftes Scraping überhaupt erst praktikabel.
Ebene 1: Realistische Request-Header
Pythons requests schickt standardmäßig User-Agent: python-requests/2.x mit — und fliegt sofort raus. Doch selbst ein realistischer User-Agent reicht nicht: Yelp prüft auch die vollständigen Client-Hints auf Konsistenz.
FULL_HEADERS = {
"authority": "www.yelp.com",
"user-agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) "
"AppleWebKit/537.36 (KHTML, like Gecko) "
"Chrome/124.0.0.0 Safari/537.36",
"accept": "text/html,application/xhtml+xml,application/xml;q=0.9,"
"image/avif,image/webp,image/apng,*/*;q=0.8",
"accept-language": "en-US,en;q=0.9",
"accept-encoding": "gzip, deflate, br",
"sec-ch-ua": '"Chromium";v="124", "Google Chrome";v="124", "Not-A.Brand";v="99"',
"sec-ch-ua-mobile": "?0",
"sec-ch-ua-platform": '"Windows"',
"sec-fetch-dest": "document",
"sec-fetch-mode": "navigate",
"sec-fetch-site": "same-origin",
"sec-fetch-user": "?1",
"upgrade-insecure-requests": "1",
"referer": "https://www.yelp.com/",
"cookie": "intl_splash=false",
}
Drei Fehler, die dich verraten:
- Der UA gibt Chrome an, aber
sec-ch-uafehlt oder widerspricht der UA-Version sec-ch-ua-platformsagt „Windows", obwohl die UA macOS behauptet- Derselbe UA für Tausende Requests von einer IP — rotiere stattdessen einen Pool aus 10–20 aktuellen Chrome-/Firefox-/Safari-Strings
Ebene 2: Rate-Limiting und Zufallspausen
Berechenbare Timing-Muster sind ein Warnsignal. Streue zufällige Schlafintervalle ein und setze bei Fehlern auf exponentielles Backoff.
import random, time
def polite_get(client_get, url, attempt=0):
r = client_get(url, headers=FULL_HEADERS, impersonate="chrome131")
if r.status_code in (403, 429, 503):
if attempt >= 4:
raise RuntimeError(f"Blocked after {attempt + 1} attempts on {url}")
backoff = 2 ** (attempt + 1) + random.random()
print(f" Got {r.status_code}, backing off {backoff:.1f}s (attempt {attempt + 1})")
time.sleep(backoff)
return polite_get(client_get, url, attempt + 1)
time.sleep(random.uniform(3, 7))
return r
| Parameter | Empfohlener Wert |
|---|---|
| Zufällige Pause zwischen Requests | random.uniform(3, 7) Sekunden |
| Backoff bei 429/403/503 | 2 → 4 → 8 → 16 s, maximal 5 Versuche |
| Gleichzeitige Worker pro IP | 1 (pro IP serialisieren; für Parallelität Proxies nutzen) |
| Maximale nachhaltige Rate pro Residential IP | ca. 1 Req / 5 s (≈ 12 rpm) |
Ebene 3: User-Agent- und Session-Rotation
Wechsle durch echte Browser-User-Agents durch. Halte Sessions und Cookies, um echtes Surfverhalten nachzustellen — Yelp setzt auf cookie-basierte Erkennung, deshalb wirkt eine frische Session pro Request schon für sich verdächtig.
UA_POOL = [
"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 Chrome/124.0.0.0 Safari/537.36",
"Mozilla/5.0 (Macintosh; Intel Mac OS X 14_4_1) AppleWebKit/537.36 Chrome/124.0.0.0 Safari/537.36",
"Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:125.0) Gecko/20100101 Firefox/125.0",
"Mozilla/5.0 (Macintosh; Intel Mac OS X 14.4; rv:125.0) Gecko/20100101 Firefox/125.0",
"Mozilla/5.0 (Macintosh; Intel Mac OS X 14_4_1) AppleWebKit/605.1.15 Safari/17.4.1",
# Füge 5–10 weitere aktuelle Strings hinzu
]
Ebene 4: Proxy-Rotation
Bei ernsthaftem Volumen brauchst du Residential Proxies. Datacenter- und Free-Proxies funktionieren bei Yelp nicht — Yelps IP-Reputation-Layer blockiert AWS-, GCP- und DigitalOcean-IP-Bereiche präventiv mit 403.
| Anbieter | Einstiegspreis pro GB | Hinweise |
|---|---|---|
| IPRoyal | $1,75/GB | Am günstigsten; betreibt das meistzitierte Yelp-Tutorial |
| Decodo (ehem. Smartproxy) | $3,20–$3,50 | Bestes GB/$-Verhältnis bei größerem Volumen |
| Bright Data | $4,00 (PAYG) | 150M+ IP-Pool; dedizierte Yelp-Proxies-Seite |
| Oxylabs | $6,00–$8,00 | Premium; 10M+ IPs |
| Aluvia (mobile SIM) | $3,00 | Echte US-Mobilfunk-IPs, explizit für Yelp positioniert |
Rotierende Residential Proxies (neue IP pro Request) eignen sich am besten für große Such-Crawls. Sticky Sessions (eine IP zehn Minuten lang halten) sind die bessere Wahl, wenn du Cookies über einen Ablauf von Unternehmensseite → Reviews → Pagination hinweg behalten willst.
Ebene 5: Blocks erkennen und behandeln
Nicht jeder Block sieht gleich aus. Oft liefert Yelp statt eines CAPTCHAs eine generische „Seite nicht verfügbar"-Hülle aus — weshalb naive Scraper glauben, sie hätten Daten, während sie in Wahrheit nur leere Antworten einsammeln.
BLOCK_MARKERS = (
"captcha", "px-captcha", "page not available",
"access denied", "unusual traffic",
)
def is_blocked(resp):
if resp.status_code in (401, 403, 429, 503):
return True
body = resp.text.lower()
if any(m in body for m in BLOCK_MARKERS):
return True
# Wenn es sich um eine Such-/Unternehmensseite handelt, aber react-root-props fehlt,
# hat Yelp eine abgespeckte Block-Antwort geliefert
if "react-root-props" not in body and "/biz/" in str(resp.url):
return True
return False
| Signal | Bedeutung |
|---|---|
| HTTP 403 | Harter Block — IP/Header/TLS verbrannt |
| HTTP 429 | Rate-Limit — oft mit Backoff behebbar |
| HTTP 503 | Generischer Block oder Lastabwurf |
Weiterleitung zu /error oder Body mit „page not available“ | Weicher Block |
| Leerer mit nur | Challenge-Seite wartet auf JS |
captcha / g-recaptcha / px-captcha im Body | Eskaliert — CAPTCHA erforderlich |
Fehlendes react-root-props auf einer Listing-Seite | Abgespeckte Block-Antwort |
Ebene 6: Der robuste Parsing-Trick — verstecktes JSON statt CSS-Selektoren
Noch einmal, weil es so zentral ist: Yelp würfelt seine CSS-Klassennamen beim Build durch. Ein auf h3.y-css-14xwok2 fest verdrahteter Scraper bricht binnen Wochen, sobald Yelp mit h3.y-css-hcq7b9 neu ausrollt.
Die Payloads, die sich nicht ändern:
<script type="application/ld+json">— strukturierte schema.org-Daten (Name, Adresse, Telefon, Bewertung, Öffnungszeiten)<script data-id="react-root-props">— vollständige Suchergebnisse als JSONhttps://www.yelp.com/gql/batch— GraphQL-Reviews-Endpunkt mit stabilerdocumentId
Wer CSS-Klassen parst, baut auf Sand. Parse stattdessen das JSON.
Ebene 7: Der Stealth-Browser als Fallback
Zum Headless-Browser greifst du nur, wenn curl_cffi + Residential Proxies nicht durchkommen — typischerweise dann, wenn Yelp eine JavaScript-Challenge-Seite oder ein CAPTCHA ausspielt.
Für 95 % der Business-/Search-/Review-Extraktionen sind curl_cffi + verstecktes JSON + Residential Proxies schneller, günstiger und zuverlässiger als ein Browser. Wenn es aber wirklich ein Browser sein muss:
| Tool | Status (2025) | Hinweise |
|---|---|---|
| rebrowser-playwright | Empfohlener Einstieg | Drop-in-Playwright mit Patches gegen CDP-Leaks |
| nodriver | Best-in-Class für Chrome-Stealth | Nachfolger von undetected-chromedriver; umgeht das WebDriver-Protokoll komplett |
| patchright | Aktiv gepflegter Playwright-Fork | Besteht moderne Detection-Tests |
| playwright-stealth | Ausgereift | Patcht navigator.webdriver, entfernt HeadlessChrome aus dem UA |
Lass bei Yelp die Finger von normalem Selenium. Es ist zu leicht zu fingerprinten.
Yelp Fusion API vs. Python Scraping vs. Thunderbit: Vollständiger Vergleich
| Dimension | Yelp Fusion API | Python Scraping | Thunderbit |
|---|---|---|---|
| Vollständiger Rezensionstext | ❌ 3 Auszüge × ~160 Zeichen | ✅ Unbegrenzt (GraphQL) | ✅ Integrierte Review-Vorlage |
| Review-Metadaten (Votes, Antworten des Betreibers) | ❌ | ✅ | ✅ Über KI-vorgeschlagene Felder |
| Fotos | ❌ (0 im Base-Tarif) | ✅ Unbegrenzt | ✅ |
| Max. Ergebnisse pro Suche | 240 (vor 2024 waren es 1.000) | Unbegrenzt (paginiert) | Unbegrenzt |
| Tägliches Rate Limit | 300–500 (neu) / 5.000 (Legacy) | Nur durch Proxy-Budget begrenzt | Credit-basiert (3.000/Monat im Pro-Tarif) |
| Einrichtungsaufwand | ~15 Min. | Stunden bis Tage | ~2 Min. |
| Anti-Bot-Handling | N/A | Dein Problem | Abgedeckt (Cloud-Modus) |
| Rechtliches Risiko | Niedrig (autorisiert) | Mittel (ToS-Graubereich) | Mittel (gleich wie Scraping) |
| Kosten (Einstieg) | Ab $29/Monat | ~ $0,75–$4/GB für Proxies + Entwicklungszeit | Kostenloser Tarif |
| Kosten bei hoher Nutzung | $643+/Monat | $50–$500/Monat für Proxies + Entwicklungszeit | $38–$49/Monat |
| Datenexport | JSON | CSV/JSON (musst du selbst bauen) | Excel / Sheets / Airtable / Notion — kostenlos |
| Wartung | Niedrig | Hoch (Selektoren brechen, Anti-Bot wird härter) | Niedrig (KI passt sich neu an) |
Rechtliche und ethische Hinweise zum Scraping von Yelp
Ich bin kein Anwalt, und das hier ist keine Rechtsberatung. Aber die Rechtslage hat sich in den letzten zwei Jahren so stark verschoben, dass du die Grundlagen kennen solltest, bevor du Zeit in ein Yelp-Scraping-Projekt steckst.
Was die Yelp-Nutzungsbedingungen sagen: Das ToS-Update von Oktober 2025 untersagt ausdrücklich „Robots, Spider ... oder andere automatisierte Mittel", um „Teile des Dienstes zuzugreifen, abzurufen, zu kopieren, zu scrapen oder zu indexieren". Neu hinzugekommen ist eine Formulierung zu „AI Technologies und/oder anderen automatisierten Tools".
Der Yelp-Support stellt klar: „Yelp erlaubt kein Scraping der Website."
Was die robots.txt sagt: Yelps robots.txt enthält ein pauschales User-agent: * / Disallow: / und sperrt darüber hinaus ausdrücklich GPTBot, ClaudeBot, PerplexityBot, CCBot und Meta-ExternalAgent. Freigegeben sind allein Googlebot, Bingbot und einige Social-Media-Crawler.
Der relevante Rechtspräzedenzfall: In Meta v. Bright Data (N.D. Cal., Jan. 2024) entschied das Gericht, dass das Scraping öffentlich zugänglicher, ausgeloggter Daten nicht gegen Metas Nutzungsbedingungen verstieß. Der springende Punkt: öffentlich zugängliche, ausgeloggte Daten vs. eingeloggte Daten. Der Fall hiQ v. LinkedIn zeigte, dass Scraping öffentlich zugänglicher Daten wohl nicht gegen den CFAA verstößt — hiQ verlor aber dennoch bei zivilrechtlichen Ansprüchen nach Landesrecht (trespass to chattels, misappropriation) und kassierte ein Urteil über 500.000 US-Dollar.
Praktische Leitlinien:
- Scrape nur öffentlich zugängliche, ausgeloggte Seiten
- Rate-Limit für Requests einhalten (die Verzögerungen in diesem Leitfaden sind zugleich ethische Limits)
- Rohe Review-Texte nicht mit Klarnamen weiterverkaufen — respektiere die Privatsphäre der Rezensenten
- Lokale Datenschutzgesetze einhalten (CCPA, DSGVO)
- Nicht zum Scrapen einloggen — damit überschreitest du die Autorisierungslinie
- Behandle Unternehmensdaten (Name/Adresse/Telefon/Bewertung) als öffentliche Faktendaten; Review-Texte sind sensibler
Zieh für deinen konkreten Fall eine juristische Fachperson hinzu.
Fazit
Drei Wege, ein Ziel.
Die Yelp Fusion API ist die autorisierte, wartungsarme Option — sie beschränkt dich aber auf 3 Review-Auszüge und startet bei 29 US-Dollar im Monat. Python Scraping gibt dir die volle Kontrolle über jeden Datenpunkt auf Yelp, verlangt dafür echten Einsatz: curl_cffi für TLS-Impersonation, Residential Proxies, Zufallspausen, das Parsen von verstecktem JSON und laufende Wartung, wann immer Yelp seine Abwehr weiterdreht. Thunderbit bringt dich in rund 30 Sekunden von „Ich brauche Yelp-Daten" zu „Hier ist meine Tabelle" — ohne Code und ohne Proxy-Konfiguration.
Die Anti-Block-Grundlagen, die 2025 wirklich tragen: realistische Header mit vollständigen Client Hints, curl_cffi für die TLS-Fingerprint-Impersonation, zufällige Verzögerungen mit exponentiellem Backoff, Rotation von Residential Proxies und — vor allem — das Parsen von verstecktem JSON (application/ld+json und react-root-props) statt fragiler CSS-Selektoren.
Unsicher, welcher Weg passt? Teste zuerst die kostenlose Version von Thunderbit. Deckt sie deinen Bedarf, sparst du dir Stunden. Brauchst du mehr Kontrolle — vollständige programmatische Pipelines, eigene Felder, enge CRM-Integration — hilft dir der Python-Leitfaden oben weiter. Und für einen tieferen Blick auf die Tool-Landschaft schau in unseren Überblick über die besten Chrome-Erweiterungen für Web Scraper oder unseren Leitfaden zum Extrahieren von Daten von Websites nach Excel.
Thunderbit für die Extraktion von Yelp-Daten ausprobieren Get Started Free
FAQs
Kann ich Yelp mit Python kostenlos scrapen?
Ja — mit kostenlosen Bibliotheken wie curl_cffi, parsel und jmespath. Bei realem Volumen (mehr als ein paar Dutzend Seiten) brauchst du allerdings kostenpflichtige Residential Proxies, die laut IPRoyal ab etwa $1,75/GB starten. Thunderbit hat zudem einen kostenlosen Tarif mit 6 Seiten pro Monat für schnelle No-Code-Extraktion.
Blockiert Yelp Scraper?
Ja, und zwar sehr aggressiv. Yelp arbeitet mit TLS-/JA3-Fingerprinting, IP-Reputation-Scoring, CAPTCHAs, Verhaltensanalysen und wechselnden verschleierten CSS-Klassen. Normales requests fliegt sofort beim ersten Treffer raus. Was 2025 funktioniert, ist die mehrschichtige Anti-Block-Strategie aus diesem Leitfaden — curl_cffi für die TLS-Impersonation, realistische Header, zufällige Pausen und Residential Proxies.
Ist die Yelp Fusion API besser als Scraping?
Kommt auf deinen Bedarf an. Die API ist autorisiert und risikoarm, gibt aber nur 3 Rezension-Auszüge mit jeweils ~160 Zeichen heraus, begrenzt Suchergebnisse auf 240 und startet bei 29 US-Dollar pro Monat. Brauchst du vollständige Rezensionstexte, Review-Metadaten oder mehr als ein paar hundert Datensätze pro Tag, bleibt Scraping die einzige Option.
Wie scrape ich Yelp-Reviews mit Python?
Hol mit curl_cffi und impersonate="chrome131" die Unternehmensseite, zieh dann die kodierte Unternehmens-ID aus <meta name="yelp-biz-id"> und schick anschließend einen POST an https://www.yelp.com/gql/batch mit der Operation GetBusinessReviewFeed. Paginiert wird über einen base64-kodierten after-Cursor. Der Schritt-für-Schritt-Code steht oben im Tutorial-Abschnitt. Auch das Scrapfly-Yelp-Scraper-Repo ist eine solide Referenzimplementierung.
Kann ich Yelp ohne Programmieren scrapen?
Ja — Thunderbits AI Web Scraper bringt fertige Vorlagen für Yelp-Unternehmen und Reviews mit. Yelp-Seite öffnen, KI-Felder vorschlagen klicken, dann Scrape. Exporte nach Google Sheets, Excel, Airtable und Notion sind in jedem Tarif kostenlos, auch im Gratisplan.
Mehr erfahren


