So scrape ich Craigslist mit Python (ohne gesperrt zu werden)

Zuletzt aktualisiert am June 18, 2026
So scrape ich Craigslist mit Python (ohne gesperrt zu werden)

Craigslist verbucht noch immer rund 108 Millionen monatliche Besuche über etwa 700 lokale Seiten – und eine öffentliche API sucht man bis heute vergebens. Wer strukturierte Daten aus Wohnungsanzeigen, Gebrauchtwagen, Jobangeboten oder Gig-Listings braucht, kommt am Scraping schlicht nicht vorbei.

Craigslists eigenes Anti-Bot-System kennt dabei keine Gnade. Es setzt weder auf Cloudflare noch auf DataDome – im Hintergrund läuft ein selbst gebauter nginx-basierter Rate Limiter, der seit über zehn Jahren immer weiter geschliffen wurde. Wer ihn falsch anspricht, kassiert oft schon vor dem zweiten Kaffee einen knappen 403. Ich habe lange verschiedene Ansätze gegen Craigslists Schutzmechanismen ausprobiert, und genau daraus ist dieser Leitfaden geworden: ein aktuelles Python-Tutorial für 2025, das über alle Kategorien hinweg funktioniert, JSON-LD-Extraktion erklärt (der größte Sprung gegenüber veralteten Guides), ehrliche Anti-Ban-Strategien, die rechtliche Lage und eine No-Code-Alternative für alle, die die Daten wollen, aber keinen Code schreiben möchten.

Was bedeutet es, Craigslist mit Python zu scrapen?

Beim Web Scraping von Craigslist rufst du mit Python-Skripten Craigslist-Seiten programmgesteuert auf, ziehst die relevanten strukturierten Daten heraus – Titel, Preise, Beschreibungen, Bilder, Standorte und Veröffentlichungsdaten – und speicherst sie in einer Tabelle, Datenbank oder JSON-Datei.

Python drängt sich dafür geradezu auf, weil das Ökosystem an Bibliotheken so stark ist. Mit requests, BeautifulSoup, lxml und curl_cffi baust du einen funktionierenden Craigslist-Scraper in weniger als 100 Zeilen. Dazu kommt eine riesige Community – wenn Craigslist etwas umstellt (und das tut es), hat meist schon jemand die Lösung parat.

Wichtig ist: Craigslist bietet keine öffentliche Read-API an. Die einzige offizielle Programmschnittstelle ist die Bulk Posting Interface (BAPI) – und die ist rein zum Schreiben da. Zugelassene, kostenpflichtige Anbieter können darüber Inserate einstellen, aber keine Daten abrufen. Jedes Produkt mit dem Etikett „Craigslist API“, das du auf Drittplattformen findest, ist in Wahrheit ein inoffizieller Scraper und kein offiziell unterstützter Endpunkt. Willst du Massendaten, scrapst du.

Warum Craigslist scrapen? Praxisbeispiele aus der echten Welt

Craigslist ist weit mehr als ein Umschlagplatz für gebrauchte Sofas. Es ist ein riesiger, laufend aktualisierter Datensatz über dutzende Kategorien hinweg. Davon profitieren unter anderem:

AnwendungsfallWer davon profitiertWelche Daten extrahiert werden
Beobachtung von Miet- und ApartmentpreisenMakler, Mieter, PropTech-UnternehmenPreis, Quadratmeter, Schlafzimmer, Stadtteil, Breitengrad/Längengrad
Analyse des GebrauchtwagenmarktsAutohäuser, Consumer-Apps, ForschendePreis, Marke, Modell, Baujahr, Kilometerstand, Zustand
Forschung zum ArbeitsmarktRecruiter, Arbeitsökonom:innen, Workforce-Analyst:innenTitel, Vergütung, Beschäftigungsart, Veröffentlichungsdatum
Lead-GenerierungVertriebsteams, DienstleisterKontaktdaten, Firmennamen, Servicegebiet
Wettbewerbsfähige PreisbeobachtungLokale Dienstleister, E-Commerce-TeamsServicepreise, Beschreibungen, Einsatzgebiete

Das am häufigsten zitierte akademische Beispiel ist das Kaggle-Dataset „Used Cars Dataset“ – rund 500.000 US-Gebrauchtwagenanzeigen mit 26 Merkmalen. Es lieferte die Grundlage für dutzende Arbeiten, darunter eine ResearchGate-Studie aus 2024 zu Dynamiken des US-Gebrauchtwagenmarkts. Hedgefonds haben aggregierte Craigslist-Mietdaten gekauft, um Miettrends zu analysieren. Und Vertriebsteams scrapen die Kategorien Services und Gigs regelmäßig für die Lead-Gewinnung.

Die Rechnung ist denkbar einfach: 8 Stunden manuelles Kopieren und Einfügen gegen etwa 10 Minuten mit einem sauber gebauten Scraper.

craigslist_stats_55285c3a34.png

