Glassdoor scrapen met Python: vacatures, salarissen en reviews

Laatst bijgewerkt op April 16, 2026

Als jouw Glassdoor-scraper in 2022 nog prima werkte en nu alleen nog maar 403-fouten teruggeeft, ben je echt niet de enige. Op fora verschijnt steeds weer dezelfde vraag: "Weet iemand waarom deze scraper niet meer werkt?"

Het korte antwoord: Glassdoor heeft alles volledig omgegooid. Recruit Holdings nam Glassdoor in juli 2025 op in Indeed, ontsloeg en zette de anti-botbeveiliging zo strak aan dat gewone Selenium- en requests-scrapers al worden geblokkeerd voordat de eerste byte HTML geladen is. Sinds februari 2026 lopen Glassdoor-logins helemaal via Indeed Login — dus elke handleiding die nog uitgaat van een Glassdoor-specifiek inlogformulier is vanaf de basis al achterhaald. Tegelijkertijd bevat het platform nog altijd van . Die data is enorm waardevol voor HR-benchmarking, concurrentieanalyse en sales prospecting — als je er tenminste bij kunt. Deze gids is de versie die werkt ná al die veranderingen, en behandelt alle drie Glassdoor-datatypeen (vacatures, reviews én salarissen) op één plek. Ik laat je de Python-aanpak zien met werkende code voor 2025, leg precies uit wat je blokkeert en hoe je daar omheen komt, en toon een no-code alternatief voor iedereen die liever helemaal geen engineering doet.

Waarom Glassdoor scrapen met Python in 2025?

Glassdoor is niet zomaar een vacaturebank. Het is een van de rijkste datasets voor werkgeversinzichten op het web — gebruikt door ongeveer en goed voor zo’n 55 miljoen unieke bezoekers per maand. De data achter die pagina’s stuurt echte zakelijke beslissingen binnen meerdere teams.

Zo gebruiken verschillende teams Glassdoor-data in de praktijk:

Use caseBenodigde dataWie profiteert
SalarisbenchmarkingSalarisverdelingen, steekproefgroottesHR, Total Rewards, Operations
Concurrentieanalyse van wervingVacatures, plaatsingsfrequentieSales, Strategy, VC/Corp Dev
Monitoring van employer brandingReviewtekst, ratingtrends, CEO-goedkeuringHR, Marketing, Communicatie
Leadgeneratie (groeiende bedrijven)Vacatures + bedrijfsinformatieSales teams, SDR's
Markt- en academisch onderzoekAlle drieAnalisten, consultants, onderzoekers

glassdoor_stats_00937e478e.png

Toen het BLS tijdens de Amerikaanse overheidsshutdown van oktober 2025 geen arbeidsmarktcijfers kon publiceren, bracht Glassdoors eigen Economic Research-team op basis van hun dataset. Zó serieus nemen institutionele analisten deze data inmiddels.

Python blijft de standaardkeuze omdat het ecosysteem simpelweg ongeëvenaard is — Playwright voor browserautomatisering, parsel/lxml voor parsing, curl_cffi voor het omzeilen van TLS-fingerprints en een enorme community die werkende patronen deelt. Het probleem is niet Python. Het probleem is dat Glassdoor een stuk lastiger te scrapen is geworden.

Als je een no-code alternatief zoekt voor het extraheren van Glassdoor-data, kan Thunderbit je helpen vacatures, reviews en salaris-pagina’s te scrapen zonder een eigen Python-stack op te zetten en te onderhouden.

Welke Glassdoor-data kun je eigenlijk scrapen?

De meeste handleidingen behandelen alleen vacatures. Maar op basis van forumthreads, GitHub-issues en Reddit-vragen die ik heb gevolgd, is de vraag het grootst voor de twee datatypes die bijna niemand uitlegt: reviews en salarissen. Hieronder zie je wat je uit alle drie de categorieën kunt halen.

Vacatures

Het meest toegankelijk. Je kunt ophalen: functietitel, bedrijfsnaam, locatie, salarisschatting, bedrijfsbeoordeling, plaatsingsdatum, easy-apply-badge en de vacaturelink. Vacatures zijn gedeeltelijk beschikbaar zonder in te loggen, al kan Glassdoor na een aantal pagina’s een login-popup tonen.

Bedrijfsreviews

Hier wordt employer-brandanalyse echt interessant. Velden die je kunt extraheren zijn onder andere: overall rating, sub-ratings (work-life balance, cultuur & waarden, diversiteit & inclusie, doorgroeimogelijkheden, beloning & voordelen, senior management), pros-tekst, cons-tekst, functietitel van de reviewer, reviewedatum en dienstverbandstatus. De volledige reviewtekst zit achter een login — je ziet wel een samenvatting, maar voor de volledige pros/cons is authenticatie nodig.

Salarisgegevens

