Wie man Indeed-Stellenanzeigen scrapt: Struktur, Blöcke und der SERP-Weg
Indeed ist das größte Jobportal im Internet und ein aktuelles Signal des Arbeitsmarktes. Es steht auch hinter Cloudflare mit wöchentlich rotierenden Klassennamen. So extrahieren Sie es dauerhaft — und wann Sie die Seite ganz meiden sollten.
Indeed zieht rund 542 Millionen Besuche pro Monat an, was seine Anzeigen zu einem der saubersten Live-Signale für den Arbeitsmarkt macht — Nachfrage nach Rollen, Gehaltsbänder, welche Unternehmen Personal aufstocken. Es ist auch eine von Cloudflare geschützte React-Seite, deren sichtbare CSS-Klassennamen oft genug rotieren, um einen naiven Scraper innerhalb von Wochen zu brechen. Dieser Leitfaden zeigt, wie man Indeed-Stellenanzeigen dauerhaft scrapt, wie man sie paginiert und dedupliziert, die Cloudflare-Realität und die Jobs-SERP-Vertikale, die es Ihnen ermöglicht, den Kampf ganz zu umgehen.
Lesen Sie die Suchseite, verankern Sie sich an stabilen Attributen
Die Einheit der Indeed-Daten ist die Suchergebnisseite: Abfrage plus Standort gibt Ihnen eine Seite mit Jobkarten. Die Falle besteht darin, auf die gehashten Klassennamen (Dinge wie eu4oa1w0) zu selektieren, die Indeed regeneriert. Verankern Sie sich stattdessen an den data-testid-Attributen, die weit weniger häufig wechseln:
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")
Jede Karte trägt einen Jobschlüssel (jk) — eine stabile ID, die Sie verwenden, um über Seiten und Läufe hinweg zu deduplizieren. Speichern Sie auf jk, nicht auf URL, da derselbe Eintrag mit unterschiedlichen Tracking-Parametern erscheint.
Paginierung und Länderseiten
Indeed paginiert mit einem start-Parameter, der um 10 erhöht wird. Und es ist nicht eine Seite — jedes Land ist eine Subdomain: www.indeed.com für die USA, uk.indeed.com für das Vereinigte Königreich und so weiter. Passen Sie Ihren Proxy-Exit an das Land an, das Sie abfragen, damit die Anfrage geografisch kohärent ist:
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
Eine Eigenart, die es zu wissen gilt: Indeed's "gepostet innerhalb"-Filter (fromage) akzeptiert nur 1, 3, 7 oder 14 Tage — andere Werte werden ignoriert, also bauen Sie Ihre Frischelogik um diese Zeiträume herum.

Die Cloudflare-Realität
Indeed sitzt hinter Cloudflare, sodass eine Rechenzentrums-IP mit einer einfachen Anfrage oft eine Herausforderung anstelle von Ergebnissen erhält. Die Lösungen sind der übliche Anti-Bot-Stack: ein kohärenter Browser-User-Agent und Header-Set und — der größte Hebel — ein Wohnsitz-Exit, der nicht als Automatisierung vorbewertet ist. Ein Wohnsitz-Proxy präsentiert sich als Verbindung eines echten Nutzers, was Cloudflare dazu bringt, die Seite zu bedienen. Wenn eine Herausforderung auftritt, ist das Anpassen des Browser-Fingerabdrucks genauso wichtig wie die IP; unser Leitfaden zum Umgehen von Cloudflare im Jahr 2026 behandelt, wo die Grenze liegt.
Die Abkürzung: die Jobs-SERP-Vertikale
Wenn Sie tatsächlich Arbeitsmarktdaten wollen — nicht speziell Indeed's HTML — gibt es einen saubereren Weg. Google's Jobs-Vertikale aggregiert Anzeigen von Indeed und vielen anderen Portalen, und eine SERP-API gibt diese Jobs-Vertikale als geparstes JSON zurück: Titel, Unternehmen, Standort, Veröffentlichungsdatum und Quelle, keine CSS-Selektoren zu pflegen und kein Cloudflare zu bekämpfen. Sie tauschen etwas Feldkontrolle gegen einen stabilen strukturierten Feed über viele Portale hinweg ein, was für aggregierte Einstellungsanalysen in der Regel die bessere Wahl ist. Es ist dieselbe Überlegung, die hinter dem Aufbau eines Job-Board-Aggregators auf einem SERP-Feed anstelle eines Scrapers pro Seite steht.
Ziehen Sie die Jobs-Vertikale als sauberes JSON
Wofür die Daten gut sind
Über die Jobsuche hinaus treiben diese Daten echte Analysen an: Gehaltsbenchmarks nach Rolle und Stadt, Nachverfolgung der Nachfrage nach bestimmten Fähigkeiten im Laufe der Zeit, Wettbewerber-Einstellsignale (ein Konkurrent, der ein neues Team aufbaut, ist ein strategischer Hinweis) und Anreicherung — das Verknüpfen der offenen Rollen eines Unternehmens mit Firmendaten für Outbound. Kombinieren Sie es mit Glassdoor-Gehaltsdaten und Sie erhalten ein vollständigeres Vergütungsbild als jede Quelle allein.

