Если твой парсер Glassdoor отлично работал в 2022 году, а теперь возвращает одни 403, ты не одинок. На форумах снова и снова всплывает один и тот же вопрос: «Кто-нибудь знает, почему этот парсер больше не работает?»
Короткий ответ: Glassdoor полностью поменял правила игры. В июле 2025 года Recruit Holdings включила Glassdoor в экосистему Indeed, уволила 1 300 сотрудников и усилила антибот-защиту до такой степени, что обычные скрипты на Selenium и requests блокируются ещё до загрузки первого байта HTML. По состоянию на февраль 2026 года вход в Glassdoor полностью проходит через Indeed Login — так что любой туториал, где жёстко прописана отдельная форма входа Glassdoor, уже сломан на уровне архитектуры. При этом платформа всё ещё хранит более 180 миллионов отзывов, зарплат и инсайтов по 2,5 миллионам работодателей. Эти данные невероятно ценны для HR-аналитики, оценки конкурентов и поиска потенциальных клиентов — если, конечно, до них удастся добраться. Это руководство — рабочая версия после всех этих изменений. Здесь разобраны все три типа данных Glassdoor: вакансии, отзывы и зарплаты — в одном месте. Я покажу Python-подход с рабочим кодом на 2025 год, объясню, что именно тебя блокирует и как это обойти, а также покажу no-code альтернатива для тех, кто не хочет заниматься инженерией.
Зачем собирать данные Glassdoor на Python в 2025 году?
Glassdoor — это не просто сайт с вакансиями. Это одна из самых богатых баз по компаниям в интернете: ею пользуется примерно треть компаний из Fortune 500, а ежемесячная аудитория составляет около 55 миллионов уникальных посетителей. Данные, которые лежат за этими страницами, влияют на реальные бизнес-решения сразу в нескольких командах.
Вот как разные отделы используют данные Glassdoor на практике:
| Сценарий | Какие данные нужны | Кому это полезно |
|---|---|---|
| Анализ зарплат | Диапазоны зарплат, размер выборки | HR, компенсации и льготы, операционные команды |
| Отслеживание найма конкурентов | Список вакансий, скорость публикаций | Продажи, стратегия, VC/корпоративное развитие |
| Мониторинг бренда работодателя | Текст отзывов, динамика рейтинга, одобрение CEO | HR, маркетинг, PR/коммуникации |
| Генерация лидов (растущие компании) | Вакансии + информация о компании | Команды продаж, SDR |
| Рыночные и академические исследования | Все три типа данных | Аналитики, консультанты, исследователи |

Когда BLS не смог опубликовать данные о вакансиях во время октябрьского шатдауна правительства США в 2025 году, собственная команда Glassdoor по экономическим исследованиям выпустила альтернативный отчёт по рынку труда на основе своей базы. Настолько серьёзно к этим данным теперь относятся аналитики уровня институтов.
Python по-прежнему остаётся языком по умолчанию: экосистема просто вне конкуренции — Playwright для автоматизации браузера, parsel/lxml для парсинга, curl_cffi для обхода TLS-фингерпринтинга, плюс огромное сообщество с рабочими паттернами. Проблема не в Python. Проблема в том, что Glassdoor стал намного сложнее для сбора.
Собирай данные Glassdoor с помощью AI Get Started Free
Если тебе нужен no-code вариант для извлечения данных Glassdoor, Thunderbit поможет собрать вакансии, отзывы и страницы с зарплатами без разработки и поддержки собственного Python-стека.
Какие данные Glassdoor вообще можно собрать?
Большинство туториалов покрывают только вакансии. Но по реальным запросам пользователей — если судить по форумам, GitHub issues и Reddit, за которыми я следил, — наибольший интерес вызывают два типа данных, которые почти никто не объясняет: отзывы и зарплаты. Ниже — полный разбор того, что реально можно извлечь по всем трём категориям.
Список вакансий
Самый доступный тип данных. Можно собрать: название вакансии, название компании, локацию, оценку зарплаты, рейтинг компании, дату публикации, бейдж easy apply и ссылку на вакансию. Списки вакансий частично доступны без входа, хотя после нескольких страниц Glassdoor может показать окно логина.
Отзывы о компании
Вот где начинается самое интересное для анализа бренда работодателя. Можно извлечь: общий рейтинг, подрейтинги (work-life balance, culture & values, diversity & inclusion, career opportunities, comp & benefits, senior management), текст плюсов, текст минусов, должность автора, дату отзыва и статус занятости. Полный текст отзыва защищён логином — ты увидишь лишь фрагмент, а полный блок pros/cons потребует авторизации.
Данные о зарплатах
Самый востребованный и одновременно самый проблемный тип данных. Можно извлечь: название должности, диапазон базовой ставки, общий диапазон компенсации, количество отчётов по зарплате и локацию. Но страницы зарплат полностью закрыты логином, а иногда Glassdoor добавляет ещё и сценарий "contribute to unlock", где нужно сначала отправить свою зарплату, чтобы увидеть чужие. Ни один конкурентный туториал не даёт для этого рабочий код — мы это исправим.
Что требует входа, а что нет
Эта таблица спасёт тебя от неприятного сюрприза, когда нужная страница вернёт пустые данные:
| Тип данных | Доступно без входа? | Примечания |
|---|---|---|
| Заголовки вакансий и базовая информация | В основном да | После нескольких страниц может появиться всплывающее окно |
| Полное описание вакансии | Частично | Часто закрывается после 2–3 просмотров |
| Отзывы о компании (полный текст) | Нет — нужен вход | Видна только выдержка, полный текст закрыт |
| Данные о зарплатах | Нет — нужен вход | Может дополнительно требовать "contribute to unlock" |
Почему твой старый парсер Glassdoor, скорее всего, сломался

