Yelp хранит 330 миллионов накопленных отзывов на 8,4 миллиона активных страниц компаний — и превратить эти данные в удобный формат стало как никогда сложно. Антибот-кампания Yelp в 2024–2025 годах тихо поломала большую часть существующих Python-руководств по парсингу.
Если ты недавно пытался запустить Yelp scraper и упирался в стену из ошибок 403, пустых HTML-ответов или CAPTCHA, которых ещё полгода назад не было, тебе это не кажется. Сейчас Yelp использует TLS/JA3-фингерпринтинг, постоянно меняющиеся обфусцированные CSS-классы и жёсткую оценку репутации IP-адресов — из-за этого старый подход requests + BeautifulSoup, который до сих пор советуют почти все туториалы, ломается с первого же запроса. Я несколько недель тестировал разные способы работы с текущей защитой Yelp и в этом гайде собрал всё, что реально работает в 2025 году: официальный Fusion API (и почему его, скорее всего, будет недостаточно), полноценный Python-воркфлоу со слоистой стратегией обхода блокировок и no-code альтернативу в 2 клика с Thunderbit для тех, кому нужны просто данные, а не марафон по отладке.
Попробовать Thunderbit для парсинга Yelp
Зачем парсить Yelp на Python и кому это вообще нужно
Прежде чем писать хоть строчку кода, стоит понять: какую реальную бизнес-задачу решают данные Yelp? Это не просто сайт с отзывами о ресторанах — по сути, это живая база локальных компаний со структурированными контактами, рейтингами, категориями, графиком работы и сотнями миллионов пользовательских отзывов.

