Ważne zastrzeżenie prawne: Ten przewodnik dotyczy wyłącznie dostępu do publicznie dostępnych danych na Glassdoor. Scrapowanie treści objętych murem logowania (pełne profile wynagrodzeń, dane osobowe pracowników) może naruszać Warunki Korzystania Glassdoor, amerykańską ustawę CFAA (Computer Fraud and Abuse Act) oraz europejskie RODO/GDPR. Przed rozpoczęciem projektów scrapingowych skonsultuj się z prawnikiem i rozważ oficjalną licencję na dane od Glassdoor lub partnerów takich jak Glassdoor for Employers.
HR-analytics i inżynierowie danych rynku pracy coraz częściej potrzebują zagregowanych opinii o firmach i wskaźników satysfakcji pracowników. Jak scrapować opinie i dane o wynagrodzeniach Glassdoor w 2026 roku, gdy platforma chroni się warstwami DataDome i Cloudflare Bot Management? Odpowiedź leży w połączeniu TLS-impersonation, endpointów BFF GraphQL oraz rotacyjnych proxy residentialnych. W tym przewodniku pokazujemy krok po kroku, jak zbudować Glassdoor reviews scraper, który działa stabilnie i etycznie.
Jak scrapować opinie i dane o wynagrodzeniach Glassdoor: co jest publiczne, a co za murem logowania
Glassdoor dzieli swoje dane na dwie strefy dostępności. Zrozumienie tej granicy jest kluczowe, bo determinuje całą architekturę scrapera i ramy prawne projektu.
Dane dostępne bez logowania
Bez konta możesz przeglądać:
- Strony przeglądów firm pod URL-em
/Reviews/<company>-Reviews-E<id>.htm— pokazują ocenę ogólną, skrócone treści pros/cons, stanowiska i daty. - Podstawowe informacje o firmie: branża, wielkość, siedziba, strona WWW.
- Truncated review nodes — zwykle 2–3 opinie na stronie z obciętym tekstem (często do ~200 znaków).
- Wyniki wyszukiwania firm w katalogu publicznym.
Te dane są wystarczające do budowy zagregowanych wskaźników: średnia ocena, rozkład ratingOverall, trendy temporalne, liczba opinii w czasie.
Dane za murem logowania (auth-walled)
Po zalogowaniu (lub po podaniu własnej wynagrodzenia/opinii — model „give-to-get”) odblokowuje się:
- Pełne profile wynagrodzeń z podziałem na stanowiska, lokalizacje i lata doświadczenia.
- Pelne treści opinii (nieobcięte).
- Szczegółowe oceny w podkategoriach (kultura, zarządzanie, work-life balance).
- Pytania rekrutacyjne i raporty z rozmów kwalifikacyjnych.
Scrapowanie treści za murem logowania nie jest objęte tym przewodnikiem. Wymaga konta, co automatycznie podlega ToS Glassdoor i zwiększa ryzyko prawne. Zamiast tego skupiamy się na publicznych, truncated review nodes dostępnych przez endpointy GraphQL.
Stack anty-botowy Glassdoor: DataDome + Cloudflare Bot Management
Glassdoor korzysta z co najmniej dwóch warstw ochrony, które razem eliminują większość amatorskich scraperów:
- DataDome — system ochrony botów oparty na ML, analizujący sygnatury przeglądarki, zachowanie sesji i reputację IP. DataDome jest szczególnie agresywny wobec adresów IP z datacenterów (AWS, GCP, DigitalOcean) oraz wobec requestów z niespójnymi nagłówkami TLS.
- Cloudflare Bot Management — warstwa JS challenge i TLS fingerprinting, która sprawdza, czy klient potrafi wykonać JavaScript i czy jego handshake TLS pasuje do deklarowanego User-Agent.
Dlaczego zwykły requests lub curl nie działa? Problem leży w TLS fingerprintingu. Biblioteki Pythona domyślnie używają OpenSSL, którego sygnatura JA3/JA4 różni się od Chrome czy Firefox. Cloudflare i DataDome potrafią wykryć tę rozbieżność i zablokować request jeszcze przed sprawdzeniem treści.
Rozwiązaniem jest curl_cffi — biblioteka Pythona, która wykorzystuje zmodyfikowany silnik curl do impersonacji TLS handshake przeglądarki Chrome. Dzięki temu JA3 fingerprint zgadza się z deklarowanym User-Agent, a request przechodzi pierwszą warstwę weryfikacji.
Endpointy BFF GraphQL i nagłówek gd-csrf-token
Glassdoor nie udokumentuje ich publicznie, ale ruch sieciowy ujawnia dwa kluczowe endpointy zwracające ustrukturyzowane JSON-y:
https://www.glassdoor.com/bff/graphql— główny endpoint BFF (Backend-for-Frontend) przyjmujący zapytania GraphQL.https://www.glassdoor.com/graph— alternatywny endpoint GraphQL (starszy, wciąż aktywny dla niektórych operacji).
Każdy request do tych endpointów wymaga:
- Nagłówka
gd-csrf-token— token CSRF pobierany z metatagu strony HTML lub z ciasteczkagdId. - Spójnych ciasteczek sesji DataDome (
datadome), które muszą być ważne dla danego IP. - Poprawnego
User-Agentzgodnego z impersonacją TLS curl_cffi. - Nagłówka
Content-Type: application/jsoni body z operacją GraphQL.
Kluczowa insight: ciasteczka DataDome są powiązane z adresem IP, na którym zostały wydane. Jeśli zmienisz IP mid-session, DataDome unieważni ciasteczko i zwróci challenge. Dlatego rotacyjne proxy residentialne z opcją sesji sticky są niezbędne.
Proxy residentialne vs datacenter: dlaczego IP scoring decyduje
DataDome klasyfikuje adresy IP według ich reputacji. Adresy z datacenterów (np. AWS 54.x.x.x) mają niemal zerowy trust score — DataDome wie, że to nie jest realny użytkownik. Adresy residentialne, pochodzące od ISP, mają trust score zbliżony do organicznego ruchu.
| Typ proxy | Trust score DataDome | Stabilność sesji | Koszt/GB | Zalecane dla Glassdoor |
|---|---|---|---|---|
| Datacenter | Bardzo niski | Słaba (częste blokady) | $0,5–1,5 | Nie |
| Residential rotacyjne | Wysoki | Dobra (z sticky session) | $2–8 | Tak |
| Mobile | Bardzo wysoki | Świetna | $8–20 | Tak (premium) |
Dla scrapowania Glassdoor optymalny wybór to residential proxy z sesją sticky — pozwala utrzymać ciasteczka DataDome ważne przez całą sesję paginacji, a jednocześnie można przełączyć IP przy nowym batchu firm. Zobacz naszą listę lokalizacji proxy, aby wybrać geo-targeting odpowiedni dla Twojego rynku.
Praktyczna implementacja: Python + curl_cffi + ProxyHat
Poniżej znajduje się kompletny, działający przykład pobierania jednej opinii z endpointu BFF GraphQL przez ProxyHat. Kod używa residential proxy z sesją sticky, aby utrzymać ciasteczka DataDome.
Krok 1: Instalacja zależności
pip install curl_cffi
Krok 2: Pobranie tokenu CSRF i ciasteczek z strony firmy
from curl_cffi import requests
import re, json
# ProxyHat residential proxy z sesją sticky (30 min)
PROXY_URL = "http://user-session-glassdoor01:pass@gate.proxyhat.com:8080"
session = requests.Session(impersonate="chrome")
session.proxies = {"http": PROXY_URL, "https": PROXY_URL}
# Krok 1: pobierz stronę HTML firmy, aby zdobyć gd-csrf-token i ciasteczka
company_url = "https://www.glassdoor.com/Reviews/Google-Reviews-E9079.htm"
resp = session.get(company_url, timeout=30)
print(f"Status: {resp.status_code}, IP trust OK")
# Wyciągnij gd-csrf-token z metatagu lub z ciasteczka
csrf_match = re.search(r'gd-csrf-token[^>]*content="([^"]+)"', resp.text)
csrf_token = csrf_match.group(1) if csrf_match else session.cookies.get("gdId", "")
print(f"CSRF token: {csrf_token[:20]}...")
Krok 3: Zapytanie GraphQL do BFF endpointu
# Krok 2: wyślij zapytanie GraphQL do BFF
graphql_url = "https://www.glassdoor.com/bff/graphql"
query = """
query EmployerReviews($employerId: Long!, $page: Int, $limit: Int) {
employer(employerId: $employerId) {
reviews(page: $page, limit: $limit) {
nodes {
ratingOverall
pros
cons
jobTitle { name }
reviewDateTime
}
pageInfo { hasNextPage currentPage }
}
}
}
"""
variables = {"employerId": 9079, "page": 1, "limit": 10}
headers = {
"Content-Type": "application/json",
"gd-csrf-token": csrf_token,
"Referer": company_url,
"Origin": "https://www.glassdoor.com",
}
payload = {"query": query, "variables": variables}
resp = session.post(graphql_url, json=payload, headers=headers, timeout=30)
data = resp.json()
reviews = data.get("data", {}).get("employer", {}).get("reviews", {}).get("nodes", [])
for r in reviews[:3]:
print(f"Ocena: {r.get('ratingOverall')}, Stanowisko: {r.get('jobTitle', {}).get('name')}")
print(f" Pros: {r.get('pros', '')[:100]}")
print(f" Cons: {r.get('cons', '')[:100]}")
Krok 4: Alternatywa w Node.js (z undici i ProxyAgent)
import { request } from "undici";
import { ProxyAgent } from "undici";
const proxyAgent = new ProxyAgent(
"http://user-session-glassdoor01:pass@gate.proxyhat.com:8080"
);
const query = `
query EmployerReviews($employerId: Long!, $limit: Int) {
employer(employerId: $employerId) {
reviews(limit: $limit) {
nodes { ratingOverall pros cons jobTitle { name } }
}
}
}`;
const res = await request("https://www.glassdoor.com/bff/graphql", {
method: "POST",
dispatcher: proxyAgent,
headers: {
"Content-Type": "application/json",
"gd-csrf-token": process.env.GD_CSRF_TOKEN,
"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36",
},
body: JSON.stringify({
query,
variables: { employerId: 9079, limit: 10 },
}),
});
const data = await res.body.json();
console.log(data.data.employer.reviews.nodes[0]);
Pełną dokumentację konfiguracji proxy znajdziesz na docs.proxyhat.com. Cennik proxy residentialnych i opcji sesji sticky jest dostępny na stronie cennika ProxyHat.
Paginacja, sesje sticky i strategie pacing
Kursory paginacji i przełączanie stron
Endpoint BFF GraphQL wspiera paginację offsetową (page, limit) oraz kursorową (after cursor). Dla dużych firm (np. Amazon z 30 000+ opinii) kursorowa paginacja jest stabilniejsza — offsetowa powyżej ~500 opinii może zwracać błędy lub duplikaty.
# Paginacja kursorowa z retry logic
def fetch_all_reviews(employer_id, max_pages=50):
all_reviews = []
cursor = None
for page in range(max_pages):
variables = {"employerId": employer_id, "limit": 20, "after": cursor}
payload = {"query": query, "variables": variables}
for attempt in range(3):
try:
resp = session.post(graphql_url, json=payload, headers=headers, timeout=30)
if resp.status_code == 403:
# DataDome challenge — przełącz IP i odśwież ciasteczka
rotate_session(session)
continue
data = resp.json()
reviews = data["data"]["employer"]["reviews"]["nodes"]
all_reviews.extend(reviews)
cursor = data["data"]["employer"]["reviews"]["pageInfo"].get("endCursor")
break
except Exception as e:
print(f"Retry {attempt}: {e}")
time.sleep(2 ** attempt)
if not cursor:
break
time.sleep(2) # pacing: 2s między requestami
return all_reviews
Sesje sticky: dlaczego i jak długo
ProxyHat obsługuje sesje sticky przez flagę -session- w nazwie użytkownika:
# Sesja sticky na 30 minut
http://user-session-gd-batch01:pass@gate.proxyhat.com:8080
# Nowa sesja dla nowej firmy
http://user-session-gd-batch02:pass@gate.proxyhat.com:8080
Rekomendowany cykl życia sesji:
- 1 firma = 1 sesja sticky — utrzymuje ciasteczka DataDome ważne przez całą paginację.
- Limit: ~200–300 requestów na sesję — potem DataDome zaczyna podnosić trust threshold.
- Pacing: 1–3 sekundy między requestami — im wolniej, tym stabilniej.
- Rotacja geo: jeśli scrapujesz firmy w UE, użyj
user-country-DE-session-xxx:pass, aby IP pasowało do lokalizacji firmy.
Challenge-retry logic
Gdy DataDome zwróci 403 lub challenge page, scraper powinien:
- Zapisac obecny stan (cursor, page number).
- Utworzyć nową sesję sticky z nowym IP.
- Ponownie pobrać stronę HTML firmy, aby odświeżyć
gd-csrf-tokeni ciasteczka. - Wznowić paginację od zapisanego cursora.
- Jeśli 3 próby z rzędu kończą się blokadą — pauzuj na 15 minut.
Najczęstsze błędy i edge case'y
1. Mismatch TLS vs User-Agent
Najczęstsza przyczyna blokad. Jeśli używasz impersonate="chrome" w curl_cffi, User-Agent MUSI pasować do Chrome (nie Firefox, nie Safari). Mismatch = natychmiastowy 403.
2. Wygasły gd-csrf-token
Token CSRF wygasa po ~60 minutach. Przy długich sesjach paginacji odświeżaj go co 30–40 minut, ponownie pobierając stronę HTML firmy.
3. Zbyt wysoka współbieżność
DataDome analizuje wzorce behawioralne. 100 concurrent requests z tego samego IP = natychmiastowa flaga. Utrzymuj max 3–5 concurrent connections na sesję sticky.
4. Ignorowanie robots.txt
Glassdoor robots.txt wyraźnie blokuje większość ścieżek. Sprawdź go przed rozpoczęciem projektu i uszanuj reguły dla ścieżek, które są objęte Disallow.
Etyczne scrapowanie i kiedy użyć oficjalnego API
Scrapowanie danych publicznych jest legalne w wielu jurysdykcjach, ale „legalne” nie znaczy „bezryzykowne”. Oto zasady, których przestrzegamy:
- Scrapuj tylko zagregowane, nieosobowe dane. Oceny, rozkłady ratingOverall, trendy temporalne — tak. Imiona recenzentów, dokładne daty z możliwością identyfikacji — nie.
- Nigdy nie scrapuj za murem logowania. Wymaga to konta i automatycznie podlega ToS Glassdoor, co może skutkować zawieszeniem konta lub działaniami cywilnymi.
- RODO/GDPR dla danych UE. Jeśli scrapujesz opinie pracowników firm z siedzibą w UE, pamiętaj że dane osobowe (nawet pseudonimizowane stanowiska + lokalizacja + data) mogą podlegać GDPR. Zagreguj do poziomu, który uniemożliwia reidentyfikację.
- Uszanuj ToS i robots.txt. Jeśli Glassdoor wyraźnie zabrania automated access, rozważ alternatywy.
- Rate limiting: nie przeciążaj infrastruktury. 1–3 req/s to bezpieczny próg.
Kiedy oficjalna licencja na dane jest właściwym wyborem
Jeśli Twój projekt to produkt komercyjny (np. platforma HR-analytics SaaS), rozważ:
- Glassdoor for Employers API — dostęp do własnych danych firmowych.
- Partnerstwa data licensing — Glassdoor oferuje licencje na zagregowane dane rynkowe dla enterprise klientów.
- Alternatywne źródła: LinkedIn Talent Insights, Levels.fyi API, Bureau of Labor Statistics dla danych makro.
Dla jednorazowych analiz konkurencji lub badań akademickich, publiczny scraping z etycznymi ograniczeniami jest często wystarczający. Zobacz też nasze przypadki użycia web scraping oraz SERP tracking, aby poznać inne wzorce zbierania danych.
Kluczowe wnioski
Podsumowanie: Scrapowanie publicznych opinii Glassdoor w 2026 wymaga trzech komponentów: (1) curl_cffi do impersonacji TLS Chrome, (2) endpointów BFF GraphQL z nagłówkiem gd-csrf-token, (3) residential proxy z sesją sticky dla utrzymania ciasteczek DataDome. Scrapuj tylko dane publiczne, zagregowane i nieosobowe — pełne dane wynagrodzeń za murem logowania wymagają oficjalnej licencji.
- Publiczne strony
/Reviews/zawierają truncated reviews — wystarczające do agregacji. - Endpoint
/bff/graphqlzwraca ustrukturyzowane JSON-y, ale wymagagd-csrf-tokeni ważnych ciasteczek DataDome. - curl_cffi z
impersonate="chrome"rozwiązuje problem TLS fingerprinting. - Residential proxy z sesją sticky (flaga
-session-) utrzymuje ciasteczka ważne przez całą paginację. - Pacing 1–3 req/s, max 200–300 requestów na sesję, rotacja IP przy challenge.
- Etyka: agreguj, nie identyfikuj, nie scrapuj za loginem, rozważ licencję dla produktów komercyjnych.






