Hoe Indeed Vacatures te Scrapen: Structuur, Blokken en de SERP Route
Indeed is het grootste vacaturebord op het web en een live signaal van de arbeidsmarkt. Het staat ook achter Cloudflare met klassenamen die wekelijks roteren. Hier is hoe je het duurzaam kunt extraheren — en wanneer je de site volledig moet overslaan.
Indeed trekt ongeveer 542 miljoen bezoeken per maand, wat zijn lijsten tot een van de schoonste live signalen voor de arbeidsmarkt maakt — vraag naar personeel per rol, salarisschalen, welke bedrijven personeel aannemen. Het is ook een door Cloudflare beschermde React-site waarvan de zichtbare CSS-klassenamen vaak genoeg roteren om een naïeve scraper binnen enkele weken te breken. Deze gids laat zien hoe je Indeed vacatures duurzaam kunt scrapen, hoe je ze kunt pagineren en dedupliceren, de Cloudflare realiteit, en de jobs SERP verticaal die je de strijd volledig laat overslaan.
Lees de zoekpagina, anker op stabiele attributen
De eenheid van Indeed-gegevens is de zoekresultatenpagina: query plus locatie geeft je een pagina met vacaturekaarten. De valkuil is selecteren op de gehashte klassenamen (dingen zoals eu4oa1w0) die Indeed regenereert. Anker in plaats daarvan op de data-testid attributen, die veel minder vaak veranderen:
import requests
from bs4 import BeautifulSoup
headers = {
"User-Agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 "
"(KHTML, like Gecko) Chrome/146.0.0.0 Safari/537.36",
"Accept-Language": "en-US,en;q=0.9",
}
proxies = {"http": "http://USER:PASS@gate.quantumproxies.io:8000",
"https": "http://USER:PASS@gate.quantumproxies.io:8000"}
url = "https://www.indeed.com/jobs?q=python&l=New+York%2C+NY"
html = requests.get(url, headers=headers, proxies=proxies, timeout=30).text
soup = BeautifulSoup(html, "html.parser")
jobs = []
for card in soup.select("div.job_seen_beacon"):
title = card.find("a", class_="jcs-JobTitle")
company = card.find("span", attrs={"data-testid": "company-name"})
location = card.find("div", attrs={"data-testid": "text-location"})
jobs.append({
"title": title.get_text(strip=True) if title else None,
"company": company.get_text(strip=True) if company else None,
"location": location.get_text(strip=True) if location else None,
"jk": title["href"].split("jk=")[-1][:16] if title else None,
})
print(len(jobs), "jobs on page 1")
Elke kaart heeft een vacature sleutel (jk) — een stabiele ID die je gebruikt om te dedupliceren over pagina's en runs. Sla op jk op, niet op URL, omdat dezelfde vacature verschijnt met verschillende tracking parameters.
Paginering en landensites
Indeed pagineert met een start parameter die met 10 toeneemt. En het is niet één site — elk land is een subdomein: www.indeed.com voor de VS, uk.indeed.com voor het VK, enzovoort. Stem je proxy exit af op het land dat je bevraagt zodat het verzoek geografisch coherent is:
def crawl(query, location, country="www", pages=5):
base = f"https://{country}.indeed.com/jobs"
for start in range(0, pages * 10, 10):
params = {"q": query, "l": location, "start": start}
html = requests.get(base, params=params, headers=headers,
proxies=proxies, timeout=30).text
# parse as above, yield rows
yield html
# freshness filter: fromage accepts only 1, 3, 7 or 14 days
# .../jobs?q=python&l=NYC&fromage=7
Een eigenaardigheid die de moeite waard is om te weten: Indeed's "geplaatst binnen" filter (fromage) accepteert alleen 1, 3, 7 of 14 dagen — andere waarden worden genegeerd, dus bouw je versheidslogica rond die buckets.