Вот кому такие данные полезнее всего и что именно они обычно вытаскивают:
| Сценарий | Ключевые поля | Почему это важно |
|---|---|---|
| Продажи и лидогенерация | Название компании, телефон, сайт, адрес, категория, рейтинг | Собирайте целевые списки локальных SMB — 4 из 5 пользователей Yelp уже готовы к покупке прямо на входе |
| Конкурентная разведка | Отзывы, звёздный рейтинг, количество отзывов, тональность | Следите за репутацией конкурентов, находите слабые места в сервисе, отслеживайте тренды |
| Маркетинговые исследования и NLP | Полный текст отзывов, даты, метаданные автора | Анализ тональности, тематическое моделирование — отзывы Yelp один из самых используемых NLP-корпусов в академических исследованиях |
| Недвижимость и выбор локации | Плотность бизнеса, сочетание категорий, качество отзывов по районам | Подбор точек для франшиз и ритейла — Yelp продаёт Location Intelligence как лицензированный B2B-продукт именно для этого |
| Ecommerce и операционные процессы | Сигналы о ценах, жалобы клиентов, часы работы | Отслеживайте, как оценивают конкурентов, и выявляйте операционные паттерны |
Смысл в целом один: конечная цель — структурированные данные, а Python — лишь один из способов их получить. Кому-то нужен полный программный контроль. А кому-то достаточно таблицы с контактами сантехников в Остине. В этом материале разобраны оба подхода.
Yelp Fusion API vs. Python web scraping: что выбрать?
Большинство гайдов вообще пропускают этот шаг и сразу переходят к коду, не проверяя, хватило бы официального Yelp Fusion API (сейчас оно переименовано в "Yelp Places API"). На практике такой анализ экономит часы впустую потраченного времени — потому что API отлично подходит для одних задач и совершенно не годится для других.
Что реально даёт Fusion API
Fusion API предоставляет структурированный поиск компаний, подробности о бизнесе, автодополнение и endpoint с отзывами. Это официальный, документированный способ доступа, без танцев с антибот-защитой.
Но всё ломается именно на endpoint с отзывами. Вот что подтвердили сотрудники Yelp на GitHub:
"Yelp API не возвращает полный текст отзыва. По умолчанию выдаются три фрагмента по 160 символов." — ответ сотрудника Yelp, GitHub Issue #163
Это не баг, а задумка. API физически ограничивает выдачу 3 фрагментами отзывов (7 на Premium), каждый из них обрезан примерно до 160 символов. Нет метаданных отзывов (useful/funny/cool), нет истории автора, нет ответов владельца. А дневной лимит для новых клиентов после мая 2023 года снизился до 300–500 запросов в день — раньше было 5 000. Стартовая цена начинается от $29 в месяц.
Как принять решение
| Фактор | Yelp Fusion API | Python scraping | Thunderbit (no-code) |
|---|---|---|---|
| Полные отзывы | ❌ Только 3 фрагмента (~160 символов каждый) | ✅ Все отзывы через GraphQL | ✅ Все видимые отзывы |
| Лимиты запросов | 300–500/день (новые); 5 000 (старые) | Вы управляете сами (и бюджетом на прокси) | По кредитной модели |
| Сложность запуска | ~15 минут (API-ключ + SDK) | От часов до дней | ~2 минуты |
| Поля о бизнесе | ~20 структурированных полей | Без ограничений (HTML/JSON-парсинг) | Поля, предлагаемые ИИ |
| Обход антибота | Не нужен | Нужно реализовать самому | Обрабатывается автоматически |
| Юридический риск | ✅ Официально разрешено | ⚠️ Серая зона ToS | ⚠️ Тот же риск, что и у парсинга |
| Стоимость | минимум $29/мес | Бесплатно (+ прокси $0.75–$4/GB) | Есть бесплатный тариф |
| Поддержка | Низкая (API стабилен) | Высокая (селекторы ломаются, антибот усиливается) | Низкая (ИИ подстраивается) |
Используй Fusion API, если: тебе нужны базовые данные о бизнесе, небольшие выборки или официальный интеграционный сценарий — и достаточно 3 фрагментов отзывов на компанию.
Используй Python scraping, если: нужны полные тексты отзывов, все отзывы по компании, метаданные отзывов, больше 240 результатов в поиске или бюджет ниже $29 в месяц.
Используй Thunderbit, если: хочешь быстро получить данные без написания и поддержки кода. Ниже я подробнее покажу no-code вариант.
No-code shortcut: парсинг Yelp через Thunderbit без Python
Прежде чем переходить к Python, вот самый быстрый путь для тех, кому нужны данные, а не упражнения в программировании. Почти все конкурирующие гайды подразумевают, что ты знаешь Python, но в работе с Thunderbit я вижу, что огромная часть людей, которые ищут "scrape Yelp", — это sales-менеджеры, операционные специалисты и владельцы малого бизнеса. Им нужна таблица с локальными компаниями, а не ускоренный курс по TLS-фингерпринтингу.
Thunderbit уже предлагает готовые шаблоны для Yelp:
- Yelp Business Web Scraper — извлекает название компании, рейтинг, контакты, адрес, часы работы, категорию
- Yelp Review Scraper — извлекает имя пользователя, текст отзыва, рейтинг, дату, локацию автора
Как это работает на практике
- Открой страницу результатов поиска Yelp или страницу компании в Chrome
- Нажми AI Suggest Fields в расширении Thunderbit — ИИ прочитает страницу и предложит столбцы (название компании, рейтинг, число отзывов, ценовой диапазон, категория, адрес, телефон, URL)
- Нажми Scrape — готово
Если ты используешь готовые шаблоны Yelp, всё ещё проще: открой шаблон и нажми Scrape.
Парсинг вложенных страниц автоматически обрабатывает enrichment-цикл — начни со страницы поиска Yelp, включи subpage scraping, и Thunderbit сам зайдёт на страницу каждой компании, чтобы собрать часы работы, полные отзывы, сайт, фото и удобства. Без дополнительной настройки.
Пагинация автоматическая — и для кликов, и для бесконечной прокрутки, всё работает из коробки. (Подробнее о том, как это устроено, см. наш гид по пагинации.)
Экспорт бесплатен на всех тарифах — Excel, Google Sheets, Airtable, Notion, CSV, JSON. Никакого pandas и никакого кода для записи файлов.
Сравнение по времени
| Время | Python scraper | Thunderbit |
|---|---|---|
| Первый запуск | Часы или дни (селекторы, пагинация, прокси, retry-логика) | ~30 секунд с готовым шаблоном Yelp |
| Когда Yelp меняет разметку | Вручную переписывать селекторы | Снова нажать AI Suggest Fields — всё подстроится автоматически |
| Когда блокируют IP | Отладка, ротация пулов прокси, повторные тесты | Cloud mode сам ротирует IP |
| Экспорт в Google Sheets | Писать OAuth и связку с pandas | Один клик, бесплатно |
Если после первой попытки Thunderbit закрывает твою задачу, можно смело пропустить оставшуюся часть статьи. Если же тебе нужен полный программный контроль, кастомные поля или масштаб свыше нескольких тысяч записей в месяц — читай дальше.
Python-библиотеки для парсинга Yelp: что выбрать
"Что лучше использовать для Yelp — Scrapy, BS4+requests или Selenium?" — один из самых частых вопросов в обсуждениях r/webscraping. И при этом в каждом туториале просто выбирают любимую библиотеку и идут дальше, не объясняя почему. Вот честный разбор.
Реальность 2025 года: requests + BeautifulSoup для Yelp сломан
Стек, который до сих пор советуют в каждом классическом гайде по Yelp — pip install requests beautifulsoup4 — получает блокировку уже на первом запросе в 2025 году. Не на 50-м. На первом.
Причина в том, что библиотека requests отправляет TLS/JA3-фингерпринт, который не совпадает ни с одним реальным браузером. Антибот-слой Yelp вычисляет это ещё на уровне TLS-handshake, до того как вообще прочитает заголовок User-Agent. Я проверял это много раз — свежий IP, реалистичные заголовки, случайные задержки — и всё равно моментально получал 403 Forbidden на обычном requests.
Матрица выбора библиотеки
| Библиотека | Лучше всего подходит для | Работает с JS? | Обход антибота? | Порог входа | Скорость |
|---|---|---|---|---|---|
requests + BeautifulSoup | ❌ | ❌ | Очень низкий | Быстро, пока не заблокировали | |
httpx async + parsel | Асинхронный парсинг в большом объёме | ❌ | ❌ | Низкий | Очень быстро |
curl_cffi + parsel | Специально для Yelp: имитация TLS | ❌ | ✅ TLS/JA3/HTTP2 | Низкий | Очень быстро |
Scrapy 2.14 | Полноценные crawl-пайплайны с пагинацией | Частично (через scrapy-playwright) | AutoThrottle, retry middleware | Средне-высокий | Быстро |
Selenium 4.43 / Playwright 1.58 | Страницы с тяжёлым JS, обход CAPTCHA | ✅ | Частично | Средний | Медленно (~10–30 страниц/мин) |
| Thunderbit | Непрограммисты, быстрое извлечение | ✅ (в браузере) | Встроено (Cloud mode) | Очень низкий | Быстро |
Почему curl_cffi — это находка
Библиотека, которая изменила мой рабочий процесс для Yelp, — это curl_cffi, Python-обёртка над curl-impersonate. Она выдаёт точно такой же TLS/JA3 + HTTP/2-фингерпринт, как настоящий Chrome, а её API почти полностью заменяет requests:
from curl_cffi import requests
r = requests.get(
"https://www.yelp.com/biz/some-restaurant",
impersonate="chrome131",
)
print(r.status_code, len(r.text))
Одно это изменение — from curl_cffi import requests плюс impersonate="chrome131" — позволяет обойти крупнейший слой антибот-защиты Yelp без запуска браузера. По моим тестам, это разница между мгновенным 403 и чистым ответом 200.
Мой рекомендуемый стек для Yelp в 2025 году: curl_cffi + parsel + jmespath + residential proxies. Если нужен полный пайплайн с расписанием, можно обернуть это в Scrapy 2.14 с downloader middleware на базе curl_cffi.
Настраиваем Python-окружение для парсинга Yelp
- Сложность: средняя
- Время: около 15 минут на настройку, 1–2 часа на рабочий скрапер
- Что понадобится: Python 3.10+ (рекомендуется 3.12), терминал и, по желанию, провайдер residential proxy
Шаг 1: Создайте виртуальное окружение и установите пакеты
python3.12 -m venv .venv
source .venv/bin/activate # На Windows: .venv\Scripts\activate
pip install "curl_cffi>=0.11" "parsel>=1.9" "jmespath>=1.0" pandas
Что делает каждый пакет:
curl_cffi— отправляет HTTP-запросы с TLS-фингерпринтом Chrome (обход антибота)parsel— CSS/XPath-селекторы для парсинга HTML (тот же движок, что у Scrapy, но легче)jmespath— декларативные запросы к JSON (удобнее, чем вручную лазить по вложенным словарям Yelp)pandas— экспорт данных в CSV/Excel
Дополнительно, но полезно:
pip install fake-useragent # Примечание: репозиторий архивирован в апреле 2026, но установка всё ещё работает
Пошагово: как парсить Yelp на Python
Это основная часть туториала. Главная идея, которая делает всё более устойчивым: не используй CSS-селекторы, а извлекай скрытый JSON. Yelp рандомизирует названия CSS-классов на этапе сборки (y-css-14xwok2 на этой неделе, y-css-hcq7b9 на следующей), поэтому любой скрапер, завязанный на них, ломается за несколько недель. Встроенные JSON-payload’ы — application/ld+json и react-root-props — остаются стабильными.
Шаг 2: парсинг результатов поиска Yelp
URL поиска Yelp имеет предсказуемый формат: https://www.yelp.com/search?find_desc={term}&find_loc={location}. Данные результатов поиска встроены в тег <script data-id="react-root-props"> как JSON, а не размазаны по CSS-каше.
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"Блокировка на странице {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"На странице {page} не найден react-root-props — возможна мягкая блокировка")
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
На выходе ты получишь список словарей с названиями компаний, URL, рейтингами и количеством отзывов. Если react-root-props отсутствует в ответе, тебе показали блок-оболочку — меняй IP и повторяй запрос.
Заголовок Cookie: intl_splash=false — стандартный обход редиректа с выбором страны у Yelp. Без него IP не из США попадают на splash-страницу, которая выглядит как мягкая блокировка, хотя ею не является.
Шаг 3: парсинг страниц компаний Yelp
Каждый URL компании из результатов поиска ведёт на карточку с более богатым набором данных. Самая стабильная цель для извлечения — блок <script type="application/ld+json">: там лежат структурированные schema.org-данные, которые Yelp поддерживает ради SEO и не пытается обфусцировать.
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}
Значение meta[name="yelp-biz-id"] — это закодированный ID компании, который понадобится для endpoint с отзывами. Сохрани его здесь — он пригодится на следующем шаге.
Шаг 4: парсинг отзывов Yelp с пагинацией
Вот здесь Fusion API уступает, а scraping выигрывает. Внутренний GraphQL batch-endpoint Yelp возвращает полный текст отзывов, информацию об авторе, даты, рейтинги и количество голосов — всё то, что скрывает API.
Endpoint находится по адресу https://www.yelp.com/gql/batch, и для операции GetBusinessReviewFeed используется статический documentId. Пагинация строится через cursor, закодированный в base64.
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"Ошибка при получении отзывов на смещении {offset}: {r.status_code}")
break
data = r.json()
# Переходим по структуре ответа и извлекаем отзывы
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
Каждая страница возвращает 10 отзывов. Для пагинации увеличивай offset в cursor, закодированном в base64. Параметр sortBy принимает DATE_DESC (сначала новые), RATING_ASC, RATING_DESC и другие значения.
Шаг 5: экспорт собранных данных Yelp
import pandas as pd
# Предположим, что у тебя уже собраны businesses и reviews
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)
# Или сохрани в JSON для большей гибкости
import json
with open("yelp_data.json", "w") as f:
json.dump({"businesses": businesses, "reviews": all_reviews}, f, indent=2)
Для тех, кто идёт по no-code пути, Thunderbit экспортирует те же данные прямо в Excel, Google Sheets, Airtable или Notion — без pandas и без кода для записи файлов.
Антиблокировочная стратегия: как парсить Yelp и не ловить блокировку
Именно ради этого раздела статья и написана. Меры защиты Yelp от ботов с конца 2024 года стали заметно жёстче — TLS fingerprinting, проверка репутации IP, CAPTCHA и поведенческий анализ теперь используются одновременно. Большинство старых гайдов устарели, потому что были написаны до этой волны ужесточения.