Craigslist mit Python scrapen: Jede Kategorie, nicht nur Autos

Fast jeder Craigslist-Scraping-Guide, den ich gefunden habe, dreht sich nur um „cars-for-sale“ – ungefähr so, als würde man ein Google-Tutorial schreiben, das ausschließlich die Bildersuche erklärt. Craigslist hat aber dutzende Kategorien, und die URL-Strukturen unterscheiden sich je nach Bereich.

Die Grundstruktur lautet immer: https://{city}.craigslist.org/search/{category_slug}

Tauschst du Stadt-Subdomain und Slug aus, scrapst du auf einmal eine ganz andere Kategorie. Hier eine Referenztabelle der beliebtesten Bereiche (Stand: April 2025):

KategorieURL-SlugTypische zu extrahierende Felder
Apartments / Wohnen/search/apaPreis, Quadratmeter, Schlafzimmer, Lage, Haustierregelung
Autos & Trucks/search/ctaPreis, Marke, Modell, Baujahr, Kilometerstand
Jobs/search/jjjTitel, Unternehmen, Gehalt, Beschäftigungsart
Services/search/bbbTitel, Beschreibung, Telefonnummer, Region
Gigs/search/gggTitel, Vergütung, Datum, Kategorie
Zu verkaufen (allgemein)/search/sssTitel, Preis, Zustand, Ort

Du kannst auch Suchparameter für Filter kombinieren:

ParameterZweckBeispiel
queryVolltext-Suchbegriff?query=studio
min_price / max_pricePreisbereich&min_price=1500&max_price=3000
hasPicNur Beiträge mit Bildern&hasPic=1
postedTodayLetzte 24 Stunden&postedToday=1
sortSortierung&sort=priceasc
sSeitenoffset (120 pro Seite)?s=120

Eine URL wie https://newyork.craigslist.org/search/apa?min_price=1500&max_price=3000&hasPic=1 liefert dir somit Apartments in New York zwischen 1.500 und 3.000 US-Dollar mit Fotos. Jeder Python-Scraper in diesem Leitfaden funktioniert über alle Kategorien hinweg – du musst nur den Slug anpassen.

Craigslist-HTML-Selektoren 2025: alt vs. neu (und der JSON-Abkürzungsweg)

Der häufigste Grund, warum Craigslist-Scraper auseinanderfallen, sind Änderungen an der HTML-Struktur. Folgst du einem Tutorial aus 2022, das .result-row oder .result-info verwendet, ist dein Scraper längst tot.

Craigslist hat sein Markup für die Suchergebnisse 2023–2024 neu aufgebaut. Die alten Klassennamen existieren zwar noch innerhalb neuer Wrapper, aber wenn du sie auf oberster Ebene im DOM ansprichst, bekommst du eine leere Liste zurück. Das hat sich geändert:

ElementAlter Selektor (vor 2024)Aktueller Selektor (2025)
Container des Inserats.result-info.cl-search-result
Titel-Link.result-title.posting-title a
Preis.result-price.priceinfo
Metadaten (Gebiet).result-hood.meta

Hier liegt aber der eigentliche Durchbruch – und genau das trennt einen wirklich aktuellen 2025-Scraper von allen älteren Ansätzen: Du musst Suchergebnisse gar nicht per HTML parsen.

Craigslist bettet inzwischen jedes sichtbare Inserat in einem <script id="ld_searchpage_results">-Tag als strukturierten JSON-LD-Datensatz ein. Ein einziger requests.get()-Aufruf liefert die vollständige schema.org-ItemList mit allen Anzeigen der Seite – Titel, Preis, Währung, Standort, Bild-URL, Link zur Detailseite. Kein JavaScript-Rendering nötig. Keine fragile CSS-Selektor-Logik.

Der JSON-LD-Ansatz ist schneller, stabiler und fällt deutlich seltener aus, wenn Craigslist am UI dreht. Genau so arbeiten alle aktiv gepflegten GitHub-Repos, und genau so machen wir es auch im folgenden Tutorial.

Ein Hinweis: Der JSON-LD-Block ist bei Kategorien mit Preisen vorhanden – etwa Wohnungen (apa), Zu verkaufen (sss), Autos (cta) und Housing (hhh). Bei Jobs (jjj), Gigs (ggg), Community (ccc) und Services (bbb) fehlt er oft oder ist nur teilweise da, weil diese Anzeigen keine schema.org/Offer-Preisdaten enthalten. Für diese Kategorien greifst du auf den HTML-Pfad mit .cl-search-result zurück.

Deinen Python-Stack wählen: Requests + BS4 vs. Selenium vs. Playwright

Die Frage poppt in jedem Scraping-Forum auf: „Welche Bibliothek soll ich nehmen?“ Für Craigslist fällt die Antwort deutlich klarer aus als bei vielen anderen Seiten.

