Как скрапить отзывы и зарплаты Glassdoor в 2026: полное руководство
Важное предупреждение. Эта статья описывает сбор только публично доступных данных Glassdoor — страниц компаний и усечённых отзывов, видимых без входа в систему. Сбор данных за стеной авторизации нарушает Условия использования Glassdoor и может подпадать под действие Закона о компьютерном мошенничестве и злоупотреблениях (CFAA, 18 U.S.C. § 1030) в США и GDPR в ЕС. Если вы обрабатываете персональные данные сотрудников из ЕС, вам необходимо правовое основание по GDPR. Информация ниже предоставлена в образовательных целях для HR-аналитиков и инженеров данных рынка труда.
Если вы HR-аналитик или data engineer, вам вероятно нужен систематический способ собирать отзывы компаний, рейтинги и данные о зарплатах с Glassdoor для анализа рынка труда. Проблема: Glassdoor защищён DataDome и Cloudflare Bot Management, а полные данные о зарплатах скрыты за логином. В этом руководстве мы разберём, как скрапить Glassdoor легально и эффективно — через BFF GraphQL эндпоинты, TLS-имперсонацию и ротацию residential-прокси.
Что доступно без логина, а что — за стеной авторизации
Glassdoor разделяет данные на два уровня доступа. Понимание этой границы критично для легального скрапинга:
Публичные данные (без авторизации)
- Страницы обзоров компаний:
/Reviews/<company>-Reviews-E<id>.htm— название, рейтинг, отрасль, штаб-квартира, количество отзывов. - Усечённые отзывы: первые ~2-3 предложения полей «Плюсы» и «Минусы», заголовок должности, общий рейтинг (ratingOverall). Полный текст доступен только после входа.
- Базовая статистика: средний рейтинг, распределение звёзд, количество отзывов по категориям.
Данные за логином (не скрапить без авторизации)
- Полные тексты отзывов с детальными комментариями.
- Детальные разбивки зарплат по должностям, локациям и опыту.
- Отзывы о собеседованиях с детальным описанием процесса.
- Фотографии офисов и расширенные профили сотрудников.
Правило: Если данные видны только после входа в аккаунт Glassdoor — не скрапите их автоматически. Это нарушает ToS и создаёт юридические риски. Используйте официальное API Glassdoor или партнёрскую программу для легального доступа.
Anti-bot стек Glassdoor: DataDome + Cloudflare
Glassdoor использует двухуровневую защиту от ботов. Понимание того, как работают эти системы, определяет архитектуру вашего скрапера.
DataDome
DataDome — это специализированный anti-bot сервис, который анализирует:
- IP-репутацию: дата-центр IP-адреса помечаются с высокой вероятностью блокировки. Residential-адреса проходят проверку гораздо легче.
- Поведенческие сигналы: скорость запросов, последовательность навигации, наличие JavaScript-выполнения.
- Cookies и токены: DataDome выдаёт cookie
datadomeпри первом запросе. Если этот cookie отсутствует или невалиден при последующих запросах — вы получаете challenge. - Заголовки браузера: наличие и порядок заголовков, User-Agent, Accept-Language, Sec-Fetch-* заголовки.
Cloudflare Bot Management
Поверх DataDome Glassdoor использует Cloudflare Bot Management, который добавляет:
- JS Challenge: браузер должен выполнить JavaScript для получения clearance cookie. Обычный
requestsилиcurlздесь не справится. - TLS-фингерпринтинг: Cloudflare анализирует JA3/JA4 хэш TLS-рукопожатия. Python
requestsиспользует TLS-библиотеку, чей отпечаток отличается от Chrome или Firefox — это мгновенно выдаёт бота. - HTTP/2 фингерпринтинг: порядок псевдо-заголовков и настройки фреймов также анализируются.
Почему нужен curl_cffi
Библиотека curl_cffi решает проблему TLS-фингерпринтинга, используя libcurl с компиляцией BoringSSL — той же TLS-библиотеки, что и Chrome. Это позволяет вашему Python-коду представляться настоящим Chrome с корректным JA3/JA4 отпечатком:
from curl_cffi import requests
# Имперсонация Chrome 120
response = requests.get(
"https://www.glassdoor.com/Reviews/Google-Reviews-E9079.htm",
impersonate="chrome120",
proxies={
"https": "http://user-country-US:password@gate.proxyhat.com:8080"
}
)
print(response.status_code) # 200 вместо 403
Без TLS-имперсонации даже с residential-прокси вы получите 403 Forbidden от Cloudflare в ~80% случаев, по нашим наблюдениям.
Сравнение типов прокси для скрапинга Glassdoor
| Тип прокси | Проходимость DataDome | Скорость | Цена | Рекомендация для Glassdoor |
|---|---|---|---|---|
| Residential (ротация) | Высокая — реальные ISP-адреса | Средняя (200-800ms) | $$ | Оптимальный выбор |
| Mobile | Очень высокая — мобильные операторы | Низкая (500-2000ms) | $$$ | Для сложных случаев |
| Datacenter | Низкая — DataDome блокирует ~90% | Высокая (50-100ms) | $ | Не рекомендуется |
| ISP (статичные residential) | Средняя — выше datacenter, ниже residential | Высокая (50-150ms) | $$ | Для малых объёмов |
BFF GraphQL эндпоинты Glassdoor
Glassdoor использует внутренний BFF (Backend-for-Frontend) слой на основе GraphQL для рендеринга страниц отзывов. Эти эндпоинты не задокументированы публично, но возвращают структурированный JSON вместо HTML — что значительно упрощает парсинг.
Ключевые эндпоинты
/bff/graphql— основной BFF GraphQL эндпоинт для отзывов./graph— альтернативный GraphQL эндпоинт (зависит от версии фронтенда).
Обязательные заголовки
Для запросов к BFF GraphQL необходимо передавать:
gd-csrf-token— CSRF-токен, который можно извлечь из метаданных страницы или cookies. Обычно находится в<meta name="gd-csrf-token" content="...">или в инициализационном JavaScript.Content-Type: application/json— для POST-запросов.gd-csrf-token— должен соответствовать токену, выданному при загрузке страницы.- Стандартные браузерные заголовки:
User-Agent,Accept,Accept-Language,Referer.
Пример GraphQL-запроса для отзывов
{
"operationName": "EmployerReviews",
"variables": {
"employerId": 9079,
"page": 1,
"pageSize": 10,
"filter": null
},
"query": "query EmployerReviews($employerId: Long!, $page: Int, $pageSize: Int) { ... }"
}
Почему residential-прокси побеждают IP-скоринг DataDome
DataDome присваивает каждому IP-адресу риск-score на основе:
- ASN (Autonomous System Number) — residential-адреса имеют ASN реальных ISP (Comcast, Verizon, Deutsche Telekom).
- Истории IP — был ли он замечен в бот-активности.
- Географической согласованности — соответствует ли IP заявленной локации браузера.
Дата-центр IP-адреса (AWS, GCP, DigitalOcean) мгновенно получают высокий risk-score. Residential-прокси от ProxyHat используют реальные ISP-адреса, что снижает риск-score до уровня обычного пользователя. Ротация IP между запросами предотвращает накопление подозрительной активности на одном адресе.
Практический пример: парсер отзывов Glassdoor на Python
Ниже — рабочий пример скрапинга отзывов через BFF GraphQL эндпоинт с использованием ProxyHat residential-прокси и curl_cffi для TLS-имперсонации.
Установка зависимостей
pip install curl_cffi
Скрапер отзывов
import json
import time
import random
from curl_cffi import requests
# ProxyHat residential proxy с ротацией
PROXY_URL = "http://user-country-US-session-rev001:PASSWORD@gate.proxyhat.com:8080"
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": "application/json",
"Accept-Language": "en-US,en;q=0.9",
"Content-Type": "application/json",
"Referer": "https://www.glassdoor.com/Reviews/Google-Reviews-E9079.htm",
"Origin": "https://www.glassdoor.com",
}
def get_csrf_token(employer_id: int, session_id: str) -> str:
"""Получаем gd-csrf-token из HTML страницы компании."""
proxy = f"http://user-country-US-session-{session_id}:PASSWORD@gate.proxyhat.com:8080"
url = f"https://www.glassdoor.com/Reviews/Google-Reviews-E{employer_id}.htm"
resp = requests.get(
url,
impersonate="chrome120",
headers={
"User-Agent": HEADERS["User-Agent"],
"Accept": "text/html",
"Accept-Language": "en-US,en;q=0.9",
},
proxies={"https": proxy, "http": proxy},
)
# Извлекаем CSRF-токен из meta-тега
import re
match = re.search(
r'gd-csrf-token[^>]*content="([^"]+)"',
resp.text
)
if not match:
raise ValueError("CSRF token not found")
return match.group(1)
def fetch_reviews_bff(employer_id: int, page: int, csrf_token: str, session_id: str):
"""Запрос к BFF GraphQL эндпоинту для отзывов."""
proxy = f"http://user-country-US-session-{session_id}:PASSWORD@gate.proxyhat.com:8080"
payload = {
"operationName": "EmployerReviews",
"variables": {
"employerId": employer_id,
"page": page,
"pageSize": 10,
"filter": None,
},
"query": """
query EmployerReviews($employerId: Long!, $page: Int, $pageSize: Int) {
employer(id: $employerId) {
reviews(page: $page, pageSize: $pageSize) {
reviews {
ratingOverall
pros
cons
jobTitle
date
}
pagination {
cursor
hasNextPage
}
}
}
}
""",
}
headers = HEADERS.copy()
headers["gd-csrf-token"] = csrf_token
resp = requests.post(
"https://www.glassdoor.com/bff/graphql",
json=payload,
headers=headers,
impersonate="chrome120",
proxies={"https": proxy, "http": proxy},
)
if resp.status_code == 403:
raise Exception("DataDome block detected — rotate session")
return resp.json()
def parse_review_node(node: dict) -> dict:
"""Извлекаем поля одного отзыва."""
return {
"ratingOverall": node.get("ratingOverall"),
"pros": node.get("pros", ""),
"cons": node.get("cons", ""),
"jobTitle": node.get("jobTitle", ""),
"date": node.get("date", ""),
}
# --- Основной цикл ---
employer_id = 9079 # Google
session_id = "rev-session-001"
csrf_token = get_csrf_token(employer_id, session_id)
print(f"CSRF token: {csrf_token[:20]}...")
all_reviews = []
page = 1
while True:
try:
data = fetch_reviews_bff(employer_id, page, csrf_token, session_id)
except Exception as e:
print(f"Block on page {page}: {e}")
# Меняем session_id для ротации IP
session_id = f"rev-session-{random.randint(1000, 9999)}"
csrf_token = get_csrf_token(employer_id, session_id)
time.sleep(5)
continue
reviews = data.get("data", {}).get("employer", {}).get("reviews", {})
review_list = reviews.get("reviews", [])
if not review_list:
break
for node in review_list:
parsed = parse_review_node(node)
all_reviews.append(parsed)
print(f" [{parsed['ratingOverall']}★] {parsed['jobTitle']} — {parsed['pros'][:60]}...")
pagination = reviews.get("pagination", {})
if not pagination.get("hasNextPage"):
break
page += 1
time.sleep(random.uniform(1.5, 3.0)) # Пейсинг: 1 запрос в ~2 секунды
print(f"\nВсего собрано отзывов: {len(all_reviews)}")
Разбор кода
- curl_cffi с
impersonate="chrome120"— обеспечивает корректный TLS-отпечаток Chrome 120, проходящий Cloudflare. - ProxyHat residential-прокси —
gate.proxyhat.com:8080с флагомsession-rev001для липкой сессии. Это сохраняет cookies DataDome валидными между запросами. - gd-csrf-token — извлекается из HTML страницы компании перед GraphQL-запросом.
- Поля отзыва —
ratingOverall(общий рейтинг),pros(плюсы),cons(минусы),jobTitle(должность). - Пейсинг — случайная задержка 1.5-3.0 секунды между запросами для имитации человеческого поведения.
Пример на Node.js
Для JavaScript-разработчиков — аналогичный подход с использованием undici и ProxyHat:
import { request } from "undici";
const PROXY_URL = "http://user-country-US-session-rev001:PASSWORD@gate.proxyhat.com:8080";
const EMPLOYER_ID = 9079;
async function fetchReviews(page) {
const payload = {
operationName: "EmployerReviews",
variables: { employerId: EMPLOYER_ID, page, pageSize: 10 },
query: `query EmployerReviews($employerId: Long!, $page: Int, $pageSize: Int) {
employer(id: $employerId) {
reviews(page: $page, pageSize: $pageSize) {
reviews { ratingOverall pros cons jobTitle date }
pagination { cursor hasNextPage }
}
}
}`,
};
const resp = await fetch("https://www.glassdoor.com/bff/graphql", {
method: "POST",
headers: {
"Content-Type": "application/json",
"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36",
"gd-csrf-token": CSRF_TOKEN,
"Referer": "https://www.glassdoor.com/",
},
body: JSON.stringify(payload),
// В продакшене используйте прокси-агент с undici ProxyAgent
});
if (resp.status === 403) throw new Error("DataDome block — rotate IP");
return resp.json();
}
const data = await fetchReviews(1);
const reviews = data.data.employer.reviews.reviews;
reviews.forEach(r => {
console.log(`[${r.ratingOverall}★] ${r.jobTitle}: ${r.pros.slice(0, 60)}...`);
});
Пагинация, липкие сессии и логика повторных попыток
Курсоры пагинации
BFF GraphQL эндпоинт возвращает курсор пагинации в поле pagination.cursor вместе с флагом hasNextPage. Используйте курсор вместо номера страницы, когда это возможно — это более надёжный способ навигации:
# Использование курсора вместо номера страницы
variables = {
"employerId": employer_id,
"cursor": "eyJwYWdlIjoxMH0=", # base64-кодированный курсор
"pageSize": 10,
}
Липкие сессии (sticky sessions)
DataDome выдаёт cookie datadome при первом запросе. Этот cookie привязан к IP-адресу. Если вы ротируете IP между запросами в рамках одной сессии, DataDome видит несоответствие cookie и IP — и блокирует запрос. Решение: используйте липкую сессию через флаг session- в username ProxyHat:
# Липкая сессия: один IP на все запросы в рамках сессии
proxy = "http://user-country-US-session-glassdoor-001:PASSWORD@gate.proxyhat.com:8080"
# Ротация: меняем session-ID для нового IP
proxy = "http://user-country-US-session-glassdoor-002:PASSWORD@gate.proxyhat.com:8080"
Стратегия: используйте одну сессию для сбора отзывов одной компании (10-50 запросов), затем ротируйте. Если получаете 403 — немедленно ротируйте сессию.
Пейсинг и лимиты
- Базовый темп: 1 запрос в 2-3 секунды на одну сессию.
- Параллельные сессии: не более 5-10 одновременно с разных IP.
- Суточный лимит: ~500-1000 запросов на одну сессию перед обязательной ротацией.
- Джиттер: случайная задержка
random.uniform(1.5, 3.0)предотвращает обнаружение по регулярности.
Логика повторных попыток при challenge
def fetch_with_retry(employer_id, page, max_retries=3):
for attempt in range(max_retries):
try:
session_id = f"rev-{attempt}-{random.randint(1000, 9999)}"
csrf = get_csrf_token(employer_id, session_id)
data = fetch_reviews_bff(employer_id, page, csrf, session_id)
return data
except Exception as e:
print(f"Попытка {attempt + 1} не удалась: {e}")
time.sleep(5 * (attempt + 1)) # Экспоненциальная задержка
raise Exception(f"Все {max_retries} попыток исчерпаны")
Типичные ошибки и edge cases
1. Использование обычного requests вместо curl_cffi
Стандартная библиотека requests использует urllib3/ OpenSSL, чей JA3-отпечаток отличается от Chrome. Cloudflare Bot Management detects это в ~90% случаев. Решение: всегда используйте curl_cffi с impersonate="chrome120" или аналогичное.
2. Игнорирование gd-csrf-token
Без валидного gd-csrf-token BFF GraphQL эндпоинт возвращает 403 или пустой ответ. Токен необходимо извлекать заново при каждой новой сессии — он привязан к cookies.
3. Ротация IP без обновления cookies
Если вы меняете IP, но не обновляете cookies DataDome, вы получаете блокировку. При ротации сессии: получите новый CSRF-токен и новые cookies через GET-запрос к HTML-странице.
4. Слишком высокая скорость запросов
Даже с residential-прокси и TLS-имперсонацией, 10+ запросов в секунду с одного IP вызовут suspicion. DataDome анализирует поведенческие паттерны, не только IP-репутацию.
5. Попытка скрапить зарплаты без логина
Полные данные о зарплатах Glassdoor — за стеной авторизации. GraphQL-запросы для зарплат требуют аутентифицированной сессии. Не пытайтесь обойти это — это нарушает ToS и CFAA.
Настройка ProxyHat для скрапинга Glassdoor
ProxyHat предоставляет residential-прокси с поддержкой липких сессий и геотаргетинга — идеальное сочетание для Glassdoor. Базовая настройка:
Параметры подключения
| Параметр | Значение |
|---|---|
| Gateway | gate.proxyhat.com |
| HTTP порт | 8080 |
| SOCKS5 порт | 1080 |
| Формат username | user-country-US-session-abc123 |
Геотаргетинг
Glassdoor показывает разные данные в зависимости от локации. Для скрапинга отзывов американских компаний используйте country-US. Для европейских компаний — country-DE, country-GB, country-FR и т.д. Подробности на странице локаций ProxyHat.
# США — для американских компаний
http://user-country-US-session-glassdoor-001:PASSWORD@gate.proxyhat.com:8080
# Германия — для европейских компаний
http://user-country-DE-session-glassdoor-002:PASSWORD@gate.proxyhat.com:8080
# Город-level таргетинг
http://user-country-US-city-newyork-session-gd-003:PASSWORD@gate.proxyhat.com:8080
SOCKS5 для повышенной анонимности
Если HTTP-прокси недостаточно, используйте SOCKS5:
socks5://user-country-US-session-glassdoor-001:PASSWORD@gate.proxyhat.com:1080
Дополнительные настройки и интеграции смотрите в официальной документации ProxyHat. Тарифные планы доступны на странице цен ProxyHat.
Этический скрапинг и когда использовать официальное API
Принципы этичного скрапинга Glassdoor
- Собирайте только агрегированные, неперсональные данные. Отзывы на Glassdoor анонимны, но заголовки должностей в сочетании с датами могут косвенно идентифицировать автора. Агрегируйте данные по компаниям и должностям, не сохраняйте индивидуальные комбинации.
- Не скрапите за логином. Полные тексты отзывов, детальные зарплаты и обзоры собеседований доступны только после входа. Сбор этих данных нарушает ToS и может нарушать CFAA.
- Соблюдайте robots.txt. Проверьте
https://www.glassdoor.com/robots.txtперед началом скрапинга. - GDPR для данных из ЕС. Если вы собираете отзывы сотрудников европейских компаний, персональные данные могут подпадать под GDPR. Убедитесь, что у вас есть правовое основание (legitimate interest) и вы не сохраняете данные, позволяющие идентифицировать конкретных лиц.
- Ограничьте частоту. Не перегружайте серверы Glassdoor. 1-2 запроса в секунду с ротацией — разумный максимум.
- Используйте данные ответственно. Не публикуйте собранные отзывы в открытом доступе — это нарушает ToS Glassdoor и авторские права.
Когда использовать официальное API вместо скрапинга
Glassdoor предлагает партнёрскую программу и API для легального доступа к данным. Официальное API — правильный выбор, если:
- Вам нужны данные о зарплатах с детальной разбивкой.
- Вы строите коммерческий продукт на данных Glassdoor.
- Вам нужна юридическая защита и гарантии точности данных.
- Ваш объём запросов превышает разумные пределы для скрапинга.
- Вы работаете с данными из ЕС и нуждаетесь в GDPR-совместимом доступе.
Скрапинг уместен для разовых аналитических задач, исследования рынка труда и прототипирования. Для продакшн-систем и коммерческих продуктов — используйте официальное API или лицензию на данные.
Key Takeaways
- Публичные данные только: страницы компаний и усечённые отзывы доступны без логина. Полные зарплаты и детальные отзывы — за стеной авторизации, не скрапите их.
- TLS-имперсонация обязательна: используйте
curl_cffiсimpersonate="chrome120"для обхода Cloudflare Bot Management. Обычныйrequestsблокируется в ~90% случаев.- BFF GraphQL удобнее HTML: эндпоинт
/bff/graphqlс заголовкомgd-csrf-tokenвозвращает структурированный JSON с полямиratingOverall,pros,cons,jobTitle.- Residential-прокси + липкие сессии: ProxyHat residential-прокси с флагом
session-сохраняют cookies DataDome валидными. Ротируйте сессию при 403.- Пейсинг 1 запрос / 2 секунды: с джиттером. Не более 5-10 параллельных сессий. ~500-1000 запросов на сессию перед ротацией.
- Этика и закон: только агрегированные неперсональные данные, соблюдайте ToS, CFAA и GDPR. Для коммерческого использования — официальное API.
FAQ
Можно ли скрапить Glassdoor без прокси?
Технически — да, для нескольких запросов. Но DataDome и Cloudflare заблокируют ваш IP после 5-10 запросов. Для любого объёма выше разового — residential-прокси обязательны.
Как часто нужно ротировать IP при скрапинге Glassdoor?
Используйте липкую сессию на 50-100 запросов, затем ротируйте. При получении 403 — ротируйте немедленно. Не используйте ротацию на каждый запрос — это нарушает cookies DataDome.
Законен ли скрапинг публичных отзывов Glassdoor?
Сбор публично доступных данных (без логина) в умеренных объёмах с соблюдением ToS и применимого законодательства (CFAA, GDPR) может быть законным. Однако Glassdoor ToS запрещает автоматизированный сбор. Консультируйтесь с юристом перед началом проекта.
Чем отличается BFF GraphQL от обычного парсинга HTML?
BFF GraphQL возвращает структурированный JSON — не нужно парсить HTML и зависеть от вёрстки. Но требуется gd-csrf-token и те же anti-bot обходы, что и для HTML.
Готовы начать? Изучите use-case скрапинга ProxyHat и тарифные планы для выбора подходящего residential-пакета. Для SERP-трекинга и мониторинга позиций также смотрите наш use-case SERP tracking.