Стратегия должна быть многоуровневой. Каждый уровень снижает шанс блокировки; вместе они делают устойчивый парсинг реальным.
Уровень 1: реалистичные заголовки запроса
Стандартные заголовки Python requests отправляют User-Agent: python-requests/2.x — и это блокируется сразу. Но даже реалистичного User-Agent недостаточно. Yelp проверяет полный набор заголовков Client Hints на согласованность.
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",
}
Три ошибки, из-за которых тебя быстро вычисляют:
- UA говорит, что это Chrome, но
sec-ch-uaотсутствует или противоречит версии браузера sec-ch-ua-platformговорит "Windows", а в строке UA указан macOS- Один и тот же UA на тысячи запросов с одного IP — нужен пул из 10–20 свежих строк Chrome/Firefox/Safari
Уровень 2: rate limiting и случайные задержки
Предсказуемые интервалы — красный флаг. Добавляй случайные паузы и exponential 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"Блокировка после {attempt + 1} попыток на {url}")
backoff = 2 ** (attempt + 1) + random.random()
print(f" Получен {r.status_code}, делаю паузу {backoff:.1f}с (попытка {attempt + 1})")
time.sleep(backoff)
return polite_get(client_get, url, attempt + 1)
time.sleep(random.uniform(3, 7))
return r
| Параметр | Рекомендуемое значение |
|---|---|
| Случайная пауза между запросами | random.uniform(3, 7) секунд |
| Backoff при 429/403/503 | 2 → 4 → 8 → 16 сек, максимум 5 попыток |
| Одновременные воркеры на один IP | 1 (сериализуйте трафик на IP; для параллельности используйте прокси) |
| Максимальная устойчивая скорость на residential IP | примерно 1 запрос / 5 сек (~12 rpm) |
Уровень 3: ротация User-Agent и сессий
Используй пул реальных browser User-Agent. Сохраняй сессии и cookies, чтобы имитировать обычное поведение пользователя — Yelp применяет cookie-based detection, поэтому новая сессия на каждый запрос тоже выглядит подозрительно.
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",
# Добавьте ещё 5–10 свежих строк
]
Уровень 4: ротация прокси
При любом серьёзном объёме тебе нужны residential proxies. Датацентровые и бесплатные прокси для Yelp не работают — IP-слой репутации Yelp заранее отдаёт 403 для адресов AWS, GCP и DigitalOcean.
| Провайдер | Стартовая цена за GB | Примечания |
|---|---|---|
| IPRoyal | $1.75/GB | Самый дешёвый; на нём работает самый цитируемый туториал по Yelp |
| Decodo (бывш. Smartproxy) | $3.20–$3.50 | Лучшее соотношение GB/цена при большом объёме |
| Bright Data | $4.00 (PAYG) | Пул из 150M+ IP; есть отдельная страница Yelp Proxies |
| Oxylabs | $6.00–$8.00 | Премиум-уровень; 10M+ IPs |
| Aluvia (mobile SIM) | $3.00 | Реальные мобильные IP от американских операторов, позиционируются под Yelp |
Ротационные residential proxies (новый IP на каждый запрос) лучше всего работают для больших поисковых обходов. Sticky sessions (один IP на 10 минут) лучше подходят, когда нужно сохранить cookies на цепочке страница компании → отзывы → пагинация.
Уровень 5: как распознавать и обрабатывать блокировки
Не каждая блокировка выглядит одинаково. Yelp часто отдаёт не CAPTCHA, а общий shell с текстом вроде "page not available", из-за чего наивные скраперы думают, что получили данные, хотя на самом деле это пустой ответ.
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
# Если это search/business page, но react-root-props отсутствует,
# Yelp прислал урезанный блок-ответ
if "react-root-props" not in body and "/biz/" in str(resp.url):
return True
return False
| Сигнал | Что это значит |
|---|---|
| HTTP 403 | Жёсткая блокировка — IP/заголовки/TLS уже сгорели |
| HTTP 429 | Ограничение по частоте — часто можно восстановиться backoff’ом |
| HTTP 503 | Общая блокировка или перегрузка |
Редирект на /error или тело с "page not available" | Мягкая блокировка |
| Пустой только со | Challenge page, ожидающая JS |
captcha / g-recaptcha / px-captcha в теле | Эскалация — требуется CAPTCHA |
Отсутствует react-root-props на странице списка | Урезанный блок-ответ |
Уровень 6: устойчивый способ парсинга — скрытый JSON вместо CSS-селекторов
Повторю ещё раз: Yelp рандомизирует CSS-классы на этапе сборки. Скрапер, завязанный на h3.y-css-14xwok2, сломается за несколько недель, когда Yelp выкатит новую сборку с h3.y-css-hcq7b9.
Пейлоады, которые не меняются:
<script type="application/ld+json">— структурированные schema.org-данные (название, адрес, телефон, рейтинг, часы)<script data-id="react-root-props">— полные данные результатов поиска в JSONhttps://www.yelp.com/gql/batch— GraphQL endpoint с отзывами и стабильнымdocumentId
Если ты парсишь CSS-классы, ты строишь на песке. Парси JSON.
Уровень 7: запасной вариант со stealth-браузером
Переходи к headless-браузеру только если curl_cffi + residential proxies не проходят — обычно это бывает, когда Yelp показывает JavaScript challenge page или CAPTCHA.
Для 95% задач по парсингу компаний, поисковых результатов и отзывов curl_cffi + скрытый JSON + residential proxies быстрее, дешевле и надёжнее браузера. Но если браузер всё же нужен:
| Инструмент | Статус (2025) | Примечания |
|---|---|---|
| rebrowser-playwright | Лучший стартовый вариант | Готовый Playwright с патчами против утечек CDP |
| nodriver | Лучший stealth для Chrome | Наследник undetected-chromedriver; полностью обходит WebDriver protocol |
| patchright | Активно поддерживаемый форк Playwright | Проходит современные тесты на детект |
| playwright-stealth | Зрелое решение | Патчит navigator.webdriver, убирает HeadlessChrome из UA |
Для Yelp не используй обычный Selenium. Его слишком легко распознать.
Yelp Fusion API vs. Python scraping vs. Thunderbit: полное сравнение
| Параметр | Yelp Fusion API | Python scraping | Thunderbit |
|---|---|---|---|
| Полный текст отзывов | ❌ 3 фрагмента × ~160 символов | ✅ Без ограничений (GraphQL) | ✅ Встроенный шаблон для отзывов |
| Метаданные отзывов (голоса, ответы владельца) | ❌ | ✅ | ✅ Через поля, предложенные ИИ |
| Фото | ❌ (0 в Base) | ✅ Без ограничений | ✅ |
| Макс. результатов в поиске | 240 (раньше было 1 000 до 2024) | Без ограничений (с пагинацией) | Без ограничений |
| Дневной лимит | 300–500 (новые) / 5 000 (старые) | Только бюджет на прокси | По кредитам (3 000/мес на Pro) |
| Сложность запуска | ~15 минут | От часов до дней | ~2 минуты |
| Обход антибота | Не нужен | Ваша задача | Обрабатывается (Cloud mode) |
| Юридический риск | Низкий (официальный доступ) | Средний (серая зона ToS) | Средний (тот же риск, что у парсинга) |
| Стоимость на старте | от $29/мес | ~$0.75–$4/GB на прокси + время разработчика | Бесплатный тариф |
| Стоимость при активном использовании | $643+/мес | $50–$500/мес на прокси + время разработчика | $38–$49/мес |
| Экспорт данных | JSON | CSV/JSON (если напишете сами) | Excel / Sheets / Airtable / Notion — бесплатно |
| Поддержка | Низкая | Высокая (селекторы ломаются, антибот усиливается) | Низкая (ИИ подстраивается) |
Юридические и этические рекомендации по парсингу Yelp
Я не юрист, и это не юридическая консультация. Но за последние два года правовая картина изменилась настолько, что базовые вещи стоит понимать до того, как ты вложишь время в проект по парсингу Yelp.
Что говорит пользовательское соглашение Yelp: обновление ToS от октября 2025 года прямо запрещает использовать "any robot, spider... or other automated device" для того, чтобы "access, retrieve, copy, scrape, or index any portion of the Service." Там же добавили формулировки про "AI Technologies and/or other automated tools."
Служба поддержки Yelp подтверждает: "Yelp не разрешает никакой парсинг сайта."
Что говорит robots.txt: в robots.txt Yelp стоит wildcard User-agent: * / Disallow: /, а также отдельно блокируются GPTBot, ClaudeBot, PerplexityBot, CCBot и Meta-ExternalAgent. В белом списке только Googlebot, Bingbot и несколько социальных crawlers.
Важный судебный прецедент: в деле Meta v. Bright Data (N.D. Cal., январь 2024) суд постановил, что парсинг общедоступных данных без входа в аккаунт не нарушал ToS Meta. Ключевое различие здесь такое: публичные данные без авторизации vs. данные за логином. Дело hiQ v. LinkedIn показало, что парсинг публичных данных, вероятно, не нарушает CFAA, но при этом hiQ всё равно проиграл по искам на уровне штата (trespass to chattels, misappropriation) и получил решение на $500 000.
Практические рекомендации:
- Парси только общедоступные страницы без авторизации
- Ограничивай частоту запросов (задержки в этом гайде одновременно работают и как этический rate limit)
- Не перепродавай сырой текст отзывов с привязкой к именам пользователей — уважай приватность авторов
- Соблюдай местные законы о защите данных (CCPA, GDPR)
- Не входи в аккаунт ради парсинга — это уже выход за рамки разрешённого доступа
- Считай бизнес-данные (название/адрес/телефон/рейтинг) публичными фактами, а текст отзывов — более чувствительной информацией
В конкретной ситуации обязательно проконсультируйся с юристом.
Итоги
Три пути, одна цель.
Yelp Fusion API — это официальный и неприхотливый вариант, но он ограничен 3 фрагментами отзывов и стоит от $29 в месяц. Python scraping даёт полный контроль над каждым полем Yelp, но требует серьёзных вложений: curl_cffi для имитации TLS-фингерпринта, residential proxies, случайные задержки, парсинг скрытого JSON и постоянная поддержка по мере эволюции защиты Yelp. Thunderbit позволяет пройти путь от "мне нужны данные Yelp" до "вот моя таблица" примерно за 30 секунд — без кода и без настройки прокси.
Антиблокировочные приёмы, которые реально работают в 2025 году: реалистичные заголовки с полным набором Client Hints, curl_cffi для имитации TLS-фингерпринта, случайные задержки с exponential backoff, ротация residential proxies и — самое главное — парсинг скрытого JSON (application/ld+json и react-root-props) вместо хрупких CSS-селекторов.
Не уверен, что подойдёт именно тебе? Сначала попробуй бесплатный тариф Thunderbit. Если он закроет задачу, ты сэкономишь часы. Если нужен больший контроль — полноценные программные пайплайны, кастомные поля, тесная интеграция с CRM — тогда подойдёт Python-гайд выше. А если хочешь глубже изучить рынок инструментов для парсинга, посмотри наш обзор лучших расширений Chrome для web scraper или руководство по извлечению данных с сайтов в Excel.
Попробовать Thunderbit для извлечения данных Yelp Get Started Free
Частые вопросы
Можно ли бесплатно парсить Yelp на Python?
Да — с помощью бесплатных библиотек вроде curl_cffi, parsel и jmespath. Но при любом реальном объёме (больше нескольких десятков страниц) тебе понадобятся платные residential proxies, которые начинаются примерно с $1.75/GB у IPRoyal. У Thunderbit тоже есть бесплатный тариф: 6 страниц в месяц для быстрого no-code извлечения.
Yelp блокирует скраперы?
Да, и довольно агрессивно. Yelp использует TLS/JA3 fingerprinting, оценку репутации IP, CAPTCHA, поведенческий анализ и постоянно меняющиеся обфусцированные CSS-классы. Обычный requests блокируется с первого же запроса. Слоистая антиблокировочная стратегия из этого гайда — curl_cffi для имитации TLS, реалистичные заголовки, случайные задержки и residential proxies — это то, что работает в 2025 году.
Yelp Fusion API лучше, чем парсинг?
Зависит от задачи. API официальный и с низким риском, но он отдаёт только 3 фрагмента отзывов по ~160 символов каждый, ограничивает поиск 240 результатами и стоит от $29 в месяц. Если тебе нужен полный текст отзывов, метаданные или больше нескольких сотен записей в день, парсинг — единственный вариант.
Как парсить отзывы Yelp на Python?
Используй curl_cffi с impersonate="chrome131", чтобы получить страницу компании, затем извлеки закодированный business ID из <meta name="yelp-biz-id"> и отправь POST-запрос на https://www.yelp.com/gql/batch с операцией GetBusinessReviewFeed, используя пагинацию через base64-кодированный cursor after. Пошаговый код есть выше в разделе с туториалом. Репозиторий Scrapfly Yelp scraper repo тоже хороший пример реализации.
Можно ли парсить Yelp без кода?
Да — AI Web Scraper от Thunderbit уже поставляется с готовыми шаблонами для Yelp business и reviews. Открой страницу Yelp, нажми AI Suggest Fields, затем Scrape. Экспорт в Google Sheets, Excel, Airtable и Notion бесплатен на любом тарифе, включая free plan.
Узнать больше