Faktorrequests + BeautifulSoupSeleniumPlaywright
Geschwindigkeit5–15 Seiten/Sek. (netzwerkbegrenzt)0,3–1 Seite/Sek.0,5–2 Seiten/Sek.
JS-gerenderte InhalteNeinJaJa
Speicherverbrauch~30–60 MB~400–700 MB~300–500 MB
EinrichtungsaufwandGeringMittelMittel
Anti-Bot-ResistenzGering (braucht Header/Proxies)Mittel (echter Browser)Mittel bis hoch
Bester Craigslist-AnwendungsfallSuchergebnisse (JSON-LD)Detailseiten mit dynamischen InhaltenSkalierbares asynchrones Scraping
LernkurveEinsteigerfreundlichMittelMittel

Craigslists Seiten werden serverseitig gerendert. Der JSON-LD-Block steckt im initialen HTML. Für Lesezugriffe gibt es keine JavaScript-Hürde. Jeder aktiv gepflegte Craigslist-Scraper auf GitHub setzt auf requests + BeautifulSoup oder Scrapy. Selenium oder Playwright tauchen dort praktisch nie auf. Das ist kein Zufall – ein Browser-Automationsframework verschlingt Hunderte Megabyte RAM, ist 10- bis 100-mal langsamer und hinterlässt einen deutlich auffälligeren Fingerabdruck, ohne hier einen echten Mehrwert zu bringen.

Meine Empfehlung:

  • requests + BS4: Hier solltest du anfangen. Die Kombination passt perfekt zur JSON-LD-Extraktion und deckt 95 % aller Craigslist-Use-Cases ab.
  • Selenium: Nur, wenn du mit dynamischen Inhalten auf bestimmten Detailseiten interagieren musst – bei Craigslist eine Seltenheit.
  • Playwright: Wenn du auf Tausende Seiten mit asynchroner Parallelität skalierst – aber ehrlich gesagt ist bei Craigslist meist der Rate Limiter der Engpass, nicht dein Tool.

Eine ausführliche Gegenüberstellung von Playwright vs. Puppeteer und eine Übersicht der besten Python-Web-Scraping-Tools findest du in separaten Beiträgen, falls du tiefer einsteigen willst.

Craigslist scrapen, ohne Python zu schreiben Get Started Free

Die No-Code-Alternative: Craigslist scrapen, ohne Python zu schreiben

Ein kurzer Abstecher vor dem Code – dieser Abschnitt richtet sich an alle, die keine Entwickler sind. Makler, Vertriebsteams, Operations-Manager: Wenn du einfach nur die Daten willst und kein Python schreiben möchtest, gibt es einen schnelleren Weg.

Thunderbit ist ein AI Web Scraper als Chrome-Erweiterung. Damit scrapst du Craigslist in etwa zwei Klicks – ganz ohne Code. Der Ablauf sieht so aus:

  1. Öffne eine beliebige Craigslist-Suchergebnisseite (Wohnungen, Autos, Jobs – egal welche Kategorie).
  2. Klick in der Thunderbit-Seitenleiste auf „KI-Felder vorschlagen“. Die KI liest die Seite und erkennt Spalten wie Titel, Preis, Standort und Link von selbst.
  3. Klick auf „Scrapen“ – die Daten werden in Sekunden extrahiert.
  4. Nutze Unterseiten-Scraping, um jede Detailseite aufzurufen und deine Daten mit vollständigen Beschreibungen, Telefonnummern, Bildern und Attributen anzureichern.
  5. Exportiere direkt nach Google Sheets, Excel, Airtable oder Notion – komplett kostenlos.

Für wiederkehrende Aufgaben – etwa tägliches Monitoring von Apartmentpreisen oder wöchentliche Snapshots von Jobanzeigen – beschreibst du mit Thunderbits Geplantem Scraper den Zeitplan in normaler Sprache, und er läuft automatisch. Keine Cronjobs, kein Server-Setup.

Thunderbit kümmert sich außerdem über den Cloud-Scraping-Modus automatisch um den Anti-Bot-Schutz, sodass du dir um rotierende Proxies oder speziell formulierte Header keine Gedanken machen musst. Willst du es ausprobieren, hol dir die Thunderbit Chrome-Erweiterung und teste es selbst.

Wenn du volle Kontrolle und maximale Anpassung willst, lies einfach weiter und folge der Python-Schritt-für-Schritt-Anleitung.

Schritt für Schritt: Craigslist mit Python scrapen (vollständiges Tutorial)

  • Schwierigkeitsgrad: Mittel
  • Zeitbedarf: ca. 30 Minuten (Setup + erster Scrape)
  • Was du brauchst: Python 3.8+, Chrome-Browser (zum Inspizieren der Seiten), ein Terminal

Schritt 1: Python-Umgebung einrichten

Installiere die benötigten Bibliotheken:

pip install requests beautifulsoup4 lxml