Скажу прямо: если ты копируешь код из туториала 2021–2023 года, он не заработает. Самый популярный старый Selenium-парсер Glassdoor на GitHub (MatthewChatham/glassdoor-review-scraper, около 1,4k звёзд) имеет 12+ открытых нерешённых проблем — в том числе "Glassdoor new UI design", "Cloudflare anti-bot protection" и "NoSuchElementException". Репозиторий фактически заброшен. Актор glassdoor-jobs-scraper у Apify помечен как DEPRECATED. ScrapeOps оценивает сложность скрапинга Glassdoor в 9/10 и сложность обхода защиты в 8/10.
Вот что изменилось и почему старый код больше не работает:
| Слой защиты | Что изменилось | Как это влияет на старые парсеры |
|---|---|---|
| Cloudflare Bot Management | С 2024 года ужесточён JA3/JA4-фингерпринтинг | Простые requests/Selenium-скрипты сразу получают 403 |
| Динамические CSS-классы | Имена классов рандомизируются при каждом билде | Старые CSS-селекторы из туториалов тихо перестают работать |
| Rate limiting + отслеживание сессий | Жёстче ограничения по IP и по сессии | Блокировка наступает уже после меньшего числа страниц |
| CAPTCHA-челленджи (вероятно Cloudflare Turnstile) | Появляются чаще, особенно при пагинации | Headless-браузеры провоцируют челленджи |
| Расширенная логин-стена | Больше типов страниц требует авторизацию | Страницы зарплат и отзывов возвращают пустые данные |
| Миграция на Indeed Login (февраль 2026) | Форма входа Glassdoor полностью заменена | Любой код, завязанный на старый DOM логина, мёртв |
В гайде Scrapfly за 2026 год есть прямое предупреждение: "Glassdoor is known for its high blocking rate, so if you get None values while running the Python code, it's likely you're getting blocked." А пост на DEV.to от марта 2026 года говорит ещё жёстче: "Simple HTTP requests with requests or httpx get blocked instantly."
Меры обхода, которые я покажу ниже — Patchright (stealth-версия Playwright), селекторы по data-test, ротация residential-прокси и авторизованные persistent sessions — как раз и рассчитаны на каждый из этих уровней защиты.
Glassdoor API или Python-скрапинг: сначала выбери правильный путь
Во многих обсуждениях на форумах спрашивают: "Может, просто использовать Glassdoor API?" — и ответ такой: не получится.
Старый Glassdoor Partner API закрыт для новых заявок. Портал разработчика формально ещё существует, но возвращает HTTP 403. Публичного endpoint’а для отзывов никогда не было — именно поэтому MatthewChatham и сделал свой парсер: "потому что у Glassdoor нет API для отзывов." И никакого пути миграции для отзывов или зарплат через Indeed Publisher API тоже нет.
Вот честное сравнение:
| Фактор | Glassdoor Partner API v1 | Python-скрапинг | Thunderbit (no-code) |
|---|---|---|---|
| Доступ | Закрыт для новых заявок | Открыт (нужно реализовать самому) | Расширение для Chrome |
| Список вакансий | Ограничен / уходит в архив | Доступен, но с усилиями | Доступен |
| Отзывы о компании | Публично никогда не было | Да (нужен вход) | Да (через Browser Mode) |
| Данные о зарплатах | Публично никогда не было | Да (нужен вход) | Да |
| Rate limits | Не документированы | Ты контролируешь частоту | По кредитной модели |
| Сложность настройки | Нельзя зарегистрировать новые приложения | От часов до дней | Около 2 минут |
| Нагрузка на поддержку | Н/Д | Высокая (изменения HTML ломают код) | Низкая (AI заново предлагает поля) |
Если тебе нужны отзывы или данные о зарплатах — а большинству читателей именно они и нужны — у тебя по сути остаются только Python-скрапинг или no-code инструмент.
Перед началом работы
- Сложность: средняя (нужно уверенно чувствовать себя в Python и терминале)
- Время: около 30–60 минут на полную настройку; затем примерно 10 минут на каждый тип данных
- Что понадобится:
- Python 3.10+ (рекомендуются 3.11 или 3.12)
- Установленный браузер Chrome
- Аккаунт Glassdoor (бесплатный — нужен для данных по зарплатам и отзывам)
- Rotating residential proxies (если нужно собирать больше нескольких страниц)
- Опционально: расширение Thunderbit для Chrome, если хочешь пойти без кода
Инструменты и библиотеки для сбора данных Glassdoor на Python в 2025 году
Ландшафт инструментов сильно изменился. Ниже — то, что реально работает против текущей защиты Glassdoor.
Почему Patchright — лучший выбор для Glassdoor
Patchright — это stealth-форк Playwright, который исправляет утечку Runtime.Enable в CDP, то есть конкретную техническую причину, почему обычный Playwright ломается на сайтах под Cloudflare. Он использует тот же API, что и Playwright, поэтому если ты умеешь работать с Playwright, ты поймёшь и Patchright. Текущая версия 1.58.2 (март 2026) активно поддерживается.
По сравнению с альтернативами:
- Обычный Playwright: Glassdoor обнаруживает его на странице входа из-за утечки Runtime.Enable
- Selenium + undetected-chromedriver: последний релиз undetected-chromedriver был в феврале 2024 года — это уже почти legacy. В бенчмарке Scrapfly он "failed on every domain in our test"
- requests + BeautifulSoup: не умеют рендерить JavaScript и сразу блокируются TLS-фингерпринтингом Cloudflare
- curl_cffi: отличный быстрый вариант (в 10–20 раз быстрее браузера), когда страницы отдают
__NEXT_DATA__прямо в исходном HTML, но он не справится с логином и промежуточными челленджами
Поддерживающие библиотеки
- parsel (1.11.0) или lxml (6.0.4): быстрый HTML/XPath-парсинг
- csv или pandas: экспорт данных
- asyncio: асинхронный скрапинг для более быстрой пагинации
Прокси: только residential
Cloudflare в Glassdoor очень агрессивно относится к datacenter ASN. Сообщается, что residential-прокси снижают долю блокировок с 20–30% до менее чем 5%. Стартовые цены — около $1.75/GB у IPRoyal (по акции) или $3.00/GB у Decodo. Для production-скрапинга закладывай $3–8/GB в зависимости от объёма.
Случайные паузы между запросами (минимум 3–8 секунд, 5–15 секунд для длинных прогонов) обязательны независимо от качества прокси.
Шаг 1: Настрой окружение Python
Создай папку проекта и установи рекомендуемый стек:
mkdir glassdoor-scraper && cd glassdoor-scraper
python3.11 -m venv .venv
source .venv/bin/activate
pip install --upgrade pip
# Основной стек
pip install patchright==1.58.2 parsel==1.11.0
# Установка бинарников браузера
patchright install chromium
# Опционально: быстрый путь для извлечения __NEXT_DATA__
pip install "curl_cffi==0.15.0"
Patchright должен скачать Chromium-бинарник. Если patchright install chromium не сработает, проверь, хватает ли места на диске (около 300 МБ), и убедись, что версия Python — 3.10+.
Шаг 2: Запусти Patchright и открой Glassdoor
Ниже — базовый шаблон запуска, который работает против защиты Cloudflare у Glassdoor:
from patchright.sync_api import sync_playwright
import random, time
with sync_playwright() as p:
browser = p.chromium.launch(
headless=False, # headless по-прежнему легче обнаружить
channel="chrome", # используем настоящий Chrome, а не bundled Chromium
)
context = browser.new_context(
viewport={"width": 1440, "height": 900},
locale="en-US",
timezone_id="America/New_York",
user_agent=(
"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) "
"AppleWebKit/537.36 (KHTML, like Gecko) "
"Chrome/134.0.0.0 Safari/537.36"
),
)
page = context.new_page()
page.goto(
"https://www.glassdoor.com/Job/new-york-data-engineer-jobs-"
"SRCH_IL.0,8_IC1132348_KO9,22.htm"
)
# Убираем окно логина — контент при этом остаётся в DOM
page.add_style_tag(content="""
#HardsellOverlay, .LoginModal { display: none !important; }
body { overflow: auto !important; position: initial !important; }
""")
page.wait_for_selector("[data-test='jobListing']")
print("Страница загружена — карточки вакансий видны.")
На что здесь стоит обратить внимание. Флаг channel="chrome" заставляет Patchright использовать установленный у тебя Chrome, а не свой Chromium — это даёт более правдоподобный браузерный отпечаток. Приём с add_style_tag скрывает модальное окно логина Glassdoor (#HardsellOverlay) без необходимости что-либо нажимать. Scrapfly подтверждает, что "весь контент всё ещё там, он просто перекрыт оверлеем" — HTML содержит данные независимо от того, показано ли окно.
Ты должен увидеть, как окно Chrome открывает страницу поиска вакансий Glassdoor и показывает карточки вакансий без мешающего попапа входа.
Шаг 3: Собираем список вакансий Glassdoor
Находим стабильные селекторы
Glassdoor рандомизирует CSS-классы при каждом билде — поэтому селектор .jobCard_xyz123 из туториала 2023 года сегодня тихо вернёт пустоту. Вместо этого используй атрибуты data-test, которые являются внутренней QA-конвенцией Glassdoor и остаются стабильными между деплоями.
Вот справочник селекторов для полей вакансий:
| Поле | Селектор |
|---|---|
| Контейнер карточки вакансии | [data-test="jobListing"] |
| Название вакансии | [data-test="job-title"] |
| Ссылка на вакансию | a[data-test="job-link"] |
| Название компании | [data-test="employer-name"] |
| Локация | [data-test="emp-location"] |
| Диапазон зарплаты | [data-test="detailSalary"] |
| Рейтинг компании | [data-test="rating"] |
| Дата публикации | [data-test="job-age"] |
| Следующая страница пагинации | [data-test="pagination-next"] |
Извлекаем данные по вакансиям
from parsel import Selector
import csv, random, time
def scrape_jobs(page, max_pages=5):
all_jobs = []
for page_num in range(1, max_pages + 1):
html = page.content()
sel = Selector(text=html)
cards = sel.css('[data-test="jobListing"]')
if not cards:
print(f"Страница {page_num}: карточки не найдены — возможно, блокировка или изменился селектор.")
break
for card in cards:
job = {
"title": card.css('[data-test="job-title"]::text').get("").strip(),
"company": card.css('[data-test="employer-name"]::text').get("").strip(),
"location": card.css('[data-test="emp-location"]::text').get("").strip(),
"salary": card.css('[data-test="detailSalary"]::text').get("").strip(),
"rating": card.css('[data-test="rating"]::text').get("").strip(),
"link": card.css('a[data-test="job-link"]::attr(href)').get(""),
"posted": card.css('[data-test="job-age"]::text').get("").strip(),
}
if job["link"] and not job["link"].startswith("http"):
job["link"] = "https://www.glassdoor.com" + job["link"]
all_jobs.append(job)
print(f"Страница {page_num}: собрано {len(cards)} вакансий")
# Пагинация
next_btn = page.query_selector('[data-test="pagination-next"]')
if next_btn and page_num < max_pages:
next_btn.click()
time.sleep(random.uniform(3, 8))
page.wait_for_selector("[data-test='jobListing']")
else:
break
return all_jobs
Сохраняем в CSV
def save_to_csv(jobs, filename="glassdoor_jobs.csv"):
if not jobs:
print("Нет данных для сохранения.")
return
keys = jobs[0].keys()
with open(filename, "w", newline="", encoding="utf-8") as f:
writer = csv.DictWriter(f, fieldnames=keys)
writer.writeheader()
writer.writerows(jobs)
print(f"Сохранено {len(jobs)} вакансий в {filename}")
Небольшое замечание про ограничения пагинации: Glassdoor ограничивает результаты поиска примерно 30 страницами независимо от общего числа результатов. Если тебе нужно больше охвата, лучше использовать фильтры (локация, тип работы, диапазон зарплаты), чем пытаться листать дальше лимита.
По моим тестам, сбор 5 страниц вакансий (примерно 75 вакансий) занял около 45 секунд с рандомными паузами. Вручную на это ушло бы минимум 20 минут копипаста.
Шаг 4: Собираем отзывы о компаниях Glassdoor
Это раздел, для которого ни один другой туториал не даёт рабочего кода. Именно в отзывах находится настоящая аналитика по работодателю: тональность, сигналы о культуре, красные флаги в управлении.
Переходим на страницу отзывов
URL отзывов имеют такой формат: /Reviews/{Company}-Reviews-E{id}.htm. ID работодателя можно найти, открыв компанию в Glassdoor и посмотрев URL.
def navigate_to_reviews(page, company_reviews_url):
page.goto(company_reviews_url)
page.add_style_tag(content="""
#HardsellOverlay, .LoginModal { display: none !important; }
body { overflow: auto !important; position: initial !important; }
""")
page.wait_for_selector('[data-test="review"]', timeout=15000)
Скрытый BFF-endpoint (самый чистый путь)
Вот главное открытие моего исследования: у отзывов Glassdoor есть рабочий внутренний JSON API, который полностью обходится без HTML-парсинга. Репозиторий Scrapfly с парсерами документирует этот endpoint, и он гораздо надёжнее, чем парсинг DOM.
import json, re, requests
def get_review_ids(page):
"""Извлекает employerId и dynamicProfileId из HTML страницы отзывов."""
html = page.content()
sel = Selector(text=html)
script_text = sel.xpath(
"//script[contains(text(), 'profileId')]/text()"
).get("")
employer_match = re.search(r'"employer"\s*:\s*(\{[^}]+\})', script_text)
if employer_match:
meta = json.loads(employer_match.group(1))
return meta.get("id"), meta.get("profileId")
return None, None
def fetch_reviews_bff(page, employer_id, profile_id, max_pages=5):
"""Вызывает внутренний BFF-endpoint Glassdoor для структурированных данных об отзывах."""
all_reviews = []
cookies = {c["name"]: c["value"] for c in page.context.cookies()}
for pg in range(1, max_pages + 1):
payload = {
"applyDefaultCriteria": True,
"employerId": employer_id,
"dynamicProfileId": profile_id,
"employmentStatuses": ["REGULAR", "PART_TIME"],
"language": "eng",
"onlyCurrentEmployees": False,
"page": pg,
"pageSize": 10,
"sort": "DATE",
"textSearch": "",
}
resp = requests.post(
"https://www.glassdoor.com/bff/employer-profile-mono/employer-reviews",
json=payload,
cookies=cookies,
headers={"Content-Type": "application/json"},
)
if resp.status_code != 200:
print(f"BFF вернул {resp.status_code} на странице {pg}")
break
data = resp.json()
reviews = data.get("data", {}).get("employerReviews", {}).get("reviews", [])
total_pages = data.get("data", {}).get("employerReviews", {}).get("numberOfPages", 1)
for r in reviews:
all_reviews.append({
"title": r.get("summary", ""),
"rating": r.get("ratingOverall"),
"pros": r.get("pros", ""),
"cons": r.get("cons", ""),
"author_role": r.get("jobTitle", {}).get("text", ""),
"date": r.get("reviewDateTime", ""),
"recommend": r.get("isRecommend"),
})
print(f"Страница отзывов {pg}/{total_pages}: получено {len(reviews)} отзывов")
if pg >= total_pages:
break
time.sleep(random.uniform(3, 6))
return all_reviews
BFF-endpoint даёт чистый JSON со всеми полями отзывов — без HTML-парсинга и без риска поломки CSS-селекторов. Тебе нужны session cookies из авторизованного Playwright-контекста (см. шаг 6 ниже), а также сначала нужно вытащить employerId и dynamicProfileId из HTML страницы отзывов.
Fallback-селекторы для отзывов через HTML
Если BFF-endpoint изменится или ты предпочитаешь DOM-парсинг, вот стабильные data-test селекторы:
| Поле | Селектор |
|---|---|
| Контейнер отзыва | [data-test="review"] |
| Заголовок | [data-test="review-title"] |
| Общий рейтинг | [data-test="overall-rating"] |
| Плюсы | [data-test="pros"] |
| Минусы | [data-test="cons"] |
| Дата | [data-test="review-date"] |
| Должность автора | [data-test="author-jobTitle"] |
Шаг 5: Собираем данные о зарплатах Glassdoor
Страницы зарплат полностью закрыты логином. Прежде чем этот код начнёт возвращать реальные данные, у тебя должна быть авторизованная сессия (шаг 6).
Переходим на страницу зарплат
URL зарплат имеют вид: /Salary/{Company}-Salaries-E{id}.htm, а пагинация добавляется как _P{n}.htm.
def scrape_salaries(page, salary_url, max_pages=3):
all_salaries = []
for pg in range(1, max_pages + 1):
url = salary_url if pg == 1 else salary_url.replace(".htm", f"_P{pg}.htm")
page.goto(url)
page.add_style_tag(content="""
#HardsellOverlay { display: none !important; }
body { overflow: auto !important; position: initial !important; }
""")
time.sleep(random.uniform(3, 7))
html = page.content()
sel = Selector(text=html)
items = sel.css('[data-test="salary-item"]')
if not items:
print(f"Страница зарплат {pg}: элементов нет — возможно, блокировка или логин-стена.")
break
for item in items:
salary = {
"job_title": item.css('[class*="SalaryItem_jobTitle__"]::text').get("").strip(),
"salary_range": item.css('[class*="SalaryItem_salaryRange__"]::text').get("").strip(),
"count": item.css('[class*="SalaryItem_salaryCount__"]::text').get("").strip(),
}
all_salaries.append(salary)
print(f"Страница зарплат {pg}: собрано {len(items)} записей")
return all_salaries
Обрати внимание на паттерн [class*="SalaryItem_jobTitle__"] по префиксу. На странице зарплат Glassdoor использует CSS-module-хэши (например, SalaryItem_jobTitle__XWGpT), и суффикс-хэш меняется при каждом деплое. Префикс остаётся стабильным — хэш нет. Никогда не хардкодь полное имя класса.
Шаг 6: Обходим логин-стену Glassdoor
Это критически важный шаг, который открывает доступ к данным о зарплатах и полным текстам отзывов. Подход такой: один раз вручную войти в видимом браузере, сохранить состояние авторизованной сессии, а затем переиспользовать его во всех следующих запусках.
Сохраняем авторизованную сессию
Запусти этот скрипт один раз. Он открывает окно Chrome, переходит на страницу входа Glassdoor (которая теперь перенаправляет на Indeed Login) и ждёт, пока ты войдёшь вручную:
import asyncio
from pathlib import Path
from patchright.async_api import async_playwright
STATE_FILE = Path("glassdoor_state.json")
async def login_and_save():
async with async_playwright() as p:
browser = await p.chromium.launch(headless=False, channel="chrome")
context = await browser.new_context(
viewport={"width": 1366, "height": 800},
locale="en-US",
)
page = await context.new_page()
await page.goto("https://www.glassdoor.com/profile/login_input.htm")
print("Войди в браузере, затем нажми Enter здесь...")
input()
await context.storage_state(path=str(STATE_FILE))
print(f"Сессия сохранена в {STATE_FILE}")
await browser.close()
asyncio.run(login_and_save())
После входа и нажатия Enter Patchright сохраняет все cookies и local storage в glassdoor_state.json. В этом файле будут gdId, GSESSIONID, cf_clearance и auth tokens.
Переиспользуем сессию для скрапинга
Каждый следующий запуск загружает сохранённое состояние — ручной вход уже не нужен:
async def scrape_with_auth(target_url):
async with async_playwright() as p:
browser = await p.chromium.launch(headless=True, channel="chrome")
context = await browser.new_context(
storage_state="glassdoor_state.json"
)
page = await context.new_page()
await page.goto(target_url)
await page.add_style_tag(
content="#HardsellOverlay{display:none!important}"
)
await page.wait_for_load_state("networkidle")
html = await page.content()
await browser.close()
return html
Обычно сохранённая сессия живёт 20–30 минут активного использования, после чего Glassdoor снова запускает проверку. Для более длинных прогонов добавь проверку: если страница, на которой точно должен быть контент, возвращает ноль результатов, просто заново запусти скрипт входа и обнови файл состояния.
Как обнаружить и закрыть всплывающее окно логина
Для частично закрытых страниц — например, список вакансий с данными под модальным окном — помогает CSS-инъекция из предыдущих шагов:
page.add_style_tag(content="""
#HardsellOverlay, .LoginModal { display: none !important; }
body { overflow: auto !important; position: initial !important; }
""")
Это работает только тогда, когда HTML уже содержит данные под оверлеем. Для полностью серверно закрытых страниц — зарплат, глубоких страниц с отзывами — единственный путь это авторизованная сессия из шага 6.
Советы, чтобы твой парсер Glassdoor продолжал работать
Glassdoor часто обновляет фронтенд. Вот как сделать парсер более устойчивым.
Предпочитай атрибуты data-test, а не CSS-классы
Glassdoor рандомизирует CSS-классы, но data-test обычно остаются стабильными. Всегда лучше использовать [data-test="jobListing"], чем .jobCard_abc123. Если data-test недоступен (как в случае полей зарплаты), используй поиск по префиксу: [class*="SalaryItem_jobTitle__"].
Ротуйте прокси и добавляй случайные паузы
Используй rotating residential proxies — datacenter IP блокируются почти сразу. Добавляй случайные задержки 3–8 секунд между загрузками страниц (5–15 секунд для длинных прогонов). По возможности не скрапь в рабочие часы США, когда поведенческая детекция Cloudflare работает агрессивнее всего.
Отслеживай поломки
Добавь в парсер простую проверку: если страница, на которой данные точно есть, возвращает ноль записей, считай это ошибкой селектора, а не пустым результатом, и сразу оповещай себя. Раз в неделю запускай небольшой тестовый сбор, чтобы ловить поломки заранее — Glassdoor выкатывает изменения фронтенда без предупреждения.
Используй быстрый путь через __NEXT_DATA__, когда это возможно
Glassdoor — это приложение на Next.js + Apollo GraphQL. Многие страницы отдают <script id="__NEXT_DATA__">, внутри которого весь GraphQL cache лежит в JSON. Парсить это намного надёжнее, чем DOM, и это полностью обходит Hardsell overlay:
import json
def extract_next_data(html):
sel = Selector(text=html)
raw = sel.css("script#__NEXT_DATA__::text").get()
if raw:
return json.loads(raw)["props"]["pageProps"].get("apolloCache", {})
return None
Такой подход возвращает структурированный Apollo cache со всеми полями вакансий, отзывов и зарплат — без CSS-селекторов. Это самый устойчивый способ извлечения данных, потому что ты работаешь с тем же источником, который использует React-фронтенд Glassdoor.
Обойдём код: собираем данные Glassdoor через Thunderbit (без Python)
Не все, кто читает этот материал, — разработчики. HR-командам, рекрутерам, sales ops-аналитикам и исследователям рынка Glassdoor тоже нужен — и им не стоит управлять Playwright-контекстами и ротацией прокси ради этого.
Thunderbit — это AI Web Scraper расширение для Chrome, которое может извлекать те же вакансии, отзывы и данные о зарплатах без единой строки кода. Я работаю в команде Thunderbit, поэтому скажу об этом прямо — но причина, по которой я включаю его сюда, в том, что он действительно решает две самые сложные проблемы скрапинга Glassdoor.
Как работает Thunderbit на Glassdoor
Процесс занимает два клика:
- Открой любую страницу Glassdoor в Chrome (поиск вакансий, отзывы о компании, страница зарплат)
- Нажми AI Suggest Fields в боковой панели Thunderbit — AI прочитает DOM страницы и предложит колонки (название вакансии, компания, рейтинг, диапазон зарплаты, плюсы, минусы и т. д.)
- Нажми Scrape — данные извлекаются в таблицу без CSS-селекторов и кода для автоматизации браузера
У Thunderbit есть готовый шаблон парсера компаний Glassdoor, который извлекает более 23 полей по компании за один запуск. Для вакансий, отзывов или зарплат универсальный сценарий AI Suggest Fields подходит под любой URL Glassdoor.
Как пройти логин-стену без кода
Именно здесь у Thunderbit появляется структурное преимущество для Glassdoor. Browser Mode работает внутри твоей собственной Chrome-сессии — если ты уже вошёл в Glassdoor в Chrome, Thunderbit автоматически использует те же cookies. Логин-стена на зарплатах и отзывах, которая блокирует серверные скрапер-скрипты, просто не мешает. Никакого управления cookies, никаких persistent contexts, никакого кода для сессий.
Скрапинг подстраниц для обогащения данных
Начни со списка (например, 30 компаний из поиска), пусть Thunderbit перечислит строки, затем включи scraping подстраниц, чтобы заходить на страницу отзывов или зарплат каждой компании и дополнять таблицу полными описаниями, текстом отзывов или данными о зарплатах.
Экспорт в бизнес-инструменты
В отличие от Python-скриптов, которые обычно сохраняют данные в CSV или JSON, Thunderbit экспортирует напрямую в Google Sheets, Airtable, Notion или Excel — и это бесплатно на любом тарифе. Это особенно удобно для команд, которым важно совместно делиться и анализировать данные.
Python или Thunderbit: когда что использовать
| Сценарий | Рекомендуемый подход |
|---|---|
| Построение регулярного потока данных | Python + Patchright |
| Разовая аналитика или небольшой проект команды | Thunderbit |
| Нужен программный контроль над каждым полем | Python |
| Неразработчик, которому Glassdoor нужен уже сегодня | Thunderbit |
| Сбор 1000+ страниц за один запуск | Python + прокси |
| Сбор 30 компаний с обогащением данных | Подойдут оба варианта — Thunderbit быстрее на старте |
Стоимость Thunderbit начинается с бесплатного тарифа (6 страниц в месяц), а тариф Pro стоит $38/месяц и даёт 3 000 кредитов. При расходе 1 кредит на строку результата (2 кредита для scraping подстраниц) этого хватает примерно на 33 запуска по 30 обогащённых компаний в месяц.
Попробовать Thunderbit для сбора данных Glassdoor
Законно ли собирать данные Glassdoor?
Скажу коротко и по фактам. Условия использования Glassdoor прямо запрещают автоматизированный сбор данных: "You may not use any robot, spider, scraper... to access the Services for any purpose without our express written permission."
Но юридическая картина сложнее, чем одна строка в ToS:
- Meta v. Bright Data (N.D. Cal., январь 2024): суд решил, что если ты никогда не входил в систему, то не соглашался с ToS, а публичный сбор данных без входа не нарушает их
- hiQ Labs v. LinkedIn (9-й округ): CFAA не применяется к автоматическому сбору общедоступных данных — но фейковые аккаунты и сбор данных в авторизованной сессии — это уже другое дело
- Van Buren v. United States (Верховный суд, 2021): сузил трактовку "exceeds authorized access" в рамках CFAA
Практический вывод: сбор публичных вакансий без входа в систему находится в сравнительно более безопасной правовой зоне. А вот скрапинг через вошедшую в систему сессию означает, что ты принял ToS при регистрации, и там автоматизированный сбор прямо запрещён. Это одинаково относится и к Python-скриптам, и к Browser Mode Thunderbit.
Этические рекомендации, которых стоит придерживаться в любом случае:
- Ограничивай частоту запросов значительно ниже человеческой скорости
- Не собирай и не перепродавай персонально идентифицируемые данные авторов отзывов
- Уважай правила robots.txt
- Забирай только те поля, которые действительно нужны
Итог: какой способ подходит именно тебе?
В этом руководстве мы разобрали все три типа данных Glassdoor — вакансии, отзывы и зарплаты — и использовали рабочий код 2025 года, который учитывает миграцию на Indeed Login, Cloudflare Bot Management и ротацию CSS-module классов, сломавшую все старые туториалы.
Вот как выбрать подход:
| Ваша ситуация | Лучший путь |
|---|---|
| Разработчик, строящий data pipeline | Python + Patchright (следуй пошаговому гайду выше) |
| Разовая аналитика или регулярные небольшие выгрузки | Thunderbit (без кода, через браузер) |
| Нужны только базовые вакансии в небольшом объёме | Сначала проверь, доступен ли вообще Glassdoor API (скорее всего, нет) |
| Нужны именно данные по зарплатам или отзывам | Придётся использовать Python-скрапинг или Thunderbit — API этого никогда не покрывал |
| Команда без разработчиков, которой нужны общие данные | Thunderbit → экспорт в Google Sheets |
Защита Glassdoor будет и дальше меняться. Селекторы будут ломаться. Появятся новые проверки. Сохрани это руководство в закладки — а если хочешь глубже разобраться в инструментах и техниках веб-скрапинга, посмотри наши материалы про лучшие инструменты для автоматического веб-скрапинга, как собрать данные с сайта на Python и лучшие инструменты для сбора вакансий. Также можно посмотреть разборы на Thunderbit YouTube Channel.
Попробуй Thunderbit для извлечения данных Glassdoor Get Started Free
FAQ
1. Можно ли собирать данные Glassdoor без входа в систему?
Да, для большинства данных по вакансиям и верхнеуровневых рейтингов компаний. Нет, если нужны полные разбивки зарплат или полный текст отзывов дальше первых нескольких страниц. #HardsellOverlay — это модальное окно только на CSS; базовый HTML всё ещё содержит данные первой страницы, но более глубокий контент закрыт серверной "give-to-get" стеной Glassdoor.
2. Какая Python-библиотека лучше всего подходит для Glassdoor в 2025 году?
Patchright (stealth-форк Playwright) — базовая рекомендация. Он исправляет утечку Runtime.Enable в CDP, которая есть в обычном Playwright и которую Cloudflare явно проверяет. Для страниц со списками, где в исходном HTML уже есть __NEXT_DATA__, curl_cffi с impersonate="chrome124" работает в 10–20 раз быстрее, но не справится со страницами, закрытыми логином.
3. Как не попасть под блокировку при сборе данных Glassdoor?
Используй Patchright или rebrowser-playwright, а не обычный Playwright и не Selenium. Ротуйте residential-прокси — datacenter IP блокируются почти сразу. Добавляй случайные паузы 3–8 секунд между страницами. Сохраняй cookies (gdId, cf_clearance, GSESSIONID) между запросами. Ожидай, что через 20–30 минут сессию придётся подтверждать заново.
4. Есть ли у Glassdoor API, который можно использовать вместо скрапинга?
Практически нет. Старый Partner API закрыт для новых заявок, публичного endpoint’а для отзывов никогда не было, и через Indeed Publisher API нет пути миграции. Для отзывов и зарплат реально остаются только скрапинг или no-code-инструмент вроде Thunderbit.
5. Как часто ломаются парсеры Glassdoor?
Часто. Glassdoor выкатывает изменения фронтенда без предупреждения, а хэши CSS-module классов меняются при каждом билде. Самые устойчивые стратегии извлечения данных: (1) селекторы по data-test, (2) JSON-блок __NEXT_DATA__, (3) внутренний BFF-endpoint для отзывов. Добавляй проверку на нулевой результат и запускай небольшой тестовый сбор каждую неделю, чтобы ловить поломки как можно раньше.
Узнать больше


