Hvis din Glassdoor-scraper fungerede perfekt i 2022 og nu kun giver 403-fejl, er du langt fra alene. Forum efter forum er fyldt med det samme spørgsmål: "Er der nogen, der ved, hvorfor denne scraper ikke virker længere?"
Det korte svar: Glassdoor har ændret hele opsætningen. Recruit Holdings slog Glassdoor sammen med Indeed i juli 2025, fyrede 1.300 medarbejdere og strammede anti-bot-beskyttelsen så meget, at helt almindelige Selenium- og requests-baserede scrapers bliver blokeret, før den første byte HTML overhovedet når at loade. Pr. februar 2026 håndteres Glassdoor-login fuldstændigt via Indeed Login — så enhver guide, der hardcoder en Glassdoor-specifik loginformular, er grundlæggende ødelagt fra kilden. Samtidig rummer platformen stadig 180 millioner+ samlede anmeldelser, løndata og indsigter på tværs af 2,5 millioner arbejdsgivere. De data er ekstremt værdifulde til HR-benchmarking, konkurrentanalyse og salgssøgning — hvis du altså kan få adgang til dem. Denne guide er den version, der virker efter alle de ændringer, og den dækker alle tre Glassdoor-datatyper (jobs, anmeldelser OG lønninger) samlet ét sted. Jeg viser dig Python-tilgangen med fungerende kode fra 2025, forklarer præcist, hvad der blokerer dig, og hvordan du kommer uden om det, og viser også en no-code-genvej til dig, der helst vil springe udviklingsarbejdet over.
Hvorfor scrape Glassdoor med Python i 2025?
Glassdoor er ikke bare en jobportal. Det er et af de mest omfattende datasæt om arbejdsgivere på nettet — brugt af omkring en tredjedel af Fortune 500-virksomhederne og med cirka 55 millioner unikke månedlige besøgende. Dataene bag siderne driver reelle forretningsbeslutninger på tværs af flere teams.
Sådan bruger forskellige teams faktisk Glassdoor-data:
| Brugsscenarie | Nødvendig datatype | Hvem får mest værdi |
|---|---|---|
| Lønbenchmarking | Lønspektre, stikprøvestørrelser | HR, Total Rewards, Operations |
| Sporing af konkurrenters ansættelser | Jobopslag, opslagshastighed | Salg, strategi, VC/Corp Dev |
| Overvågning af employer brand | Anmeldelsestekst, rating-trends, CEO-godkendelse | HR, marketing, kommunikation |
| Leadgenerering (voksende virksomheder) | Jobopslag + virksomhedsinfo | Salgsteams, SDR'er |
| Markeds- og akademisk forskning | Alle tre | Analytikere, konsulenter, forskere |