lxml ist optional, beschleunigt das Parsen mit BeautifulSoup aber spürbar. Falls du später Probleme mit TLS-Fingerprinting bekommst (mehr dazu im Anti-Ban-Abschnitt), kannst du zusätzlich curl_cffi installieren:

pip install curl_cffi

Dein Import-Block:

import requests
from bs4 import BeautifulSoup
import json
import csv
import time
import random

Damit hast du jetzt eine saubere Python-Umgebung mit allen nötigen Abhängigkeiten.

Schritt 2: Craigslist-URL für jede Kategorie bauen

Erzeuge die Ziel-URL dynamisch aus Stadt + Kategorie-Slug + optionalen Filtern:

from urllib.parse import urlencode

BASE = "https://{city}.craigslist.org/search/{slug}"

def build_url(city, slug, **params):
    return f"{BASE.format(city=city, slug=slug)}?{urlencode(params)}"

# Beispiel: Wohnungen in New York, 1500–3000 $, mit Fotos
url = build_url("newyork", "apa", min_price=1500, max_price=3000, hasPic=1)
print(url)
# https://newyork.craigslist.org/search/apa?min_price=1500&max_price=3000&hasPic=1

Ersetze "apa" durch "cta" (Autos), "jjj" (Jobs), "bbb" (Services) oder einen anderen Slug aus der Tabelle oben. Tausche "newyork" gegen "sfbay", "chicago", "losangeles" usw.

Schritt 3: Seite abrufen und eingebettetes JSON extrahieren

Sende eine GET-Anfrage mit passenden Headern und parse dann den JSON-LD-Block:

HEADERS = {
    "User-Agent": (
        "Mozilla/5.0 (Windows NT 10.0; Win64; x64) "
        "AppleWebKit/537.36 (KHTML, like Gecko) "
        "Chrome/124.0.0.0 Safari/537.36"
    ),
    "Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8",
    "Accept-Language": "en-US,en;q=0.9",
    "Accept-Encoding": "gzip, deflate, br",
    "Referer": "https://www.craigslist.org/",
    "Sec-Fetch-Dest": "document",
    "Sec-Fetch-Mode": "navigate",
    "Sec-Fetch-Site": "same-origin",
    "Upgrade-Insecure-Requests": "1",
}

session = requests.Session()
r = session.get(url, headers=HEADERS, timeout=20)
r.raise_for_status()

soup = BeautifulSoup(r.text, "html.parser")
tag = soup.select_one("script#ld_searchpage_results")
data = json.loads(tag.text) if tag else {"itemListElement": []}

Ist tag gleich None, fehlt der JSON-LD-Block für diese Kategorie – dann musst du auf das HTML-Parsen ausweichen (siehe Selektortabelle oben). Bei Apartments, Autos und „for sale“-Kategorien ist der JSON-LD-Block in der Regel zuverlässig vorhanden.

Schritt 4: Listendaten in strukturierte Datensätze umwandeln

Geh durch die JSON-Elemente und extrahiere die Felder, die du brauchst:

listings = []
for entry in data["itemListElement"]:
    item = entry["item"]
    offers = item.get("offers", {}) or {}
    addr = (offers.get("availableAtOrFrom") or {}).get("address", {})
    listings.append({
        "name":     item.get("name"),
        "url":      offers.get("url"),
        "price":    offers.get("price"),
        "currency": offers.get("priceCurrency"),
        "locality": addr.get("addressLocality"),
        "region":   addr.get("addressRegion"),
        "image":    item.get("image"),
    })

print(f"Gefunden: {len(listings)} Inserate")

Du solltest etwas wie „Gefunden: 120 Inserate“ sehen (Craigslist zeigt 120 Ergebnisse pro Seite). Manche Anzeigen haben womöglich None als Preis, wenn der Anbieter keinen eingetragen hat – damit solltest du in deiner weiteren Logik sauber umgehen.

Schritt 5: Detailseiten für mehr Daten scrapen

Suchergebnisse liefern nur eine Zusammenfassung. Für vollständige Beschreibungen, Attribute (Schlafzimmer, Quadratmeter, Haustierregelung), Koordinaten und Bilder musst du jede Detailseite öffnen.

def fetch_detail(url, session):
    r = session.get(url, headers=HEADERS, timeout=20)
    r.raise_for_status()
    s = BeautifulSoup(r.text, "html.parser")
    body = s.select_one("#postingbody")
    mp = s.select_one("#map")
    return {
        "description": body.get_text("\n", strip=True) if body else None,
        "attributes":  [x.get_text(" ", strip=True) 
                        for x in s.select("p.attrgroup span, div.attrgroup .attr")],
        "lat": mp.get("data-latitude") if mp else None,
        "lng": mp.get("data-longitude") if mp else None,
        "images": [img["src"] for img in s.select("div.gallery img")],
    }

for item in listings:
    item.update(fetch_detail(item["url"], session))
    time.sleep(random.uniform(3, 6))  # wichtig: Anti-Ban-Jitter