Häufig gestellte Fragen
Kann man Indeed-Stellenanzeigen legal scrapen?
Stellenanzeigen sind öffentliche Daten, und das Sammeln öffentlich sichtbarer Einträge ist im Allgemeinen vertretbar, aber die Bedingungen von Indeed schränken den automatisierten Zugriff ein und Sie sollten persönliche Daten vermeiden und Ratenbegrenzungen respektieren. Viele Teams umgehen die Frage der Bedingungen, indem sie die aggregierte Jobs-SERP-Vertikale anstelle des direkten Scrapens von Indeed verwenden. Dies ist allgemeine Information, keine Rechtsberatung — prüfen Sie die aktuellen Bedingungen vor einem großen Projekt.
Warum bricht mein Indeed-Scraper immer wieder zusammen?
Zwei Gründe. Erstens, Indeed rotiert seine gehashten CSS-Klassennamen, sodass Selektoren, die daran gebunden sind, innerhalb von Wochen fehlschlagen — verankern Sie sich stattdessen an data-testid-Attributen und dem Jobschlüssel. Zweitens, Cloudflare beginnt, Ihre IP herauszufordern, sobald sie markiert ist; ein Wohnsitz-Exit und ein kohärenter Browser-Fingerabdruck halten die echte Seite am Laden. Beheben Sie beides und der Scraper stabilisiert sich.
Wie scrapt man Jobs aus mehreren Ländern?
Indeed bedient jedes Land von seiner eigenen Subdomain (www.indeed.com, uk.indeed.com, de.indeed.com und so weiter). Fragen Sie die richtige Subdomain ab und leiten Sie durch einen Proxy-Exit in diesem Land, damit die Anfrage geografisch konsistent ist — andernfalls können Sie unpassende oder umgeleitete Ergebnisse erhalten. Die Jobs-SERP-Vertikale akzeptiert auch einen Länderparameter, wenn Sie keine Subdomains verwalten möchten.
Ist die Google Jobs-SERP besser als das Scrapen von Indeed?
Für aggregierte Arbeitsmarktanalysen in der Regel ja. Die Jobs-Vertikale gibt Anzeigen von Indeed und vielen anderen Portalen als strukturiertes JSON zurück, ohne rotierende Selektoren und ohne Cloudflare-Herausforderung zu handhaben. Sie verlieren einige Indeed-spezifische Felder, aber Sie gewinnen einen stabilen Multi-Source-Feed und weit weniger Wartung. Scrapen Sie Indeed direkt nur, wenn Sie Felder benötigen, die auf Indeed's eigenen Seiten leben.
Indeed belohnt den dauerhaften Ansatz: Verankern Sie sich an stabilen Attributen, deduplizieren Sie nach Jobschlüssel, paginieren Sie in Zehnerschritten und klopfen Sie mit einer Wohnsitz-IP, damit Cloudflare Sie bedient. Und wenn Sie nur das Arbeitsmarktsignal benötigen, anstatt Indeed's genaues HTML, liefert Ihnen die Jobs-SERP-Vertikale es als JSON. Wählen Sie den Weg, der zu dem passt, wie viel Feldkontrolle Sie tatsächlich benötigen.