Da BLS ikke kunne offentliggøre jobdata under statslukningen i oktober 2025, offentliggjorde Glassdoors eget Economic Research-team en alternativ jobrapport baseret på deres datasæt. Så seriøst bliver disse data nu taget af institutionelle analytikere.
Python er stadig det foretrukne sprog, fordi økosystemet er stærkt: Playwright til browserautomatisering, parsel/lxml til parsing, curl_cffi til at omgå TLS-fingerprinting — og et stort community, der deler fungerende mønstre. Problemet er ikke Python. Problemet er, at Glassdoor er blevet meget sværere at scrape.
Scrape Glassdoor-data med AI Get Started Free
Hvis du vil have et no-code-alternativ til at hente data fra Glassdoor, kan Thunderbit hjælpe dig med at scrape jobs, anmeldelser og lønsider uden at bygge og vedligeholde et skræddersyet Python-setup.
Hvilke Glassdoor-data kan du faktisk scrape?
De fleste guides dækker kun jobopslag. Men efterspørgslen fra brugere — baseret på forumtråde, GitHub-issues og Reddit-spørgsmål, jeg har fulgt — er størst på de to datatyper, næsten ingen lærer fra sig: anmeldelser og lønninger. Her er det fulde overblik over, hvad der kan udtrækkes på tværs af alle tre kategorier.
Jobopslag
Den mest tilgængelige datatype. Du kan hente: jobtitel, firmanavn, placering, estimeret løn, virksomhedsbedømmelse, dato for opslag, badge for nem ansøgning og joblink. Jobopslag er delvist tilgængelige uden login, men Glassdoor kan dukke med en login-pop-up op efter flere sider.
Virksomhedsanmeldelser
Her bliver det interessant for employer brand-analyse. Felter, du kan udtrække, omfatter: samlet rating, underratings (work-life balance, kultur & værdier, diversitet & inklusion, karrieremuligheder, løn & benefits, ledelse), pros-tekst, cons-tekst, anmelderens jobtitel, anmeldelsesdato og ansættelsesstatus. Den fulde anmeldelsestekst kræver login — du ser et uddrag, men hele pros/cons-delen er bag autentificering.
Løndata
Den mest efterspurgte og mest frustrerende datatype. Du kan udtrække: jobtitel, grundlønsspænd, samlet kompensationsspænd, antal lønrapporter og placering. Men lønsider er fuldt låst bag login, og Glassdoor lægger nogle gange oveni et flow med "contribute to unlock", hvor du skal indsende din egen løn, før du kan se andres. Ingen konkurrerende guide har fungerende kode til det — det retter vi op på her.
Hvad kræver login, og hvad kræver det ikke?
Denne tabel sparer dig for at opdage på den hårde måde, hvilke sider der bare returnerer tomme data:
| Datatype | Tilgængelig uden login? | Bemærkninger |
|---|---|---|
| Titler og grundinfo i jobopslag | For det meste ja | Pop-up kan dukke op efter flere sider |
| Fuld jobbeskrivelse | Delvist | Ofte låst efter 2–3 visninger |
| Virksomhedsanmeldelser (fuld tekst) | Nej — login kræves | Uddrag er synligt, fuld tekst er låst |
| Løndata | Nej — login kræves | Kan også kræve "contribute to unlock" |
Hvorfor din gamle Glassdoor-scraper sandsynligvis er gået i stykker