time.sleep(random.uniform(3, 6)) ist kein Luxus. Lässt du das weg, läufst du schon nach wenigen Dutzend Anfragen mit hoher Wahrscheinlichkeit in einen 403. Detailseiten werden serverseitig gerendert und haben stabile Selektoren (#titletextonly, #postingbody, #map), die sich seit ungefähr 2017 kaum verändert haben – eine der wenigen wirklich verlässlichen Konstanten bei Craigslist.

Schritt 6: Pagination handhaben und alle Ergebnisse scrapen

Craigslist nutzt für die Seitennavigation den Offset-Parameter ?s=120. Jede Seite zeigt 120 Ergebnisse, und der maximale Offset liegt typischerweise bei 2999.

def iter_all(city, slug, max_pages=25, **filters):
    for page in range(max_pages):
        offset = page * 120
        url = build_url(city, slug, s=offset, **filters)
        r = session.get(url, headers=HEADERS, timeout=20)
        r.raise_for_status()
        soup = BeautifulSoup(r.text, "html.parser")
        tag = soup.select_one("script#ld_searchpage_results")
        if not tag:
            break
        data = json.loads(tag.text)
        items = data.get("itemListElement", [])
        if not items:
            break
        for entry in items:
            item = entry["item"]
            offers = item.get("offers", {}) or {}
            yield {
                "name": item.get("name"),
                "url": offers.get("url"),
                "price": offers.get("price"),
            }
        time.sleep(random.uniform(2.5, 5.0))

Versuch nicht, in sehr kurzer Zeit Tausende Seiten zu scrapen. Craigslists Rate Limiter arbeitet pro IP, und ein nachhaltiger Durchsatz mit einer einzelnen IP liegt unabhängig von der Bibliothek nur bei etwa 0,3–0,5 Anfragen pro Sekunde. Diese Grenze zieht Craigslist – nicht Python.

Schritt 7: Craigslist-Daten nach CSV, JSON oder Google Sheets exportieren

Speichere deine Ergebnisse:

# CSV
with open("craigslist.csv", "w", newline="", encoding="utf-8") as f:
    w = csv.DictWriter(f, fieldnames=listings[0].keys())
    w.writeheader()
    w.writerows(listings)

# JSON
with open("craigslist.json", "w", encoding="utf-8") as f:
    json.dump(listings, f, indent=2, ensure_ascii=False)

Wenn du den Exportcode lieber ganz überspringst, kannst du mit Thunderbit die Daten direkt und kostenlos aus dem Browser nach Google Sheets, Excel, Airtable oder Notion exportieren. Für Python-Pipelines sind CSV und JSON jedoch die Standardausgaben. Du kannst die Daten auch direkt für Analysen an pandas oder per sqlite3 in eine Datenbank weiterreichen.

Wie du beim Craigslist-Scraping mit Python nicht gesperrt wirst

Die meisten Tutorials huschen über diesen Teil hinweg. Craigslists Anti-Bot-System ist Eigenentwicklung und keine Standardlösung – und es hat ein paar sehr spezifische Eigenheiten.

craigslist_antibot_ae9ddc3f54.png

Realistische Request-Header verwenden

Craigslist prüft Reihenfolge und Vollständigkeit der Header. Eine Anfrage ohne Sec-Fetch-Dest oder mit veraltetem User-Agent fliegt oft schon vor dem eigentlichen Seiteninhalt auf. Das vollständige Chrome-120+-Header-Set (oben in Schritt 3 gezeigt) ist das Minimum. Du kannst den User-Agent pro Session zwischen 5–10 aktuellen Chrome-/Firefox-Desktop-Strings rotieren – aber nicht mitten in der Session wechseln, das wirkt unnatürlich.

Fehlende Sec-Fetch-*-Header sind der häufigste Grund, warum Einsteiger sofort blockiert werden.

Zufällige Pausen zwischen Anfragen einbauen

Der Konsens aus mehreren Quellen (ScrapingBee, Scraperly, Oxylabs, Multilogin) liegt bei zufälligen 2–5 Sekunden zwischen Suchseiten und 3–6 Sekunden zwischen Detailseiten. Feste Intervalle schreien förmlich „Bot“. Nimm time.sleep(random.uniform(2, 5)) – niemals einfach time.sleep(2).

Proxies rotieren, wenn du in größerem Maßstab scrapen willst

Craigslist blockt ganze IP-Bereiche von AWS, GCP und Azure vorab. Datacenter-Proxies sind oft sofort unbrauchbar. Für alles jenseits weniger hundert Seiten brauchst du Residential Proxies mit Rotation, idealerweise alle 20–30 Anfragen gewechselt. Mobile Proxies haben das geringste Erkennungsrisiko, sind aber mit 8–30 US-Dollar pro GB deutlich teurer.

Proxy-TypErkennungsrisiko bei CraigslistKosten (2025)
DatacenterSehr hoch — oft schon beim ersten Request blockiert0,50–2 $/GB
Residential rotatingNiedrig — empfohlen5–15 $/GB
MobileAm niedrigsten8–30 $/GB

Thunderbits Cloud-Scraping-Modus übernimmt die Proxy-Rotation automatisch, wenn du das nicht selbst verwalten möchtest.

CAPTCHAs sauber behandeln

CAPTCHAs kommen auf Craigslist bei Lesezugriffen selten vor – meist tauchen sie beim Posten oder Antworten auf. Erscheint doch eines: mindestens 60 Sekunden pausieren, IP wechseln, Cookies löschen und das Tempo drosseln. Wiederholte CAPTCHAs bedeuten meist, dass dein Tempo zu aggressiv ist – nicht, dass du das Rätsel per Solver „knacken“ solltest.

Rate Limits respektieren und Backoff einbauen

Craigslist liefert 403 (nicht 429), wenn du das Rate Limit reißt. Ein 403 heißt, dass die aktuelle IP auf einer Sperrliste gelandet ist – nicht blind erneut versuchen. IP wechseln, User-Agent ändern und warten.

from requests.adapters import HTTPAdapter
from urllib3.util.retry import Retry

retry = Retry(
    total=5,
    backoff_factor=1.5,  # 1.5, 3, 6, 12, 24s
    status_forcelist=[429, 500, 502, 503, 504],
    allowed_methods={"GET"},
    respect_retry_after_header=True,
)
adapter = HTTPAdapter(max_retries=retry)
session.mount("https://", adapter)

Noch ein Tipp: Aus der Community kommen sehr einheitlich Hinweise, dass 2–6 Uhr Ortszeit der Zielstadt das sicherste Zeitfenster ist – mit etwa 30–40 % niedrigeren Blockraten als tagsüber.

TLS-Fingerprinting — die versteckte Falle

Craigslists Bot-Layer prüft den TLS ClientHello. Die Python-Bibliothek requests (auf OpenSSL-Basis) hat einen JA3-Fingerprint, der zu keinem echten Browser passt. Ein perfekter User-Agent zusammen mit einem nicht-browsertypischen TLS-Fingerprint ist ein offensichtlicher Widerspruch. Abhilfe schafft curl_cffi mit impersonate="chrome124", das den TLS-Handshake von Chrome nachbildet:

from curl_cffi import requests as cffi_requests

r = cffi_requests.get(url, headers=HEADERS, impersonate="chrome124")

Bekommst du trotz sauberer Residential-IP und korrekter Header unerklärliche 403s, steckt sehr wahrscheinlich TLS-Fingerprinting dahinter.

Craigslist robots.txt, Nutzungsbedingungen und ethisches Scraping

Die meisten Guides lassen das komplett aus oder verstecken einen Einzeiler in den FAQs. Da Craigslist 2017 in einem Scraping-Streit ein Urteil über 60,5 Millionen US-Dollar gegen einen Scraper (RadPad) erwirkt hat, verdient das mehr als eine Fußnote.

Was Craigslist in der robots.txt tatsächlich sagt

Die robots.txt-Datei ist überraschend knapp. Sie enthält nur einen User-agent: *-Block mit sieben gesperrten Pfaden:

Disallow: /reply
Disallow: /fb/
Disallow: /suggest
Disallow: /flag
Disallow: /mf
Disallow: /mailflag
Disallow: /eaf

Alle sieben sind interaktive oder verändernde Endpunkte: antworten, melden, vorschlagen, E-Mail an Freund senden. Anzeigenseiten (/search/..., einzelne Post-URLs) sind nicht gesperrt. Eine Crawl-delay-Anweisung gibt es nicht – dennoch setzt Craigslist faktisch über IP-Sperren ein Limit durch.

Die Stadt-Subdomains veröffentlichen außerdem Sitemaps – zum Beispiel https://newyork.craigslist.org/sitemap/index.xml – also den offiziell auffindbaren Weg zu den Inseraten.

Rechtliche Präzedenzfälle: die wichtigen Fälle

Craigslist v. 3Taps (2013, Vergleich 2015): 3Taps scrapte Craigslist-Anzeigen und verkaufte sie weiter. Als Craigslist eine Unterlassungserklärung schickte und die IPs sperrte, umging 3Taps die Blockade mit rotierenden Proxies. Das Gericht wertete das Umgehen von IP-Sperren nach ausdrücklichem Widerruf als „without authorization“ im Sinne des CFAA. 3Taps einigte sich später auf einen Vergleich über 1 Mio. US-Dollar.

Meta v. Bright Data (2024): Ein neueres Urteil stellte fest, dass die Nutzungsbedingungen von Meta das Scraping öffentlich verfügbarer Daten im ausgeloggten Zustand nicht verbieten können. Das Gericht sah einen ausgeloggten Scraper „in derselben Rolle wie ein Besucher“. Für Scraper der Jahre 2024–2025 ist das besonders relevant: Wenn du nie ein Craigslist-Konto anlegst, dich nie einloggst und ausschließlich öffentlich sichtbare Seiten aufrufst, sind die Nutzungsbedingungen unter Umständen nicht als Vertrag gegen dich durchsetzbar.

Die praktische Konsequenz: Das CFAA-Risiko ist nach Van Buren (2021) und hiQ v. LinkedIn (2022) für öffentlich zugängliche Seiten deutlich gesunken. Aber zivilrechtliche Ansprüche nach Landesrecht – etwa trespass to chattels oder misappropriation – bleiben relevant. Genau diese Ansprüche spielten beim 3Taps-Vergleich und beim 60,5-Mio.-Urteil gegen RadPad eine Rolle.

Das hier ist eine Informationsquelle, keine Rechtsberatung. Wenn du Craigslist kommerziell scrapen willst, sprich mit einem Anwalt. Wer aus dem DACH-Raum personenbezogene Daten verarbeitet, sollte zusätzlich die DSGVO beachten.

Praktische Checkliste für ethisches Scraping

  • ✅ Halte dich an alle Disallow-Einträge in der robots.txt – besonders an die sieben Aktions-Endpunkte
  • ✅ Bleibe deutlich unter 1.000 Seiten pro 24 Stunden und IP (Craigslists Nutzungsbedingungen setzen darüber $0,25 pro Seite als pauschalierten Schadensersatz an)
  • ✅ Bleibe ausgeloggt – lege niemals für Scraping einen Craigslist-Account an
  • ✅ Umgehe IP-Sperren nach einem ausdrücklichen Block nicht per Proxy-Wechsel (genau daran ist 3Taps gescheitert)
  • ✅ Baue Pausen zwischen den Anfragen ein – mindestens 2–5 Sekunden
  • ✅ Scrape keine personenbezogenen Kontaktdaten für Spam
  • ✅ Gib rohe Craigslist-Daten nicht einfach weiter und stelle sie nicht als deine eigene Plattform dar
  • ✅ Nutze die Daten für legitime Forschung, Analyse oder private Zwecke
  • ✅ Nutze veröffentlichte Sitemaps, wo immer es geht, statt stumpf alles zu crawlen
  • ✅ Entferne personenbezogene Daten (E-Mails, Telefonnummern) direkt beim Import, wenn du die Daten speicherst

Wir haben einen ausführlicheren Leitfaden zu den rechtlichen Implikationen von Web Scraping, falls du das Gesamtbild verstehen möchtest.

Python vs. No-Code: Welcher Ansatz passt zu dir?

FaktorPython (requests + BS4)Thunderbit (No-Code)
Einrichtungszeit30–60 Min. (installieren, Code schreiben)2 Minuten (Chrome-Erweiterung installieren)
Erforderliches technisches Know-howMittlere Python-KenntnisseKeine
AnpassbarkeitVolle Kontrolle über Logik, Felder und AblaufKI erkennt Felder automatisch; Nutzer kann anpassen
SkalierungUnbegrenzt (mit Proxies und Zeitplänen)Geplanter Scraper für wiederkehrende Aufgaben
Umgang mit SperrenManuell (Header, Pausen, Proxies, TLS)Integriert (Cloud Scraping)
ExportoptionenCSV, JSON (selbst programmieren)Google Sheets, Excel, Airtable, Notion — kostenlos
Am besten geeignet fürEntwickler, Data Scientists, individuelle PipelinesVertrieb, Makler, Operations-Teams

Nimm Python, wenn du maximale Anpassung brauchst, das Ganze in eine größere Datenpipeline einbinden willst oder genau verstehen möchtest, was im Hintergrund passiert. Nimm Thunderbit, wenn du schnell Ergebnisse willst, ohne Code schreiben oder pflegen zu müssen. Beides ist richtig. Es hängt davon ab, wofür du es brauchst und ob du deine Zeit lieber im Terminal oder im Browser verbringst.

Fazit

Craigslist ist eine reichhaltige, laufend aktualisierte Datenquelle für Wohnungen, Autos, Jobs, Services, Gigs und mehr – und ohne öffentliche API ist Scraping der einzige Weg, strukturierte Daten im großen Stil zu bekommen. Der Ansatz für 2025, der wirklich trägt: eingebettetes JSON-LD aus den Suchergebnissen extrahieren statt fragiler CSS-Selektoren, requests + BeautifulSoup statt Selenium verwenden, realistische Header inklusive Sec-Fetch-* setzen, Pausen zufällig variieren und bei mehr als ein paar hundert Seiten Residential Proxies einsetzen.

Die JSON-LD-Methode ist der mit Abstand größte Fortschritt gegenüber älteren Guides. Sie ist schneller, robuster gegenüber Layout-Änderungen und kommt ganz ohne JavaScript-Rendering aus. Kombiniert mit den Anti-Ban-Strategien oben hältst du dir die 403-Fehler vom Leib, die die meisten Scraper ausbremsen.

Willst du den Code lieber ganz überspringen, kann die Thunderbit Chrome-Erweiterung jede Craigslist-Kategorie mit wenigen Klicks scrapen und direkt in deine bevorzugte Tabelle oder Datenbank exportieren. Möchtest du tiefer einsteigen, erklären unsere Leitfäden zu Web Scraping mit Python und zu Best Practices fürs Web Scraping die Grundlagen ausführlicher.

Thunderbit für Craigslist-Scraping testen

KI-Web-Scraper für Craigslist-Daten testen Get Started Free

FAQs

Ist es legal, Craigslist zu scrapen?

Craigslists Nutzungsbedingungen verbieten automatisiertes Scraping und enthalten eine Klausel zu pauschaliertem Schadensersatz (0,25 $ pro Seite über 1.000/Tag). Jüngere Gerichtsurteile – insbesondere Meta v. Bright Data (2024) und hiQ v. LinkedIn (2022) – haben die Haftung nach CFAA für das Scraping öffentlich verfügbarer Daten im ausgeloggten Zustand allerdings eingeschränkt. Zivilrechtliche Ansprüche nach Landesrecht (trespass to chattels) bleiben ein Risiko, vor allem bei kommerzieller Weiterverbreitung. Halte dich an robots.txt, bleibe ausgeloggt, baue Pausen ein und verbreite die Rohdaten nicht weiter. Das ist allgemeine Information, keine Rechtsberatung.

Gibt es eine öffentliche API für Craigslist?

Nein. Craigslist bietet nur eine rein schreibende Bulk Posting Interface (BAPI) für zugelassene, kostenpflichtige Anbieter. Es gibt keine öffentliche Read-API, kein Entwicklerportal und keinen limitierten Datenabruf-Tarif. Jedes „Craigslist API“-Produkt auf Drittplattformen ist in Wahrheit ein inoffizieller Scraper.

Warum bricht mein Craigslist-Scraper immer wieder?

Fast immer liegt es an Änderungen in der HTML-Struktur. Craigslist hat 2023–2024 sein Markup für Suchergebnisse neu geschrieben, und Anleitungen mit alten Selektoren wie .result-row oder .result-info funktionieren nicht mehr. Wechsle zur eingebetteten JSON-LD-Methode (script#ld_searchpage_results), die ist deutlich robuster. Prüfe außerdem, ob deine Header Sec-Fetch-*-Felder enthalten – fehlen sie, wirst du oft sofort blockiert.

Kann ich Craigslist auch ohne Python scrapen?

Ja. Thunderbits AI-Web-Scraper-Chrome-Erweiterung funktioniert auf jeder Craigslist-Seite – Wohnungen, Autos, Jobs, Services. Klick auf „KI-Felder vorschlagen“, damit die Spalten automatisch erkannt werden, klick auf „Scrapen“, um die Daten zu extrahieren, und exportiere anschließend kostenlos nach Google Sheets, Excel, Airtable oder Notion. Kein Coding, kein Setup, keine Proxy-Verwaltung.

Wie oft kann ich Craigslist scrapen, ohne gesperrt zu werden?

Mit einer einzelnen Residential-IP liegt der nachhaltige Durchsatz bei etwa 0,3–0,5 Requests pro Sekunde, wenn du zwischen den Seiten zufällige Pausen von 2–5 Sekunden einbaust. Bleibe unter 1.000 Seiten pro 24 Stunden und IP, um sowohl Sperren als auch die Schwelle für pauschalierten Schadensersatz in Craigslists Nutzungsbedingungen zu vermeiden. Scraping in Nebenzeiten (2–6 Uhr Ortszeit der Zielstadt) drückt die Blockrate um etwa 30–40 %. Bei größeren Mengen solltest du Residential Proxies alle 20–30 Anfragen rotieren.

Mehr erfahren

Ke
Ke
CTO bei Thunderbit | Senior Data Scientist & ML-Experte Mit fast zehn Jahren Erfahrung in Machine Learning und Data Science ist Ke Shen Absolvent der Columbia University und ehemaliger Senior Data Scientist bei Walmart Labs. Mit tiefgreifender, von Fachkollegen anerkannter Expertise in Python, R, Java und Statistik teilt er praxiserprobte Einblicke dazu, wie sich komplexe KI-Algorithmen von der Theorie in eine produktionsreife Architektur überführen lassen.
Inhaltsverzeichnis

Eine Webseite einfach per Anfrage scrapen

Sag einfach in normalem Deutsch, was du brauchst. Oder noch besser: sag gar nichts.

Thunderbit ausprobieren kostenlos
Daten mit KI extrahieren
Daten einfach zu Google Sheets, Airtable oder Notion übertragen
Chrome Store Rating
PRODUCT HUNT#1 Product of the Week