Het meest gevraagde én het meest frustrerende datatype. Je kunt ophalen: functietitel, basissalarisrange, totale compensatierange, aantal salarisrapporten en locatie. Maar salarispagina’s zijn volledig afgeschermd achter login, en Glassdoor gebruikt soms ook nog een "bijdragen om te ontgrendelen"-flow waarbij je eerst je eigen salaris moet invoeren voordat je anderen ziet. Geen enkele concurrerende handleiding geeft hier werkende code voor — dat lossen we hier op.

Wat vereist inloggen en wat niet?

Deze tabel voorkomt dat je op de harde manier ontdekt welke pagina’s leeg terugkomen:

DatatypeBeschikbaar zonder login?Opmerking
Vacaturtitels & basisinformatieMeestal welNa enkele pagina’s kan een popup verschijnen
Volledige vacaturebeschrijvingenGedeeltelijkVaak afgeschermd na 2–3 weergaven
Bedrijfsreviews (volledige tekst)Nee — login vereistSamenvatting zichtbaar, volledige tekst afgeschermd
SalarisgegevensNee — login vereistMogelijk ook "contribute to unlock" vereist

Waarom je oude Glassdoor-scraper waarschijnlijk kapot is

glassdoor_defense_82a26cd8bd.png

Ik wil hier duidelijk over zijn: als je code uit een handleiding van 2021–2023 kopieert, gaat die niet werken. De legacy Glassdoor Selenium-scraper met de meeste sterren op GitHub (, ongeveer 1,4k sterren) heeft 12+ open, onopgeloste issues — waaronder "Glassdoor new UI design," "Cloudflare anti-bot protection" en "NoSuchElementException." De repo is in de praktijk verlaten. . en 8/10 voor het omzeilen van de beveiliging.

Dit is er veranderd en waarom oude code stukloopt:

VerdedigingslaagWat er veranderdeImpact op oude scrapers
Cloudflare Bot ManagementStrengere JA3/JA4-fingerprinting sinds 2024Basis requests/Selenium-scripts krijgen direct 403
Dynamische CSS-klassennamenKlassennamen worden bij elke build gerandomiseerdOude CSS-selectors uit tutorials werken stilletjes niet meer
Rate limiting + sessietrackingStrengere limieten per IP en per sessieScrapers raken sneller geblokkeerd
CAPTCHA-uitdagingen (waarschijnlijk Cloudflare Turnstile)Vaker, vooral tijdens pagineringHeadless browsers triggeren uitdagingen
Uitgebreidere login wallMeer paginatypes vereisen authenticatieSalaris- en reviewpagina’s geven lege data terug
Migratie naar Indeed Login (feb 2026)Glassdoor-loginformulier volledig vervangenCode die het oude login-DOM target is dood

bevat een expliciete waarschuwing: "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." En een zegt het nog directer: "Simple HTTP requests with requests or httpx get blocked instantly."

De tegenmaatregelen die ik hier laat zien — Patchright (een stealth-fork van Playwright), selectors op basis van data-test-attributen, roterende residential proxies en geauthenticeerde persistente sessies — zijn specifiek ontworpen om met al deze lagen om te gaan.

Glassdoor API versus Python-scraping: kies eerst de juiste aanpak

In meerdere forumthreads wordt gevraagd: "Moet ik dan gewoon de Glassdoor API gebruiken?" — en het antwoord is: dat kan niet.

De . Het developerportal bestaat technisch gezien nog wel, maar . Er is nooit een publieke reviews-endpoint geweest — de scraper van MatthewChatham is juist gebouwd "omdat Glassdoor geen API voor reviews heeft." En onder Indeed’s Publisher API bestaat geen migratiepad voor reviews of salarissen.

Hier is de eerlijke vergelijking:

FactorGlassdoor Partner API v1Python-scrapingThunderbit (no-code)
ToegangGesloten voor nieuwe aanmeldingenOpen (zelf implementeren)Chrome-extensie
VacaturesBeperkt/afgebouwdBeschikbaar met moeiteBeschikbaar
BedrijfsreviewsNooit publiek beschikbaar geweestJa (login nodig)Ja (via Browser Mode)
SalarisgegevensNooit publiek beschikbaar geweestJa (login nodig)Ja
Rate limitsNiet gedocumenteerdJij bepaalt het tempoOp credits gebaseerd
Setup-inspanningGeen nieuwe apps te registrerenUren tot dagen~2 minuten
OnderhoudslastN.v.t.Hoog (HTML-wijzigingen breken code)Laag (AI stelt velden opnieuw voor)

Als je reviews of salarisgegevens nodig hebt — en de meeste lezers hebben dat — dan is Python-scraping of een no-code tool je enige realistische optie.

Voordat je begint

  • Moeilijkheidsgraad: Gemiddeld (je moet comfortabel zijn met Python en de terminal)
  • Benodigde tijd: ~30–60 minuten voor de volledige setup; daarna ~10 minuten per datatype
  • Wat je nodig hebt:
    • Python 3.10+ (3.11 of 3.12 aanbevolen)
    • Chrome-browser geïnstalleerd
    • Een Glassdoor-account (gratis — nodig voor salaris- en reviewdata)
    • Roterende residential proxies (voor meer dan een handvol pagina’s)
    • Optioneel: als je de no-code route wilt