Jeg vil være helt direkte: Hvis du kopierer kode fra en guide fra 2021–2023, så virker den ikke. Den mest stjernemarkede gamle Glassdoor-Selenium-scraper på GitHub (MatthewChatham/glassdoor-review-scraper, ca. 1,4k stjerner) har 12+ åbne, uløste issues — blandt andet "Glassdoor new UI design", "Cloudflare anti-bot protection" og "NoSuchElementException". Repoet er reelt opgivet. Apifys glassdoor-jobs-scraper-aktor er markeret som DEPRECATED. ScrapeOps vurderer Glassdoor til 9/10 i samlet scraping-sværhedsgrad og 8/10 i bypass-sværhedsgrad.
Her er, hvad der har ændret sig, og hvorfor gammel kode fejler:
| Forsvarslag | Hvad der ændrede sig | Konsekvens for gamle scrapers |
|---|---|---|
| Cloudflare Bot Management | Strengere JA3/JA4-fingerprinting siden 2024 | Almindelige requests-/Selenium-scripts får straks 403 |
| Dynamiske CSS-klassenavne | Klassenavne randomiseres ved hver build | Gamle CSS-selektorer fra tutorials holder op med at virke uden fejl |
| Rate limiting + sessionssporing | Skarpere grænser pr. IP og pr. session | Scrapers blokeres efter færre sider |
| CAPTCHA-udfordringer (formentlig Cloudflare Turnstile) | Hyppigere, især ved pagination | Headless browsere udløser udfordringer |
| Udvidet login-mur | Flere sidetyper kræver autentificering | Løn- og anmeldelsessider returnerer tomme data |
| Migration til Indeed Login (februar 2026) | Glassdoors loginformular er helt erstattet | Kode, der rammer det gamle login-DOM, er død |
Scrapflys 2026-guide har en direkte advarsel: "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." Og et DEV.to-indlæg fra marts 2026 siger det meget klart: "Simple HTTP requests with requests or httpx get blocked instantly."
De modforanstaltninger, jeg viser dig — Patchright (en stealth Playwright-fork), data-test-attribut-selektorer, roterende residential proxies og autentificerede persistente sessioner — er specifikt designet til at håndtere hvert af disse lag.
Glassdoor API vs. Python-scraping: Vælg den rigtige tilgang først
Flere forumtråde spørger: "Skal jeg bare bruge Glassdoor API'et?" — og svaret er: det kan du ikke.
Det gamle Glassdoor Partner API er lukket for nye ansøgere. Udviklerportalen findes teknisk set stadig, men returnerer HTTP 403. Der har aldrig været et offentligt reviews-endpoint — MatthewChathams scraper blev netop lavet "fordi Glassdoor ikke har et API til anmeldelser." Og der findes ingen migrationsvej for anmeldelser eller lønninger via Indeed's Publisher API.
Her er den ærlige sammenligning:
| Faktor | Glassdoor Partner API v1 | Python-scraping | Thunderbit (no-code) |
|---|---|---|---|
| Adgang | Lukket for nye ansøgere | Åben (du implementerer selv) | Chrome-udvidelse |
| Jobopslag | Begrænset/afviklet | Tilgængeligt med indsats | Tilgængeligt |
| Virksomhedsanmeldelser | Har aldrig eksisteret offentligt | Ja (login kræves) | Ja (via Browser Mode) |
| Løndata | Har aldrig eksisteret offentligt | Ja (login kræves) | Ja |
| Rate limits | Ikke dokumenteret | Du styrer selv tempoet | Kreditbaseret |
| Opsætningsindsats | Kan ikke oprette nye apps | Timer til dage | Ca. 2 minutter |
| Vedligeholdelse | Ikke relevant | Høj (HTML-ændringer ødelægger kode) | Lav (AI foreslår felter igen) |
Hvis du har brug for anmeldelser eller løndata — og det har de fleste, der læser dette — er Python-scraping eller et no-code-værktøj din eneste realistiske mulighed.
Før du går i gang
- Sværhedsgrad: Mellem (du bør være komfortabel med Python og terminalen)
- Tidsforbrug: Ca. 30–60 minutter til fuld opsætning; derefter ca. 10 minutter pr. datatype
- Det skal du bruge:
- Python 3.10+ (3.11 eller 3.12 anbefales)
- Chrome-browser installeret
- En Glassdoor-konto (gratis — nødvendig til løn- og anmeldelsesdata)
- Roterende residential proxies (hvis du vil scrape mere end ganske få sider)
- Valgfrit: Thunderbit Chrome Extension, hvis du vil gå no-code-vejen
Værktøjer og biblioteker til at scrape Glassdoor med Python i 2025
Værktøjslandskabet har ændret sig markant. Her er det, der faktisk virker mod Glassdoors nuværende beskyttelse.
Hvorfor Patchright er det bedste valg til Glassdoor
Patchright er en stealth-fork af Playwright, som patchede Runtime.Enable CDP-lekket — den konkrete tekniske årsag til, at ren Playwright fejler på Cloudflare-beskyttede sider. Den bruger præcis samme API som Playwright, så hvis du kender Playwright, kan du også Patchright. Version 1.58.2 (marts 2026) er den aktuelle og aktivt vedligeholdte.
Sammenlignet med alternativerne:
- Ren Playwright: Bliver opdaget på Glassdoors login-side på grund af Runtime.Enable-lekket
- Selenium + undetected-chromedriver: undetected-chromedriver havde seneste release i februar 2024 — det er reelt et legacy-værktøj. Scrapflys benchmark fandt, at det "failed on every domain in our test"
- requests + BeautifulSoup: Kan ikke rendere JavaScript og bliver straks blokeret af Cloudflares TLS-fingerprinting
- curl_cffi: Fremragende til den hurtige vej (10–20x hurtigere end en browser), når sider leverer
__NEXT_DATA__i den første HTML, men kan ikke håndtere login eller mellem-lag med udfordringer
Supplerende biblioteker
- parsel (1.11.0) eller lxml (6.0.4): Hurtig HTML/XPath-parsing
- csv eller pandas: Eksport af data
- asyncio: Asynkron scraping for hurtigere pagination
Proxies: Kun residential
Glassdoors Cloudflare-lag udfordrer datacenter-ASNs aggressivt. Residential proxies skulle reducere blokkeringsraten fra 20–30% til under 5%. Startpriser ligger omkring $1,75/GB fra IPRoyal (kampagnepris) eller $3,00/GB fra Decodo. Til produktion bør du budgettere med $3–8/GB afhængigt af volumen.
Tilfældige pauser mellem requests (mindst 3–8 sekunder, 5–15 sekunder ved længere kørsler) er vigtige uanset proxy-kvalitet.
Trin 1: Sæt dit Python-miljø op
Opret projektmappen og installer den anbefalede stack:
mkdir glassdoor-scraper && cd glassdoor-scraper
python3.11 -m venv .venv
source .venv/bin/activate
pip install --upgrade pip
# Core stack
pip install patchright==1.58.2 parsel==1.11.0
# Install browser binaries
patchright install chromium
# Optional: fast path for __NEXT_DATA__ extraction
pip install "curl_cffi==0.15.0"
Du bør se Patchright downloade en Chromium-binærfil. Hvis patchright install chromium fejler, så tjek, at du har nok diskplads (ca. 300 MB), og at din Python-version er 3.10+.
Trin 2: Start Patchright og navigér til Glassdoor
Her er den basale startopsætning, som virker mod Glassdoors Cloudflare-lag:
from patchright.sync_api import sync_playwright
import random, time
with sync_playwright() as p:
browser = p.chromium.launch(
headless=False, # headless er stadig lettere at opdage
channel="chrome", # brug rigtig Chrome, ikke den indbyggede 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"
)
# Fjern login-overlayet — indholdet ligger stadig i DOM'en
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("Siden er indlæst — jobopslagene er synlige.")
Et par ting er værd at bemærke. Flaget channel="chrome" fortæller Patchright, at den skal bruge din installerede Chrome-binærfil i stedet for den medfølgende Chromium — det giver et mere autentisk browser-fingerprint. Tricket med add_style_tag skjuler Glassdoors login-modal (kaldet #HardsellOverlay) uden at du behøver klikke på noget. Scrapfly bekræfter, at "all of the content is still there, it's just covered up by the overlay" — HTML'en indeholder dataene, uanset om modalvinduet vises eller ej.
Du bør se et Chrome-vindue åbne, gå til Glassdoors jobsearch-side og vise kort med jobopslag uden at login-popuppen spærrer udsynet.
Trin 3: Scrape jobopslag fra Glassdoor
Find stabile selektorer
Glassdoor randomiserer CSS-klassenavne ved hver build — så en .jobCard_xyz123-selector fra en guide fra 2023 returnerer stille og roligt ingenting i dag. Brug i stedet data-test-attributter, som er Glassdoors interne QA-konvention og forbliver stabile på tværs af deploys.
Her er selector-reference til felter i jobopslag:
| Felt | Selektor |
|---|---|
| Container for jobkort | [data-test="jobListing"] |
| Jobtitel | [data-test="job-title"] |
| Joblink | a[data-test="job-link"] |
| Firmanavn | [data-test="employer-name"] |
| Placering | [data-test="emp-location"] |
| Lønspektrum | [data-test="detailSalary"] |
| Virksomhedsrating | [data-test="rating"] |
| Opslået dato | [data-test="job-age"] |
| Næste side i pagination | [data-test="pagination-next"] |
Udtræk jobdata
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"Side {page_num}: Ingen kort fundet — mulig blokering eller ændret selector.")
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"Side {page_num}: hentet {len(cards)} jobopslag")
# Pagination
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
Gem til CSV
def save_to_csv(jobs, filename="glassdoor_jobs.csv"):
if not jobs:
print("Ingen jobs at gemme.")
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"Gemte {len(jobs)} jobopslag i {filename}")
Et par ord om pagination-grænser: Glassdoor begrænser søgeresultater til cirka 30 sider, uanset hvor mange resultater der findes samlet. Hvis du vil have større dækning, så brug filtre (placering, jobtype, løninterval) til at indsnævre hver søgning i stedet for at forsøge at paginate forbi loftet.
I min test tog scraping af 5 sider med jobopslag (ca. 75 jobs) omkring 45 sekunder med tilfældige pauser. At gøre det samme manuelt ville tage mindst 20 minutter med copy-paste.
Trin 4: Scrape Glassdoor-virksomhedsanmeldelser
Det her er den del, ingen andre guides giver fungerende kode til. Anmeldelser er der, den reelle employer intelligence ligger — sentimentanalyse, kultur-signaler og advarselstegn i ledelsen.
Gå til anmeldelsessiden
Review-URL'er følger dette mønster: /Reviews/{Company}-Reviews-E{id}.htm. Du kan finde employer ID'et ved at søge efter en virksomhed på Glassdoor og se URL'en.
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)
Det skjulte BFF-endpoint (den reneste vej)
Her er den vigtigste opdagelse fra min research: Glassdoor-anmeldelser har et fungerende internt JSON-API, som helt omgår HTML-parsing. Scrapflys scrapers-repo dokumenterer dette endpoint, og det er langt mere stabilt end DOM-scraping.
import json, re, requests
def get_review_ids(page):
"""Udtræk employerId og dynamicProfileId fra anmeldelsernes 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):
"""Kald Glassdoors interne BFF-endpoint for strukturerede anmeldelsesdata."""
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 returnerede {resp.status_code} på side {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"Anmeldelsesside {pg}/{total_pages}: hentede {len(reviews)} anmeldelser")
if pg >= total_pages:
break
time.sleep(random.uniform(3, 6))
return all_reviews
BFF-endpointet giver dig ren JSON med alle anmeldelsesfelter — ingen HTML-parsing, ingen CSS-selector-problemer. Du skal bruge sessionscookies fra en autentificeret Playwright-session (beskrevet i trin 6 nedenfor), og du skal først udtrække employerId og dynamicProfileId fra anmeldelsessidens HTML.
HTML-fallback-selektorer til anmeldelser
Hvis BFF-endpointet ændrer sig, eller du foretrækker DOM-parsing, er her de stabile data-test-selektorer:
| Felt | Selektor |
|---|---|
| Container for anmeldelse | [data-test="review"] |
| Overskrift | [data-test="review-title"] |
| Samlet rating | [data-test="overall-rating"] |
| Pros | [data-test="pros"] |
| Cons | [data-test="cons"] |
| Dato | [data-test="review-date"] |
| Forfatterens jobrolle | [data-test="author-jobTitle"] |
Trin 5: Scrape Glassdoor-løndata
Lønsider er fuldt låst bag login. Du skal have en autentificeret session (trin 6), før nogen af disse koder kan returnere rigtige data.
Gå til lønsiden
Løn-URL'er følger mønsteret: /Salary/{Company}-Salaries-E{id}.htm, med pagination som _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"Lønside {pg}: Ingen elementer — mulig loginmur eller blokering.")
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"Lønside {pg}: hentede {len(items)} poster")
return all_salaries
Bemærk prefix-match-mønsteret [class*="SalaryItem_jobTitle__"]. Glassdoors lønside bruger CSS-module-hashede klassenavne (f.eks. SalaryItem_jobTitle__XWGpT), hvor hash-suffixet skifter ved hver deploy. Prefixet forbliver stabilt — ikke hashen. Hardcod aldrig det fulde klassenavn.
Trin 6: Kom forbi Glassdoors loginmur
Det her er den afgørende del, der låser op for løndata og fuld anmeldelsestekst. Fremgangsmåden er: log ind manuelt én gang i en synlig browser, gem den autentificerede session, og genbrug den derefter i alle efterfølgende scraping-kørsler.
Gem din autentificerede session
Kør dette script én gang. Det åbner et Chrome-vindue, går til Glassdoors login-side (som nu viderestiller til Indeed Login) og venter på, at du logger ind manuelt:
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("Log ind i browser-vinduet, og tryk derefter Enter her...")
input()
await context.storage_state(path=str(STATE_FILE))
print(f"Session gemt i {STATE_FILE}")
await browser.close()
asyncio.run(login_and_save())
Når du har logget ind og trykket Enter, gemmer Patchright alle cookies og lokal lagring i glassdoor_state.json. Denne fil indeholder dine gdId, GSESSIONID, cf_clearance og auth tokens.
Genbrug sessionen til scraping
Alle efterfølgende scraping-kørsler indlæser den gemte state — ingen manuel login igen:
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
Den gemte session varer typisk 20–30 minutters aktiv brug, før Glassdoor udfordrer igen. Ved længere scraping-kørsler bør du indbygge et tjek: Hvis du får nul resultater fra en side, der burde indeholde data, så kør login-scriptet igen for at opdatere din state-fil.
Sådan opdager og lukker du login-popuppen
For delvist låste sider (jobopslag, hvor data vises, men en modal ligger ovenpå), virker CSS-injektionen fra de tidligere trin:
page.add_style_tag(content="""
#HardsellOverlay, .LoginModal { display: none !important; }
body { overflow: auto !important; position: initial !important; }
""")
Det virker kun, når HTML allerede indeholder dataene under overlayet. For fuldt server-side-låste sider (lønninger, dybere anmeldelsessider) er den autentificerede session fra trin 6 den eneste vej.
Tips til at holde din Glassdoor-scraper kørende
Glassdoor opdaterer sit frontend løbende. Her er, hvordan du bygger robusthed ind i din scraper.
Foretræk data-test-attributter frem for klassenavne
Glassdoor randomiserer CSS-klassenavne, men plejer at holde data-test-attributterne stabile. Brug altid [data-test="jobListing"] frem for .jobCard_abc123. Når data-test ikke findes (som på lønsiden), så brug prefix-match-mønstret: [class*="SalaryItem_jobTitle__"].
Rotér proxies og brug tilfældige pauser
Brug roterende residential proxies — datacenter-IP'er bliver næsten straks udfordret. Læg tilfældige pauser på 3–8 sekunder ind mellem sideindlæsninger (5–15 sekunder ved længere kørsler). Undgå om muligt scraping i amerikanske arbejdstider, hvor Cloudflares adfærdsdetektion er mest aggressiv.
Overvåg for fejl
Indbyg et simpelt tjek i din scraper: Hvis en side, der burde indeholde data, giver nul udtrukne poster, så behandl det som en selector-fejl — ikke som et tomt resultat — og gør dig selv opmærksom på det. Kør en lille testscrape ugentligt, så du fanger fejl tidligt — Glassdoor deployer frontend-ændringer uden varsel.
Brug __NEXT_DATA__-hurtigsporet, når det er muligt
Glassdoor er en Next.js + Apollo GraphQL-app. Mange sider leverer et <script id="__NEXT_DATA__">-tag med hele GraphQL-cachen som JSON. At parse dette er langt mere robust end DOM-scraping og omgår helt Hardsell-overlayet:
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
Det returnerer den strukturerede Apollo-cache med alle job-, anmeldelses- og lønfelter — helt uden CSS-selektorer. Det er den mest robuste udtræksstrategi, der findes, fordi det er de samme data, som driver Glassdoors React-frontend.
Spring koden over: Scrape Glassdoor med Thunderbit (ingen Python nødvendig)
Det er ikke alle, der læser dette, som er udviklere. HR-teams, recruiters, salgsoperationsanalytikere og markedsforskere har også brug for Glassdoor-data — og de bør ikke skulle håndtere Playwright-contexts og proxy-rotation for at få dem.
Thunderbit er en AI Web Scraper Chrome Extension, der kan udtrække de samme data om jobs, anmeldelser og lønninger uden at skrive en eneste linje kode. Jeg arbejder på Thunderbit-teamet, så det siger jeg gerne åbent — men grunden til, at jeg nævner det her, er, at det faktisk løser de to sværeste problemer ved Glassdoor-scraping.
Sådan virker Thunderbit på Glassdoor
Arbejdsgangen er to klik:
- Åbn en hvilken som helst Glassdoor-side i Chrome (jobsearch, virksomhedsanmeldelser, lønside)
- Klik på AI Suggest Fields i Thunderbit-sidebaren — AI'en læser sidens DOM og foreslår kolonner (jobtitel, firma, rating, løninterval, pros, cons osv.)
- Klik på Scrape — data trækkes ind i en tabel uden CSS-selektorer eller browserautomatiseringskode
Thunderbit har en færdig Glassdoor company scraper-skabelon, der henter 23+ felter pr. virksomhed i én kørsel. Til jobopslag, anmeldelser eller lønninger håndterer den generelle AI Suggest Fields-arbejdsgang enhver Glassdoor-URL.
Håndtering af login-muren uden kode
Det er Thunderbits strukturelle fordel netop på Glassdoor. Browser Mode kører inde i din egen Chrome-session — hvis du er logget ind på Glassdoor i Chrome, arver Thunderbit automatisk de cookies. Loginmuren for løn og anmeldelser, som blokerer server-side scrapers, gælder simpelthen ikke. Ingen cookiehåndtering, ingen persistente contexts, ingen sessionskode.
Subpage-scraping til berigelse
Start fra en listeside (fx 30 virksomheder fra en søgning), lad Thunderbit enumerere rækkerne, og slå derefter subpage scraping til for at besøge hver virksomheds anmeldelses- eller lønside og berige tabellen med fulde beskrivelser, anmeldelsestekst eller løndetaljer.
Eksport til forretningsværktøjer
I modsætning til Python-scripts, der outputter CSV eller JSON, eksporterer Thunderbit direkte til Google Sheets, Airtable, Notion eller Excel — gratis på alle planer. Det er særligt nyttigt for teams, der skal dele og analysere data sammen.
Python vs. Thunderbit: Hvornår bruger man hvad?
| Situation | Anbefalet tilgang |
|---|---|
| Bygger en tilbagevendende datapipeline | Python + Patchright |
| Engangsresearch eller mindre teamprojekt | Thunderbit |
| Har brug for programmatisk kontrol over hvert felt | Python |
| Ikke-udvikler, der skal bruge Glassdoor-data i dag | Thunderbit |
| Scraper 1.000+ sider i én kørsel | Python + proxies |
| Scraper 30 virksomheder med berigelse | Begge virker — Thunderbit er hurtigere at sætte op |
Thunderbits pris starter gratis (6 sider/måned), og Pro-planen koster $38/måned for 3.000 credits. Med 1 credit pr. outputrække (2 credits for subpage scraping) er det nok til cirka 33 kørsler á 30 berigede virksomheder om måneden.
Prøv Thunderbit til Glassdoor-scraping
Er det lovligt at scrape Glassdoor?
Jeg holder det kort og faktuelt. Glassdoors vilkår forbyder udtrykkeligt automatiseret scraping: "You may not use any robot, spider, scraper... to access the Services for any purpose without our express written permission."
Det juridiske landskab er dog mere nuanceret end en enkelt ToS-bestemmelse:
- Meta v. Bright Data (N.D. Cal., jan. 2024): Retten fastslog, at hvis du aldrig logger ind, har du aldrig accepteret ToS, og offentlig scraping uden login bryder dem ikke
- hiQ Labs v. LinkedIn (9th Cir.): CFAA gælder ikke for automatiseret indsamling af offentligt tilgængelige data — men falske konti og scraping med login er en anden sag
- Van Buren v. United States (Supreme Court, 2021): Indskrænkede "exceeds authorized access" under CFAA
Den praktiske konklusion: scraping af offentlige jobopslag uden login ligger i en relativt sikrere juridisk zone. Scraping med en logget ind session betyder, at du accepterede vilkårene ved oprettelsen, og de forbyder det udtrykkeligt. Det gælder både Python-scripts og Thunderbits Browser Mode.
Etiske retningslinjer, der er værd at følge uanset hvad:
- Begræns hastigheden langt under menneskelig browsing-hastighed
- Scrape eller videresælg ikke personhenførbare oplysninger om anmeldere
- Respektér robots.txt-direktiver
- Hent kun de felter, du faktisk har brug for
Konklusion: Hvilken metode er den rigtige for dig?
Denne guide dækkede alle tre Glassdoor-datatyper — jobs, anmeldelser og lønninger — med fungerende kode fra 2025, der tager højde for migrationen til Indeed Login, Cloudflare Bot Management og den rotation af CSS-module-klassenavne, som ødelagde alle ældre tutorials.
Her er beslutningsmodellen:
| Din situation | Bedste løsning |
|---|---|
| Udvikler, der bygger en datapipeline | Python + Patchright (følg trin-for-trin-guiden ovenfor) |
| Engangsresearch eller tilbagevendende små indsamlinger | Thunderbit (uden kode, browserbaseret) |
| Du har kun brug for simple jobopslag i lille skala | Tjek først, om Glassdoor API-adgang stadig er mulig (sandsynligvis ikke) |
| Du har specifikt brug for løn- eller anmeldelsesdata | Du må bruge Python-scraping eller Thunderbit — API'et dækkede aldrig det |
| Team af ikke-udviklere, der skal dele data | Thunderbit → eksport til Google Sheets |
Glassdoors forsvar vil fortsætte med at udvikle sig. Selektorer vil gå i stykker. Nye udfordringer vil dukke op. Bogmærk denne guide — og hvis du vil dykke dybere ned i web scraping-værktøjer og teknikker, så se også vores indlæg om de bedste automatiserede web scraping-værktøjer, hvordan man scraper data fra en hjemmeside med Python og de bedste job-scraping-værktøjer. Du kan også se walkthroughs på Thunderbit YouTube-kanalen.
Prøv Thunderbit til udtræk af Glassdoor-data Get Started Free
FAQs
1. Kan man scrape Glassdoor uden at logge ind?
Ja, for det meste af jobopslagsdataene og de øverste virksomhedsratinger. Nej, ikke for fulde lønopdelinger eller den komplette anmeldelsestekst ud over de første få sider. #HardsellOverlay er en CSS-only modal — den underliggende HTML indeholder stadig dataene på første side — men dybere indhold er server-side låst bag Glassdoors "give-to-get"-mur.
2. Hvilket Python-bibliotek er bedst til at scrape Glassdoor i 2025?
Patchright (en stealth Playwright-fork) er standardanbefalingen. Den patchede Runtime.Enable CDP-lækagen, som ren Playwright har, og som Cloudflare eksplicit tjekker for. For listsider, der leverer __NEXT_DATA__ i den første HTML, er curl_cffi med impersonate="chrome124" 10–20x hurtigere, men kan ikke håndtere sider, der kræver login.
3. Hvordan undgår jeg at blive blokeret, når jeg scraper Glassdoor?
Brug Patchright eller rebrowser-playwright (ikke ren Playwright eller Selenium). Rotér residential proxies — datacenter-IP'er bliver udfordret med det samme. Læg tilfældige pauser på 3–8 sekunder ind mellem sider. Bevar cookies (gdId, cf_clearance, GSESSIONID) mellem requests. Forvent et session-vindue på 20–30 minutter, før du bliver udfordret igen.
4. Findes der et Glassdoor API, jeg kan bruge i stedet for scraping?
I praksis nej. Det gamle Partner API er lukket for nye ansøgere, der har aldrig eksisteret et offentligt reviews-endpoint, og der er ingen migrationsvej via Indeed's Publisher API. Scraping eller et no-code-værktøj som Thunderbit er den eneste realistiske løsning til anmeldelser og løndata.
5. Hvor ofte går Glassdoor-scrapers i stykker?
Ofte. Glassdoor deployer frontend-ændringer uden varsel, og CSS-module-klassenavnshashes roterer ved hver build. De mest stabile udtræksstrategier er: (1) data-test-attribut-selektorer, (2) __NEXT_DATA__-JSON-blokken og (3) det interne BFF-reviews-endpoint. Indbyg et tjek for nul resultater, og kør en lille testscrape ugentligt for at opdage fejl tidligt.
Læs mere


