Важно: Эта статья посвящена доступу исключительно к публичным данным. Перед любым скрейпингом Yelp ознакомьтесь с Условиями использования Yelp. Несанкционированный доступ к данным может нарушать Закон о компьютерном мошенничестве и злоупотреблениях (CFAA, США) и Общий регламент по защите данных (GDPR, ЕС). Информация ниже предназначена для разработчиков, работающих с общедоступными страницами в рамках применимого законодательства.
Как скрейпить Yelp в 2026 году: обзор публичных данных и антибот-защиты
Yelp остаётся одним из крупнейших агрегаторов отзывов о местных бизнесах — более 250 млн отзывов по состоянию на 2024 год, согласно отчёту Yelp About. Для разработчиков, собирающих датасеты локальных бизнесов, Yelp представляет ценный источник структурированной информации: рейтинги, категории, часы работы, координаты и тексты отзывов.
Однако скрейпинг Yelp в 2026 году — это не простой HTTP-запрос. Платформа защищена PerimeterX (ныне HUMAN Security), использует TLS-фингерпринтинг и активно блокирует дата-центровые IP-адреса уже после нескольких запросов. В этом руководстве мы разберём, как скрейпить Yelp бизнес-листинги и отзывы, используя резидентные прокси с гео-таргетингом, и какие данные доступны без авторизации.
Что доступно без входа в систему
Без аккаунта Yelp вы можете получить доступ к следующим публичным данным на странице бизнеса /biz/<slug>:
- Название бизнеса, адрес, телефон, категория
- Общий рейтинг (1–5 звёзд) и количество отзывов
- Часы работы по дням недели
- Координаты (широта, долгота)
- Тексты отзывов с именем автора, датой, рейтингом и текстом
- Фотографии с подписями
Для сравнения, официальный Yelp Fusion API возвращает максимум 3 отзыва на бизнес-эндпоинте /reviews и требует регистрации приложения. Веб-страница Yelp показывает значительно больше отзывов через пагинацию, что делает веб-скрейпинг привлекательным для исследователей, нуждающихся в полных наборах отзывов.
Антибот-защита Yelp: PerimeterX/HUMAN и TLS-фингерпринтинг
Yelp использует несколько уровней защиты от автоматизированного доступа:
PerimeterX (HUMAN Security)
PerimeterX — это система антибот-защиты, которая устанавливает cookie _px3 и выполняет JavaScript sensor challenge — скрипт, собирающий данные о браузере: canvas fingerprint, WebGL-параметры, тайминги событий мыши и клавиатуры, список плагинов. Если sensor data не проходит проверку, Yelp возвращает HTTP 403 или CAPTCHA-страницу.
Ключевая проблема для скрейперов: PerimeterX ведёт IP-reputation scoring. Дата-центровые IP-адреса (AWS, DigitalOcean, OVH) получают низкий reputation score и блокируются быстрее — часто после 5–15 запросов с одного дата-центрового IP. Резидентные IP-адреса от реальных интернет-провайдеров имеют значительно более высокий trust score.
TLS-фингерпринтинг (JA3/JA4)
Yelp также анализирует TLS Client Hello-пакет для определения типа клиента. Библиотеки вроде Python requests или urllib3 имеют характерные TLS-паттерны, отличающиеся от реальных браузеров. Это означает, что даже с правильными заголовками User-Agent, не-браузерный клиент может быть обнаружен по TLS-отпечатку.
Для обхода TLS-фингерпринтинга разработчики часто используют:
- curl-impersonate — модифицированный curl с TLS-отпечатком Chrome/Firefox
tls-client— Python-обёртка с настраиваемым JA3- Playwright/Puppeteer с
stealth-плагинами для полного браузерного рендеринга
CAPTCHA после нескольких запросов
Даже при правильной настройке заголовков, после нескольких десятков запросов с одного IP-адреса Yelp может показать CAPTCHA. Это типичный паттерн для PerimeterX: первый порог — soft challenge (JavaScript), второй — hard CAPTCHA. Стратегия ротации IP-адресов критически важна для поддержания пропускной способности.
Почему резидентные прокси с US-гео необходимы для Yelp
Для скрейпинга Yelp требуются резидентные прокси по двум причинам:
- IP-reputation: Резидентные IP-адреса от реальных ISP (Comcast, AT&T, Verizon) имеют высокий trust score в PerimeterX, что снижает частоту блокировок.
- Локализация результатов: Yelp возвращает разные бизнес-листинги в зависимости от гео-расположения запроса. Для сбора данных о ресторанах в Остине, вам нужен IP из США, желательно из Техаса.
Дата-центровые прокси могут работать для единичных запросов, но не выдерживают массовый сбор данных. Мобильные прокси — отличная альтернатива с ещё более высоким trust score, но они дороже и медленнее.
| Тип прокси | Trust score PerimeterX | Скорость | Стоимость | Подходит для Yelp |
|---|---|---|---|---|
| Дата-центровые | Низкий | Высокая | Низкая | Только единичные запросы |
| Резидентные | Высокий | Средняя | Средняя | Оптимальный выбор |
| Мобильные | Очень высокий | Низкая | Высокая | Для сложных случаев |
Практическая реализация: Python с ProxyHat
Настройка прокси через ProxyHat gateway
ProxyHat предоставляет единый gateway для резидентных прокси с гибким гео-таргетингом. Формат username поддерживает флаги страны, города и сессии:
# Гео-таргетинг: США, Остин
http://user-country-US-city-austin:pass@gate.proxyhat.com:8080
# Sticky-сессия для пагинации
http://user-country-US-city-austin-session-abc123:pass@gate.proxyhat.com:8080
# Простая ротация (новый IP на каждый запрос)
http://user-country-US:pass@gate.proxyhat.com:8080
Пример 1: Сбор отзывов через review_feed и __INITIAL_STATE__
Yelp встраивает начальное состояние приложения в тег <script> с переменной __INITIAL_STATE__. Это JSON-объект, содержащий бизнес-данные и первые отзывы. Для пагинации отзывов Yelp использует внутренний endpoint /review_feed с параметром rl (review language) и sort_by.
import requests
import json
import re
import time
import random
PROXY = "http://user-country-US-city-austin-session-yelp001:pass@gate.proxyhat.com:8080"
PROXIES = {
"http": PROXY,
"https": PROXY,
}
HEADERS = {
"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36",
"Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8",
"Accept-Language": "en-US,en;q=0.9",
"Accept-Encoding": "gzip, deflate, br",
"Connection": "keep-alive",
"Upgrade-Insecure-Requests": "1",
}
USER_AGENTS = [
"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36",
"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36",
"Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36",
]
def scrape_yelp_business(biz_slug):
"""Собирает бизнес-данные и отзывы со страницы /biz/<slug>"""
url = f"https://www.yelp.com/biz/{biz_slug}"
headers = HEADERS.copy()
headers["User-Agent"] = random.choice(USER_AGENTS)
try:
resp = requests.get(url, headers=headers, proxies=PROXIES, timeout=30)
if resp.status_code == 403:
print(f"[!] Заблокировано PerimeterX (403) для {biz_slug}")
return None
if resp.status_code != 200:
print(f"[!] HTTP {resp.status_code} для {biz_slug}")
return None
# Извлекаем __INITIAL_STATE__
match = re.search(
r"__INITIAL_STATE__=({.*?});</script>",
resp.text,
re.DOTALL
)
if not match:
print(f"[!] __INITIAL_STATE__ не найден для {biz_slug}")
return None
state = json.loads(match.group(1))
# Извлекаем бизнес-данные
biz_data = state.get("biz", {}).get(biz_slug, {})
business = {
"name": biz_data.get("name", ""),
"rating": biz_data.get("rating", 0),
"review_count": biz_data.get("reviewCount", 0),
"categories": [c.get("title", "") for c in biz_data.get("categories", [])],
"address": biz_data.get("location", {}).get("displayAddress", []),
"hours": biz_data.get("hours", []),
"coordinates": biz_data.get("latitude"), biz_data.get("longitude"),
}
# Извлекаем первые отзывы
reviews = state.get("review", {}).get("feed", {}).get("reviews", [])
parsed_reviews = []
for r in reviews[:3]: # первые 3 отзыва из __INITIAL_STATE__
parsed_reviews.append({
"author": r.get("user", {}).get("markupDisplayName", ""),
"rating": r.get("rating", 0),
"date": r.get("localizedDate", ""),
"text": r.get("comment", {}).get("text", "")[:200], # truncated
})
business["reviews_sample"] = parsed_reviews
return business
except requests.exceptions.RequestException as e:
print(f"[!] Ошибка запроса: {e}")
return None
def scrape_review_feed(biz_slug, start=0, limit=20):
"""Собирает отзывы через review_feed endpoint (пагинация)"""
url = f"https://www.yelp.com/biz/{biz_slug}/review_feed"
params = {
"rl": "en",
"sort_by": "relevance_desc",
"start": start,
"limit": limit,
}
headers = HEADERS.copy()
headers["User-Agent"] = random.choice(USER_AGENTS)
headers["Accept"] = "application/json"
headers["X-Requested-With"] = "XMLHttpRequest"
try:
resp = requests.get(
url, headers=headers, params=params,
proxies=PROXIES, timeout=30
)
if resp.status_code != 200:
print(f"[!] review_feed вернул {resp.status_code}")
return []
data = resp.json()
reviews = data.get("reviews", [])
return [{
"author": r.get("user", {}).get("markupDisplayName", ""),
"rating": r.get("rating", 0),
"date": r.get("localizedDate", ""),
"text": r.get("comment", {}).get("text", "")[:200],
} for r in reviews]
except Exception as e:
print(f"[!] Ошибка review_feed: {e}")
return []
# Использование
if __name__ == "__main__":
# Шаг 1: бизнес-данные + первые отзывы
biz = scrape_yelp_business("house-of-prime-rib-san-francisco")
if biz:
print(json.dumps(biz, indent=2, ensure_ascii=False))
# Шаг 2: пагинация отзывов
all_reviews = biz.get("reviews_sample", [])
for offset in range(20, 200, 20):
print(f"[*] Загрузка отзывов {offset}–{offset+20}...")
batch = scrape_review_feed("house-of-prime-rib-san-francisco", start=offset)
if not batch:
break
all_reviews.extend(batch)
time.sleep(random.uniform(2.0, 5.0)) # рандомная задержка
print(f"\n[+] Всего собрано отзывов: {len(all_reviews)}")
В этом примере мы используем sticky-сессию (session-yelp001), чтобы все запросы в рамках пагинации шли с одного IP-адреса. Это важно: если IP меняется между запросами /biz/<slug> и /review_feed, PerimeterX может заподозрить несоответствие сессии.
Пример 2: Node.js через SOCKS5
Для Node.js можно использовать SOCKS5-агент через ProxyHat на порту 1080:
const { SocksProxyAgent } = require('socks-proxy-agent');
const axios = require('axios');
const SOCKS5_PROXY = 'socks5://user-country-US-city-austin-session-node01:pass@gate.proxyhat.com:1080';
const agent = new SocksProxyAgent(SOCKS5_PROXY);
const USER_AGENTS = [
'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36',
'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36',
];
async function scrapeYelpBusiness(bizSlug) {
const url = `https://www.yelp.com/biz/${bizSlug}`;
const ua = USER_AGENTS[Math.floor(Math.random() * USER_AGENTS.length)];
try {
const resp = await axios.get(url, {
httpAgent: agent,
httpsAgent: agent,
timeout: 30000,
headers: {
'User-Agent': ua,
'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8',
'Accept-Language': 'en-US,en;q=0.9',
'Accept-Encoding': 'gzip, deflate, br',
'Connection': 'keep-alive',
},
});
if (resp.status === 403) {
console.error(`[!] Заблокировано PerimeterX (403)`);
return null;
}
// Извлекаем __INITIAL_STATE__
const match = resp.data.match(/__INITIAL_STATE__=({.*?});<\/script>/s);
if (!match) {
console.error('[!] __INITIAL_STATE__ не найден');
return null;
}
const state = JSON.parse(match[1]);
const bizData = state?.biz?.[bizSlug] || {};
const reviews = state?.review?.feed?.reviews || [];
return {
name: bizData.name || '',
rating: bizData.rating || 0,
reviewCount: bizData.reviewCount || 0,
categories: (bizData.categories || []).map(c => c.title || ''),
reviewsSample: reviews.slice(0, 3).map(r => ({
author: r?.user?.markupDisplayName || '',
rating: r?.rating || 0,
text: (r?.comment?.text || '').substring(0, 200),
})),
};
} catch (err) {
console.error(`[!] Ошибка: ${err.message}`);
return null;
}
}
// Использование
(async () => {
const result = await scrapeYelpBusiness('house-of-prime-rib-san-francisco');
console.log(JSON.stringify(result, null, 2));
})();
Пагинация, rate-limit pacing и sticky-сессии
Пагинация отзывов
Yelp загружает отзывы асинхронно через /review_feed. Параметр start управляет смещением, limit — количеством (обычно 20). Максимальная глубина пагинации составляет около 1000 отзывов на бизнес — после этого Yelp может перестать возвращать данные.
Rate-limit pacing
PerimeterX отслеживает частоту запросов с одного IP. Рекомендуемые темпы:
- 1 запрос каждые 3–5 секунд с одного sticky-IP для безопасного режима
- Не более 100 запросов с одной сессии перед ротацией
- Случайные задержки (jitter) — избегайте равномерных интервалов, которые легко детектируются
# Паттерн безопасного rate-limiting
import random
import time
def safe_delay():
"""Случайная задержка 2–6 секунд между запросами"""
delay = random.uniform(2.0, 6.0)
time.sleep(delay)
def rotate_session():
"""Генерирует новый session ID для ротации IP"""
import uuid
return f"yelp-{uuid.uuid4().hex[:8]}"
# Ротация сессии каждые 50 запросов
request_count = 0
for biz_slug in business_slugs:
if request_count % 50 == 0:
session_id = rotate_session()
proxy = f"http://user-country-US-city-austin-session-{session_id}:pass@gate.proxyhat.com:8080"
scrape_yelp_business(biz_slug)
safe_delay()
request_count += 1
Sticky-сессии для пагинации
При сборе всех отзывов для одного бизнеса используйте одну sticky-сессию. Меняйте сессию только при переходе к следующему бизнесу. Это имитирует поведение реального пользователя, просматривающего отзывы одного заведения.
# Sticky-сессия: один бизнес = одна сессия
session_id = f"biz-{biz_slug}-001"
proxy = f"http://user-country-US-city-austin-session-{session_id}:pass@gate.proxyhat.com:8080"
# Все запросы пагинации идут через один IP
for offset in range(0, 500, 20):
reviews = scrape_review_feed(biz_slug, start=offset)
safe_delay()
Ротация User-Agent
PerimeterX анализирует заголовки запроса. Использование одного User-Agent для всех запросов создаёт детектируемый паттерн. Ротация между 5–10 актуальными браузерными User-Agent снижает риск:
- Используйте только актуальные версии Chrome, Firefox, Safari
- Согласовывайте User-Agent с другими заголовками (Sec-CH-UA для Chrome)
- Избегайте редких или устаревших User-Agent
Типичные ошибки и edge cases
1. Игнорирование cookie _px3
PerimeterX устанавливает cookie _px3 при первом визите. Если ваш скрейпер не сохраняет и не отправляет этот cookie в последующих запросах, PerimeterX будет повторно инициировать sensor challenge, что быстро приводит к блокировке. Используйте requests.Session() для автоматического управления cookie.
2. Слишком высокая частота запросов
Даже с резидентными прокси, запросы без задержек вызовут блокировку. PerimeterX анализирует не только IP, но и поведенческие паттерны. Равномерные интервалы в 1 секунду так же подозрительны, как и отсутствие задержек.
3. Несоответствие гео и бизнеса
Если вы скрейпите бизнесы в Сан-Франциско через IP из Нью-Йорка, Yelp может вернуть другой набор результатов или показать предупреждение. Используйте гео-таргетинг по городу: city-san-francisco для бизнесов в SF.
4. Игнорирование robots.txt
Проверьте robots.txt Yelp перед скрейпингом. Хотя не все пути закрыты, уважение к директивам robots.txt — это хорошая практика и часть этического скрейпинга.
Настройка ProxyHat для скрейпинга Yelp
ProxyHat предоставляет резидентные прокси с гибким гео-таргетингом по странам и городам. Для скрейпинга Yelp рекомендуется:
- Используйте резидентные прокси с US-гео:
user-country-US-city-san-francisco - Включайте sticky-сессии для пагинации:
session-{id} - Ротируйте сессию каждые 50–100 запросов
- Используйте SOCKS5 (порт 1080) для Node.js-приложений
Подробная документация доступна на docs.proxyhat.com. Цены на резидентные прокси — на странице тарифов ProxyHat. Полный список доступных локаций — на странице локаций ProxyHat.
Дополнительные материалы по веб-скрейпингу доступны в нашем руководстве по веб-скрейпингу и руководстве по SERP-трекингу.
Этический скрейпинг: когда использовать официальные API
Скрейпинг публичных данных — это серая зона. Перед началом сбора данных с Yelp задайте себе следующие вопросы:
- Доступны ли данные без входа? Если данные требуют авторизации, не пытайтесь обойти это — это нарушает ToS и может подпадать под CFAA.
- Содержат ли данные персональную информацию? Имена авторов отзывов, их фотографии и профили — это персональные данные по GDPR. Избегайте сбора таких данных или анонимизируйте их.
- Покрывает ли Fusion API ваши нужды? Если вам нужны базовые бизнес-данные и до 3 отзывов на бизнес, Fusion API — более надёжный и легальный путь.
- Уважаете ли вы robots.txt? Директивы robots.txt — это не юридическое требование, но их соблюдение — стандарт индустрии.
Рекомендация: Если Yelp Fusion API покрывает ваши потребности (бизнес-поиск, базовая информация, 3 отзыва), используйте его. Это надёжнее, быстрее и юридически безопаснее. Веб-скрейпинг оправдан, когда вам нужны полные наборы отзывов для исследовательских целей, анализ тональности или обучение ML-моделей — но только с публичных страниц и в рамках применимого законодательства.
Key Takeaways
- Публичные данные Yelp: бизнес-профили, рейтинги, категории, часы работы и тексты отзывов доступны без входа на
/biz/<slug>. Fusion API ограничен 3 отзывами на бизнес.- Антибот-защита: PerimeterX/HUMAN использует cookie
_px3, JavaScript sensor challenge и TLS-фингерпринтинг. Дата-центровые IP блокируются после 5–15 запросов.- Резидентные прокси с US-гео: необходимы для обхода IP-reputation scoring и получения локализованных бизнес-результатов. Используйте
country-US-city-austinдля гео-таргетинга.- Sticky-сессии: используйте одну сессию для всех запросов пагинации одного бизнеса, ротируйте каждые 50–100 запросов.
- Rate-limit pacing: случайные задержки 2–6 секунд, ротация User-Agent, не более 100 запросов на сессию.
- Этика и закон: уважайте ToS Yelp, robots.txt и GDPR. Избегайте данных, требующих авторизации. Рассмотрите Fusion API, если он покрывает ваши нужды.
FAQ
Что такое скрейпинг Yelp бизнес-листингов и отзывов?
Скрейпинг Yelp — это автоматизированный сбор публично доступных данных с веб-страниц Yelp: названий бизнесов, рейтингов, категорий, часов работы и текстов отзывов. В отличие от официального Fusion API, который возвращает максимум 3 отзыва на бизнес, веб-скрейпинг позволяет собирать полные наборы отзывов через пагинацию endpoint /review_feed. Данные встраиваются в страницу в виде JSON-объекта __INITIAL_STATE__.
Почему для скрейпинга Yelp важны прокси?
Yelp защищён PerimeterX (HUMAN Security), который блокирует дата-центровые IP-адреса после 5–15 запросов из-за низкого IP-reputation score. Резидентные прокси с IP-адресами реальных интернет-провайдеров имеют высокий trust score и значительно реже блокируются. Кроме того, гео-таргетинг прокси по США и конкретным городам необходим для получения локализованных бизнес-результатов, так как Yelp возвращает разные данные в зависимости от гео-расположения запроса.
Какой тип прокси лучше всего подходит для скрейпинга Yelp?
Резидентные прокси с гео-таргетингом по США — оптимальный выбор для скрейпинга Yelp. Они обеспечивают высокий IP-reputation score в PerimeterX, поддерживают гео-локализацию по городам (например, city-san-francisco) и позволяют использовать sticky-сессии для пагинации отзывов. Мобильные прокси имеют ещё более высокий trust score, но они дороже и медленнее. Дата-центровые прокси не рекомендуются — они блокируются практически сразу.
Как избежать блокировок при скрейпинге Yelp?
Используйте резидентные прокси с US-гео и sticky-сессиями, поддерживайте случайные задержки 2–6 секунд между запросами, ротируйте User-Agent между 5–10 актуальными браузерными строками, сохраняйте cookie _px3 через requests.Session(), и ротируйте сессию каждые 50–100 запросов. Избегайте равномерных интервалов между запросами — PerimeterX детектирует паттерны. При получении HTTP 403 сделайте паузу 10–15 минут и смените сессию.
Можно ли скрейпить Yelp легально?
Скрейпинг публично доступных данных (без входа в систему) с Yelp технически возможен, но юридическая ситуация зависит от юрисдикции. В США дело hiQ v. LinkedIn установило прецедент, что скрейпинг публичных данных может не нарушать CFAA, однако условия использования Yelp могут запрещать автоматизированный доступ. В ЕС сбор персональных данных (имена авторов отзывов) регулируется GDPR. Рекомендуется использовать официальный Fusion API, где это возможно, и консультироваться с юристом перед масштабным сбором данных.