Tools en libraries voor Glassdoor scrapen met Python in 2025

Het toolinglandschap is flink veranderd. Dit is wat tegenwoordig echt werkt tegen Glassdoor’s huidige beveiliging.

Waarom Patchright de beste keuze is voor Glassdoor

is een stealth-fork van Playwright die de Runtime.Enable CDP-leak patcht — precies de technische reden waarom vanilla Playwright faalt op sites die door Cloudflare worden beschermd. Het gebruikt exact dezelfde API als Playwright, dus als je Playwright kent, kun je ook met Patchright uit de voeten. Versie 1.58.2 (maart 2026) is actueel en wordt actief onderhouden.

Vergeleken met alternatieven:

  • Vanilla Playwright: Wordt op Glassdoor’s loginpagina gedetecteerd door de Runtime.Enable-leak
  • Selenium + undetected-chromedriver: De laatste release van undetected-chromedriver was in februari 2024 — feitelijk legacy. vond dat het "failed on every domain in our test"
  • requests + BeautifulSoup: Kan geen JavaScript renderen en wordt meteen geblokkeerd door Cloudflare’s TLS-fingerprinting
  • : Uitstekend voor de snelle route (10–20x sneller dan een browser) wanneer pagina’s __NEXT_DATA__ in de initiële HTML meesturen, maar niet geschikt voor login of tussenliggende uitdagingen

Ondersteunende libraries

  • parsel (1.11.0) of lxml (6.0.4): snelle HTML/XPath-parsing
  • csv of pandas: export van data
  • asyncio: async scraping voor snellere paginering

Proxies: alleen residential

Glassdoor’s Cloudflare-laag daagt datacenter-ASN’s agressief uit. . Instapprijzen liggen rond (promotie) of $3,00/GB bij . Voor productie-scraping moet je rekenen op $3–8/GB, afhankelijk van volume.

Willekeurige vertragingen tussen requests (minimaal 3–8 seconden, 5–15 seconden bij langere runs) zijn essentieel, ongeacht de proxykwaliteit.

Stap 1: zet je Python-omgeving op

Maak je projectmap aan en installeer de aanbevolen stack:

1mkdir glassdoor-scraper && cd glassdoor-scraper
2python3.11 -m venv .venv
3source .venv/bin/activate
4pip install --upgrade pip
5# Core stack
6pip install patchright==1.58.2 parsel==1.11.0
7# Browserbinaries installeren
8patchright install chromium
9# Optioneel: snelle route voor __NEXT_DATA__-extractie
10pip install "curl_cffi==0.15.0"

Je zou Patchright een Chromium-binary moeten zien downloaden. Als patchright install chromium faalt, controleer dan of je genoeg schijfruimte hebt (~300MB) en of je Python-versie 3.10+ is.

Stap 2: start Patchright en ga naar Glassdoor

Hier is het basispatroon dat werkt tegen Glassdoor’s Cloudflare-laag:

1from patchright.sync_api import sync_playwright
2import random, time
3with sync_playwright() as p:
4    browser = p.chromium.launch(
5        headless=False,          # headless is nog steeds makkelijker te detecteren
6        channel="chrome",        # gebruik echte Chrome, niet de meegeleverde Chromium
7    )
8    context = browser.new_context(
9        viewport={"width": 1440, "height": 900},
10        locale="en-US",
11        timezone_id="America/New_York",
12        user_agent=(
13            "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) "
14            "AppleWebKit/537.36 (KHTML, like Gecko) "
15            "Chrome/134.0.0.0 Safari/537.36"
16        ),
17    )
18    page = context.new_page()
19    page.goto(
20        "https://www.glassdoor.com/Job/new-york-data-engineer-jobs-"
21        "SRCH_IL.0,8_IC1132348_KO9,22.htm"
22    )
23    # Sluit de login-overlay — de content staat nog steeds in de DOM
24    page.add_style_tag(content="""
25        #HardsellOverlay, .LoginModal { display: none !important; }
26        body { overflow: auto !important; position: initial !important; }
27    """)
28    page.wait_for_selector("[data-test='jobListing']")
29    print("Pagina geladen — vacatures zichtbaar.")