De Cloudflare realiteit
Indeed zit achter Cloudflare, dus een datacenter IP met een kale aanvraag krijgt vaak een uitdaging in plaats van resultaten. De oplossingen zijn de gebruikelijke anti-bot stack: een coherente browser User-Agent en header set, en — de grootste hefboom — een residentiële exit die niet vooraf als automatisering is gescoord. Een residentiële proxy presenteert zich als de verbinding van een echte gebruiker, wat ervoor zorgt dat Cloudflare de pagina blijft serveren. Wanneer er een uitdaging verschijnt, is het matchen van de browser fingerprint net zo belangrijk als het IP; onze gids over het omzeilen van Cloudflare in 2026 behandelt waar de grens ligt.
De snelkoppeling: de jobs SERP verticaal
Als je eigenlijk arbeidsmarktgegevens wilt — niet specifiek de HTML van Indeed — is er een schoner pad. Google's jobs verticaal aggregeert vacatures van Indeed en vele andere borden, en een SERP API retourneert die jobs verticaal als geparseerde JSON: titel, bedrijf, locatie, geplaatste datum en bron, geen CSS-selectors om te onderhouden en geen Cloudflare om te bestrijden. Je ruilt wat veldniveau controle in voor een stabiele gestructureerde feed over veel borden tegelijk, wat voor geaggregeerde wervingsanalyses meestal de betere deal is. Het is dezelfde redenatie achter het bouwen van een vacaturebord-aggregator op een SERP-feed in plaats van één scraper per site.
Trek de jobs verticaal als schone JSON
Waar de gegevens goed voor zijn
Naast een vacaturezoektocht drijven deze gegevens echte analyses: salarisbenchmarking per rol en stad, vraagtracking voor specifieke vaardigheden in de tijd, concurrentie wervingssignalen (een rivaal die een nieuw team bemant is een strategische aanwijzing), en verrijking — het koppelen van de openstaande functies van een bedrijf met firmographics voor outbound. Koppel het met Glassdoor salarisgegevens en je krijgt een vollediger comp beeld dan beide bronnen alleen.

Veelgestelde vragen
Kun je legaal Indeed vacatures scrapen?
Vacatures zijn openbare gegevens, en het verzamelen van openbaar zichtbare lijsten is over het algemeen verdedigbaar, maar de voorwaarden van Indeed beperken geautomatiseerde toegang en je moet persoonlijke gegevens vermijden en respecteer rate limits. Veel teams omzeilen de vraag over de voorwaarden door de geaggregeerde jobs SERP verticaal te gebruiken in plaats van Indeed direct te scrapen. Dit is algemene informatie, geen juridisch advies — bekijk de huidige voorwaarden voordat je een groot project start.
Waarom blijft mijn Indeed scraper breken?
Twee redenen. Ten eerste roteert Indeed zijn gehashte CSS-klassenamen, dus selectors die daarop zijn vastgepind falen binnen weken — anker in plaats daarvan op data-testid attributen en de vacature sleutel. Ten tweede begint Cloudflare je IP uit te dagen zodra het wordt gemarkeerd; een residentiële exit en een coherente browser fingerprint houden de echte pagina aan het laden. Los beide op en de scraper stabiliseert.
Hoe scrape ik banen uit meerdere landen?
Indeed bedient elk land vanuit zijn eigen subdomein (www.indeed.com, uk.indeed.com, de.indeed.com, enzovoort). Vraag het juiste subdomein op en routeer via een proxy exit in dat land zodat het verzoek geografisch consistent is — anders krijg je mogelijk niet-overeenkomende of omgeleide resultaten. De jobs SERP verticaal accepteert ook een landparameter als je liever geen subdomeinen beheert.
Is de Google jobs SERP beter dan het scrapen van Indeed?
Voor geaggregeerde arbeidsmarktanalyses meestal wel. De jobs verticaal retourneert vacatures van Indeed en vele andere borden als gestructureerde JSON, zonder roterende selectors en zonder Cloudflare uitdaging om te hanteren. Je verliest enkele Indeed-specifieke velden, maar je krijgt een stabiele multi-source feed en veel minder onderhoud. Scrape Indeed direct alleen wanneer je velden nodig hebt die op Indeed's eigen pagina's staan.
Indeed beloont de duurzame aanpak: anker op stabiele attributen, dedupliceer op vacature sleutel, pagineer per tientallen, en klop met een residentieel IP zodat Cloudflare je bedient. En wanneer je alleen het arbeidsmarktsignaal nodig hebt in plaats van de exacte HTML van Indeed, geeft de jobs SERP verticaal het aan je als JSON. Kies het pad dat past bij hoeveel veldcontrole je daadwerkelijk nodig hebt.