Een paar dingen om op te merken. De channel="chrome"-vlag vertelt Patchright om jouw geïnstalleerde Chrome-binary te gebruiken in plaats van de meegeleverde Chromium — dat levert een authentiekere browserfingerprint op. De add_style_tag-truc verbergt Glassdoor’s loginmodal (genaamd #HardsellOverlay) zonder iets aan te klikken. dat "all of the content is still there, it's just covered up by the overlay" — de HTML bevat de data dus gewoon, ook als de modal zichtbaar is.

Je zou nu een Chrome-venster moeten zien dat naar de Glassdoor-jobzoekpagina navigeert en vacaturekaarten toont zonder dat de login-popup in de weg zit.

Stap 3: Glassdoor-vacatures scrapen

Vind stabiele selectors

Glassdoor randomiseert CSS-klassennamen bij elke build — dus de .jobCard_xyz123-selector uit een tutorial van 2023 levert tegenwoordig stilletjes niets op. Gebruik daarom data-test-attributen; dat is Glassdoor’s interne QA-conventie en die blijven meestal stabiel tussen deploys.

Hier is de selectorreferentie voor vacaturevelden:

VeldSelector
Vacaturekaart-container[data-test="jobListing"]
Functietitel[data-test="job-title"]
Vacaturelinka[data-test="job-link"]
Bedrijfsnaam[data-test="employer-name"]
Locatie[data-test="emp-location"]
Salarisrange[data-test="detailSalary"]
Bedrijfsrating[data-test="rating"]
Plaatsingsdatum[data-test="job-age"]
Volgende pagina[data-test="pagination-next"]

Extraheer vacaturedata

1from parsel import Selector
2import csv, random, time
3def scrape_jobs(page, max_pages=5):
4    all_jobs = []
5    for page_num in range(1, max_pages + 1):
6        html = page.content()
7        sel = Selector(text=html)
8        cards = sel.css('[data-test="jobListing"]')
9        if not cards:
10            print(f"Pagina {page_num}: geen kaarten gevonden — mogelijk een blokkade of gewijzigde selector.")
11            break
12        for card in cards:
13            job = {
14                "title": card.css('[data-test="job-title"]::text').get("").strip(),
15                "company": card.css('[data-test="employer-name"]::text').get("").strip(),
16                "location": card.css('[data-test="emp-location"]::text').get("").strip(),
17                "salary": card.css('[data-test="detailSalary"]::text').get("").strip(),
18                "rating": card.css('[data-test="rating"]::text').get("").strip(),
19                "link": card.css('a[data-test="job-link"]::attr(href)').get(""),
20                "posted": card.css('[data-test="job-age"]::text').get("").strip(),
21            }
22            if job["link"] and not job["link"].startswith("http"):
23                job["link"] = "https://www.glassdoor.com" + job["link"]
24            all_jobs.append(job)
25        print(f"Pagina {page_num}: {len(cards)} vacatures gescrapet")
26        # Paginering
27        next_btn = page.query_selector('[data-test="pagination-next"]')
28        if next_btn and page_num < max_pages:
29            next_btn.click()
30            time.sleep(random.uniform(3, 8))
31            page.wait_for_selector("[data-test='jobListing']")
32        else:
33            break
34    return all_jobs

Opslaan naar CSV

1def save_to_csv(jobs, filename="glassdoor_jobs.csv"):
2    if not jobs:
3        print("Geen vacatures om op te slaan.")
4        return
5    keys = jobs[0].keys()
6    with open(filename, "w", newline="", encoding="utf-8") as f:
7        writer = csv.DictWriter(f, fieldnames=keys)
8        writer.writeheader()
9        writer.writerows(jobs)
10    print(f"{len(jobs)} vacatures opgeslagen in {filename}")

Een opmerking over paginering: Glassdoor beperkt zoekresultaten tot ongeveer 30 pagina’s, ongeacht de totale aantallen. Als je meer dekking nodig hebt, gebruik dan filters (locatie, functietype, salarisrange) om elke zoekopdracht te verfijnen in plaats van door de limiet heen te proberen te bladeren.

In mijn tests kostte het scrapen van 5 pagina’s vacatureoverzichten (ongeveer 75 vacatures) met willekeurige vertragingen zo’n 45 seconden. Handmatig zou hetzelfde minimaal 20 minuten copy-pasten kosten.

Stap 4: Glassdoor-bedrijfsreviews scrapen

Dit is het gedeelte waarvoor geen enkele andere handleiding werkende code geeft. Reviews zijn waar de échte employer intelligence zit — sentimentanalyse, cultuursignalen, management-waarschuwingen.

Ga naar de reviewpagina

Review-URL’s volgen dit patroon: /Reviews/{Company}-Reviews-E{id}.htm. Je kunt het employer-ID vinden door op Glassdoor naar een bedrijf te zoeken en de URL te bekijken.

1def navigate_to_reviews(page, company_reviews_url):
2    page.goto(company_reviews_url)
3    page.add_style_tag(content="""
4        #HardsellOverlay, .LoginModal { display: none !important; }
5        body { overflow: auto !important; position: initial !important; }
6    """)
7    page.wait_for_selector('[data-test="review"]', timeout=15000)

De verborgen BFF-endpoint (de schoonste route)

Dit is de belangrijkste ontdekking uit mijn onderzoek: Glassdoor-reviews hebben een werkende interne JSON API die HTML-parsing volledig omzeilt. De documenteert dit endpoint, en het is veel betrouwbaarder dan DOM-scraping.

1import json, re, requests
2def get_review_ids(page):
3    """Extraheer employerId en dynamicProfileId uit de HTML van de reviewpagina."""
4    html = page.content()
5    sel = Selector(text=html)
6    script_text = sel.xpath(
7        "//script[contains(text(), 'profileId')]/text()"
8    ).get("")
9    employer_match = re.search(r'"employer"\s*:\s*(\{[^}]+\})', script_text)
10    if employer_match:
11        meta = json.loads(employer_match.group(1))
12        return meta.get("id"), meta.get("profileId")
13    return None, None
14def fetch_reviews_bff(page, employer_id, profile_id, max_pages=5):
15    """Roep Glassdoor's interne BFF-endpoint aan voor gestructureerde reviewdata."""
16    all_reviews = []
17    cookies = {c["name"]: c["value"] for c in page.context.cookies()}
18    for pg in range(1, max_pages + 1):
19        payload = {
20            "applyDefaultCriteria": True,
21            "employerId": employer_id,
22            "dynamicProfileId": profile_id,
23            "employmentStatuses": ["REGULAR", "PART_TIME"],
24            "language": "eng",
25            "onlyCurrentEmployees": False,
26            "page": pg,
27            "pageSize": 10,
28            "sort": "DATE",
29            "textSearch": "",
30        }
31        resp = requests.post(
32            "https://www.glassdoor.com/bff/employer-profile-mono/employer-reviews",
33            json=payload,
34            cookies=cookies,
35            headers={"Content-Type": "application/json"},
36        )
37        if resp.status_code != 200:
38            print(f"BFF gaf {resp.status_code} terug op pagina {pg}")
39            break
40        data = resp.json()
41        reviews = data.get("data", {}).get("employerReviews", {}).get("reviews", [])
42        total_pages = data.get("data", {}).get("employerReviews", {}).get("numberOfPages", 1)
43        for r in reviews:
44            all_reviews.append({
45                "title": r.get("summary", ""),
46                "rating": r.get("ratingOverall"),
47                "pros": r.get("pros", ""),
48                "cons": r.get("cons", ""),
49                "author_role": r.get("jobTitle", {}).get("text", ""),
50                "date": r.get("reviewDateTime", ""),
51                "recommend": r.get("isRecommend"),
52            })
53        print(f"Reviews-pagina {pg}/{total_pages}: {len(reviews)} reviews opgehaald")
54        if pg >= total_pages:
55            break
56        time.sleep(random.uniform(3, 6))
57    return all_reviews

De BFF-endpoint levert schone JSON met alle reviewvelden — geen HTML-parsing, geen brekende CSS-selectors. Je hebt wel sessiecookies nodig uit een geauthenticeerde Playwright-context (hieronder in Stap 6), en je moet eerst de employerId en dynamicProfileId uit de HTML van de reviewpagina halen.

HTML-fallback selectors voor reviews

Als de BFF-endpoint verandert of als je liever DOM-parsing gebruikt, dan zijn dit de stabiele data-test-selectors:

VeldSelector
Review-container[data-test="review"]
Kopregel[data-test="review-title"]
Overall rating[data-test="overall-rating"]
Pros[data-test="pros"]
Cons[data-test="cons"]
Datum[data-test="review-date"]
Functie van auteur[data-test="author-jobTitle"]

Stap 5: Glassdoor-salarisdata scrapen

Salarispagina’s zijn volledig afgeschermd achter login. Je moet dus eerst een geauthenticeerde sessie hebben (Stap 6) voordat deze code echte data teruggeeft.

Ga naar de salarispagina

Salaris-URL’s volgen dit patroon: /Salary/{Company}-Salaries-E{id}.htm, met paginering als _P{n}.htm.

1def scrape_salaries(page, salary_url, max_pages=3):
2    all_salaries = []
3    for pg in range(1, max_pages + 1):
4        url = salary_url if pg == 1 else salary_url.replace(".htm", f"_P{pg}.htm")
5        page.goto(url)
6        page.add_style_tag(content="""
7            #HardsellOverlay { display: none !important; }
8            body { overflow: auto !important; position: initial !important; }
9        """)
10        time.sleep(random.uniform(3, 7))
11        html = page.content()
12        sel = Selector(text=html)
13        items = sel.css('[data-test="salary-item"]')
14        if not items:
15            print(f"Salarispagina {pg}: geen items — mogelijk loginblok of blokkade.")
16            break
17        for item in items:
18            salary = {
19                "job_title": item.css('[class*="SalaryItem_jobTitle__"]::text').get("").strip(),
20                "salary_range": item.css('[class*="SalaryItem_salaryRange__"]::text').get("").strip(),
21                "count": item.css('[class*="SalaryItem_salaryCount__"]::text').get("").strip(),
22            }
23            all_salaries.append(salary)
24        print(f"Salarispagina {pg}: {len(items)} items gescrapet")
25    return all_salaries

Let op het patroon [class*="SalaryItem_jobTitle__"]. Glassdoor gebruikt op de salarispagina CSS-module-hashes (bijv. SalaryItem_jobTitle__XWGpT) waarbij het hash-achtervoegsel bij elke deploy verandert. Het voorvoegsel blijft stabiel — de hash niet. Hardcode dus nooit de volledige classname.

Stap 6: kom voorbij Glassdoor’s login wall

Dit is het cruciale onderdeel waarmee je salarisdata en volledige reviewtekst ontsluit. De aanpak: log één keer handmatig in via een zichtbaar browservenster, sla de geauthenticeerde sessie op en hergebruik die daarna voor al je scraping-runs.

Sla je geauthenticeerde sessie op

Voer dit script één keer uit. Het opent een Chrome-venster, gaat naar Glassdoor’s loginpagina (die nu doorstuurt naar Indeed Login), en wacht tot jij handmatig inlogt:

1import asyncio
2from pathlib import Path
3from patchright.async_api import async_playwright
4STATE_FILE = Path("glassdoor_state.json")
5async def login_and_save():
6    async with async_playwright() as p:
7        browser = await p.chromium.launch(headless=False, channel="chrome")
8        context = await browser.new_context(
9            viewport={"width": 1366, "height": 800},
10            locale="en-US",
11        )
12        page = await context.new_page()
13        await page.goto("https://www.glassdoor.com/profile/login_input.htm")
14        print("Log in in het browservenster en druk daarna hier op Enter...")
15        input()
16        await context.storage_state(path=str(STATE_FILE))
17        print(f"Sessie opgeslagen in {STATE_FILE}")
18        await browser.close()
19asyncio.run(login_and_save())

Nadat je bent ingelogd en op Enter hebt gedrukt, slaat Patchright alle cookies en local storage op in glassdoor_state.json. Dit bestand bevat je gdId, GSESSIONID, cf_clearance en auth-tokens.

Hergebruik de sessie voor scraping

Bij elke volgende scraping-run laad je de opgeslagen state opnieuw — handmatig inloggen is dan niet meer nodig:

1async def scrape_with_auth(target_url):
2    async with async_playwright() as p:
3        browser = await p.chromium.launch(headless=True, channel="chrome")
4        context = await browser.new_context(
5            storage_state="glassdoor_state.json"
6        )
7        page = await context.new_page()
8        await page.goto(target_url)
9        await page.add_style_tag(
10            content="#HardsellOverlay{display:none!important}"
11        )
12        await page.wait_for_load_state("networkidle")
13        html = await page.content()
14        await browser.close()
15        return html

De opgeslagen sessie blijft doorgaans 20–30 minuten actief voordat Glassdoor opnieuw een challenge toont. Bouw voor langere runs daarom een controle in: als een pagina die data zou moeten hebben nul resultaten oplevert, log dan opnieuw in om je statebestand te verversen.

De login-popup detecteren en wegwerken

Voor gedeeltelijk afgeschermde pagina’s (vacatures met data achter een modal) werkt de CSS-injectie uit eerdere stappen prima:

1page.add_style_tag(content="""
2    #HardsellOverlay, .LoginModal { display: none !important; }
3    body { overflow: auto !important; position: initial !important; }
4""")

Dat werkt alleen als de HTML onder de overlay de data al bevat. Voor volledig server-side afgeschermde pagina’s (salarissen, diepere reviewpagina’s) is de geauthenticeerde sessie uit Stap 6 de enige route.

Tips om je Glassdoor-scraper werkend te houden

Glassdoor wijzigt zijn frontend regelmatig. Zo bouw je veerkracht in je scraper.

Geef voorkeur aan data-test-attributen boven klassennamen

Glassdoor randomiseert CSS-klassennamen, maar laat data-test-attributen vaak stabiel. Gebruik altijd liever [data-test="jobListing"] dan .jobCard_abc123. Als data-test niet beschikbaar is (zoals bij salarisvelden), gebruik dan het prefix-match-patroon: [class*="SalaryItem_jobTitle__"].

Roteer proxies en randomiseer vertragingen

Gebruik roterende residential proxies — datacenter-IP’s worden vrijwel direct uitgedaagd. Voeg willekeurige vertragingen van 3–8 seconden toe tussen pagina’s (5–15 seconden bij langere runs). Scrapen buiten Amerikaanse kantooruren kan helpen, omdat Cloudflare’s gedragsdetectie dan vaak minder agressief is.

Houd breuken in de gaten

Bouw een eenvoudige controle in je scraper: als een pagina die data zou moeten bevatten nul records oplevert, behandel dat dan als een selectorfout (niet als een lege dataset) en stuur jezelf een melding. Draai wekelijks een kleine testscrape om problemen vroeg te ontdekken — Glassdoor rolt frontendwijzigingen uit zonder aankondiging.

Gebruik de __NEXT_DATA__-snelle route waar mogelijk

Glassdoor is een Next.js + Apollo GraphQL-app. Veel pagina’s leveren een <script id="__NEXT_DATA__">-tag mee met de volledige GraphQL-cache als JSON. Dat parseren is veel robuuster dan DOM-scraping en :

1import json
2def extract_next_data(html):
3    sel = Selector(text=html)
4    raw = sel.css("script#__NEXT_DATA__::text").get()
5    if raw:
6        return json.loads(raw)["props"]["pageProps"].get("apolloCache", {})
7    return None

Dit geeft je de gestructureerde Apollo-cache met alle vacature-, review- en salarisvelden — zonder CSS-selectors. Het is de meest robuuste extractiestrategie die er is, omdat het exact dezelfde data is die Glassdoor’s React-frontend aandrijft.

Sla de code over: Glassdoor scrapen met Thunderbit (geen Python nodig)

Niet iedereen die dit leest is developer. HR-teams, recruiters, sales ops-analisten en marktonderzoekers hebben ook Glassdoor-data nodig — en die zouden geen Playwright-contexten en proxyrotatie hoeven beheren om die data te krijgen.

is een AI Web Scraper Chrome Extension die dezelfde vacatures-, review- en salarisdata kan extraheren zonder één regel code te schrijven. Ik werk zelf aan het Thunderbit-team, dus daar ben ik transparant over — maar de reden dat ik het hier noem is dat het werkelijk de twee lastigste problemen in Glassdoor-scraping oplost.

Hoe Thunderbit werkt op Glassdoor

De workflow bestaat uit twee klikken:

  1. Open een willekeurige Glassdoor-pagina in Chrome (job search, company reviews, salary page)
  2. Klik op AI Suggest Fields in de Thunderbit-sidebar — de AI leest de DOM van de pagina en stelt kolommen voor (functietitel, bedrijf, rating, salarisrange, pros, cons, enz.)
  3. Klik op Scrape — de data wordt naar een tabel gehaald zonder CSS-selectors of browserautomatisering code

Thunderbit heeft een die in één run meer dan 23 velden per bedrijf ophaalt. Voor vacatures, reviews of salarissen werkt de generieke AI Suggest Fields-flow met elke Glassdoor-URL.

De login wall zonder code verwerken

Dit is Thunderbit’s structurele voordeel specifiek voor Glassdoor. Browser Mode draait in je eigen Chrome-sessie — als je al bent ingelogd bij Glassdoor in Chrome, neemt Thunderbit die cookies automatisch over. De login wall voor salarissen en reviews die server-side scrapers blokkeert, speelt dan gewoon niet meer mee. Geen cookiebeheer, geen persistente contexten, geen sessiecode.

Subpage-scraping voor verrijking

Begin vanaf een lijstpagina (bijv. 30 bedrijven uit een zoekopdracht), laat Thunderbit de rijen uitlezen en zet daarna aan om per bedrijf de review- of salaris-pagina te bezoeken en de tabel te verrijken met volledige beschrijvingen, reviewtekst of salarisdetails.

Export naar business tools

In tegenstelling tot Python-scripts die CSV of JSON opleveren, exporteert Thunderbit direct naar Google Sheets, Airtable, Notion of Excel — gratis op elk plan. Vooral handig voor teams die data samen moeten delen en analyseren.

Python versus Thunderbit: wanneer gebruik je wat?

ScenarioAanbevolen aanpak
Een terugkerende datapijplijn bouwenPython + Patchright
Eenmalig onderzoek of klein teamprojectThunderbit
Programmatic controle over elk veld nodigPython
Niet-developer die vandaag Glassdoor-data nodig heeftThunderbit
1.000+ pagina’s in één run scrapenPython + proxies
30 bedrijven scrapen met verrijkingBeide werken — Thunderbit is sneller op te zetten

Thunderbit begint gratis (6 pagina’s per maand), met het voor 3.000 credits. Met 1 credit per outputrij (2 credits voor subpage scraping) is dat genoeg voor ongeveer 33 runs van 30 verrijkte bedrijven per maand.

Is Glassdoor scrapen legaal?

Ik houd dit kort en feitelijk. Glassdoor’s verbieden geautomatiseerd scrapen expliciet: "You may not use any robot, spider, scraper... to access the Services for any purpose without our express written permission."

Het juridische landschap is echter genuanceerder dan één ToS-clausule:

  • (N.D. Cal., jan 2024): de rechtbank oordeelde dat als je nooit inlogt, je de ToS ook nooit hebt geaccepteerd, en scrapen van publiek toegankelijke uitgelogde data die voorwaarden niet schendt
  • hiQ Labs v. LinkedIn (9th Cir.): de CFAA is niet van toepassing op geautomatiseerde verzameling van publiek toegankelijke data — maar nepaccounts en scraping na login zijn een ander verhaal
  • Van Buren v. United States (Supreme Court, 2021): beperkte de betekenis van "exceeds authorized access" onder de CFAA

De praktische conclusie: publieke vacaturelijsten scrapen zonder in te loggen zit juridisch in een relatief veiliger gebied. Scrapen met een ingelogde sessie betekent dat je bij aanmelding akkoord bent gegaan met de ToS, en daarin staat expliciet dat het niet mag. Dat geldt zowel voor Python-scripts als voor Thunderbit’s Browser Mode.

Een paar ethische richtlijnen die je hoe dan ook zou moeten volgen:

  • Rate-limit ruim onder menselijke browsesnelheid
  • Scrape of verkoop geen persoonlijk identificeerbare informatie van reviewers
  • Respecteer robots.txt-richtlijnen
  • Haal alleen de velden op die je echt nodig hebt

Conclusie: welke methode past bij jou?

Deze gids behandelde alle drie de Glassdoor-datatypes — vacatures, reviews en salarissen — met werkende code voor 2025 die rekening houdt met de migratie naar Indeed Login, Cloudflare Bot Management en de rotatie van CSS-moduleklassennamen die oudere tutorials stuk maakten.

Dit is het besliskader:

Jouw situatieBeste route
Developer die een datapijplijn bouwtPython + Patchright (volg de stap-voor-stap hierboven)
Eenmalig onderzoek of terugkerende kleine pullsThunderbit (no-code, browsergebaseerd)
Alleen basis-vacatures op kleine schaal nodigCheck eerst of Glassdoor API-toegang nog bestaat (waarschijnlijk niet)
Specifiek salaris- of reviewdata nodigMoet via Python-scraping of Thunderbit — de API dekte dit nooit
Team van niet-developers dat gedeelde data nodig heeftThunderbit → export naar Google Sheets

Glassdoor’s beveiliging blijft zich ontwikkelen. Selectors breken. Nieuwe uitdagingen verschijnen. Bookmark deze gids — en als je dieper wilt duiken in webscraping-tools en technieken, bekijk dan onze artikelen over , , en . Je kunt ook walkthroughs bekijken op het .

Probeer Thunderbit voor Glassdoor-data-extractie

FAQ’s

1. Kun je Glassdoor scrapen zonder in te loggen?

Ja, voor de meeste vacaturedata en de bovenste bedrijfsratings. Nee, voor volledige salarisuitsplitsingen of de complete reviewtekst voorbij de eerste paar pagina’s. De #HardsellOverlay is een CSS-only modal — de onderliggende HTML bevat nog steeds de data van de eerste pagina — maar diepere content zit server-side achter Glassdoor’s "give-to-get"-muur.

2. Welke Python-library werkt in 2025 het best voor Glassdoor scrapen?

Patchright (een stealth Playwright-fork) is de standaardaanbeveling. Het patcht de Runtime.Enable CDP-leak die vanilla Playwright heeft en waar Cloudflare expliciet op controleert. Voor lijstpagina’s die __NEXT_DATA__ in de initiële HTML meesturen, is curl_cffi met impersonate="chrome124" 10–20x sneller, maar het kan geen login-afgeschermde pagina’s verwerken.

3. Hoe voorkom ik blokkades bij het scrapen van Glassdoor?

Gebruik Patchright of rebrowser-playwright (niet vanilla Playwright of Selenium). Roteer residential proxies — datacenter-IP’s worden vrijwel meteen uitgedaagd. Voeg willekeurige vertragingen van 3–8 seconden toe tussen pagina’s. Bewaar cookies (gdId, cf_clearance, GSESSIONID) tussen requests. Reken op een sessievenster van 20–30 minuten voordat opnieuw een challenge verschijnt.

4. Is er een Glassdoor API die ik kan gebruiken in plaats van scrapen?

In de praktijk niet. De legacy Partner API staat , er heeft nooit een publieke reviews-endpoint bestaan, en via Indeed’s Publisher API is er geen migratiepad. Scraping of een no-code tool zoals Thunderbit is de enige praktische optie voor reviews en salarisdata.

5. Hoe vaak breken Glassdoor-scrapers?

Vaak. Glassdoor rolt frontendwijzigingen uit zonder aankondiging, en CSS-module hash-namen veranderen bij elke build. De meest stabiele extractiestrategieën zijn: (1) data-test-attribute selectors, (2) de __NEXT_DATA__-JSON blob, en (3) de interne BFF-reviews-endpoint. Bouw een zero-results-check in en draai wekelijks een kleine testscrape om problemen vroeg te signaleren.

Meer lezen

Ke
Ke
CTO @ Thunderbit. Ke is the person everyone pings when data gets messy. He's spent his career turning tedious, repetitive work into quiet little automations that just run. If you've ever wished a spreadsheet could fill itself in, Ke has probably already built the thing that does it.
Inhoudsopgave

Probeer Thunderbit

Leads en andere data in slechts 2 klikken scrapen. Aangedreven door AI.

Thunderbit downloaden Het is gratis
Extraheer data met AI
Verplaats data eenvoudig naar Google Sheets, Airtable of Notion
Chrome Store Rating
PRODUCT HUNT#1 Product of the Week