Airbnb-Angebotsseiten enthalten genau die Art von Preisinformationen, die für Reiserecherchen, Marktanalysen und Wettbewerbsbeobachtung relevant sind: einen Nachtpreis, einen Angebotsnamen, eine Gästebewertung und den öffentlich angegebenen Standort des Gastgebers. Das Problem ist, dass Airbnb diese Seiten clientseitig rendert und sie aggressiv gegen automatisierten Datenverkehr absichert, sodass eine einfache HTTP-Anfrage nur eine leere Hülle ohne Preisangabe zurückgibt.

Diese Anleitung zeigt Ihnen, wie Sie Airbnb-Preise mit Python zuverlässig scrapen. Sie entwickeln einen kleinen, lauffähigen Scraper, der eine gerenderte Angebotsseite über die Crawling API abruft, die gewünschten Felder mit BeautifulSoup parst und einen sauber strukturierten Datensatz ausgibt. Die Anleitung beschränkt sich bewusst auf öffentliche Angebotsdaten. Der Abschnitt zur Rechtslage am Ende ist kein Boilerplate, lesen Sie ihn, bevor Sie den Scraper auf größere Datenmengen ansetzen.

Was Sie entwickeln werden

Ein Python-Skript, das eine öffentliche Airbnb-Angebots-URL entgegennimmt, das gerenderte HTML über die Crawling API abruft und einen strukturierten Datensatz für das Angebot extrahiert. Als laufendes Beispiel verwenden wir eine einzelne Zimmer-URL und lesen folgende Felder aus:

  • Titel der Angebotsname, der oben auf der Seite angezeigt wird.
  • Preis der Nachtpreis für die angeforderten Daten.
  • Bewertung die öffentliche Gästebewertung, zum Beispiel „4,92".
  • Standort die Gegend, die Airbnb öffentlich für das Angebot anzeigt.

Warum ein einfacher Abruf bei Airbnb scheitert

Wenn Sie eine Airbnb-Zimmer-URL mit einem gewöhnlichen HTTP-Client aufrufen, erhalten Sie eine Antwort mit Status 200 und fast keinen Angebotsdaten im Body. Zwei Faktoren arbeiten gegen Sie. Erstens rendert Airbnb seinen Angebotsinhalt im Browser mit JavaScript, sodass das initiale HTML eine Hülle ist, die erst nach dem Ausführen der Seitenscripte befüllt wird. Zweitens erkennt Airbnb automatisierten Datenverkehr schnell: Rechenzentrum-IPs und Anfragemuster, die nicht wie ein echter Browser aussehen, werden herausgefordert oder blockiert, bevor der gerenderte Inhalt erreicht wird.

Es gibt eine dritte Hürde, die speziell für Preise gilt. Seit Airbnbs Preisüberarbeitung erscheint der Nachtpreis erst, wenn die Seite Ein- und Auscheckterminen sowie eine Gästeanzahl enthält. Die Preisgestaltung ist dynamisch: Dasselbe Angebot zeigt für verschiedene Daten, Wochenenden und Jahreszeiten unterschiedliche Beträge. Ein funktionierender Airbnb-Preis-Scraper benötigt also einen Browser, der die Seite rendert, eine IP-Adresse, die die Plattform als echten Besucher einstuft, sowie Datumsparameter in der URL, damit der Preis überhaupt gerendert wird.

Das lässt sich zwar selbst mit einem Headless-Browser und einem Pool aus rotierenden Residential-Proxies zusammenstellen, doch das Zusammenfügen und Aufrechterhalten dieser Komponenten ist der Großteil der Arbeit. Die Crawling API fasst die schwierigen Teile in einem einzigen Aufruf zusammen: Sie senden ihr die Angebots-URL mit einem JavaScript-Token, sie rendert die Seite hinter einer vertrauenswürdigen IP und gibt Ihnen fertiges HTML zum Parsen zurück.

Warum das JS-Token

Crawlbase bietet zwei Token-Typen. Das normale Token ruft statisches HTML ab; das JavaScript-Token (JS) rendert die Seite zuerst in einem echten Browser. Airbnb ist clientseitig gerendert, daher benötigen Sie hier das JS-Token. Das normale Token gibt dieselbe leere Hülle zurück wie ein einfacher Abruf, ohne Preis zum Parsen.

Voraussetzungen

Bevor Sie mit dem Programmieren beginnen, müssen einige Dinge vorbereitet sein. Keines davon nimmt viel Zeit in Anspruch.

Python-Grundkenntnisse. Sie sollten mit dem Schreiben und Ausführen von Python-Skripten sowie der Installation von Paketen mit pip vertraut sein. Wenn Sie neu beim HTML-Parsen sind, erläutert unsere Anleitung zum Einsatz von BeautifulSoup in Python die Selector-Grundlagen, die dieses Tutorial voraussetzt.

Python 3.8 oder höher. Überprüfen Sie Ihre Version mit python --version. Falls Sie es noch nicht installiert haben, laden Sie es von python.org herunter oder installieren Sie es über eine Distribution wie Anaconda.

Ein Crawlbase-Konto und JS-Token. Melden Sie sich an, öffnen Sie Ihr Dashboard und kopieren Sie Ihr JavaScript-Token (JS) von der Kontodokumentationsseite. Behandeln Sie das Token wie ein Passwort: Es authentifiziert Ihre Anfragen, halten Sie es also aus der Versionskontrolle fern.

Projekt einrichten

Erstellen Sie eine virtuelle Umgebung, damit Projektabhängigkeiten isoliert bleiben, und installieren Sie dann die beiden Bibliotheken, die der Scraper benötigt.

bash
python --version

python -m venv airbnb_env
source airbnb_env/bin/activate

pip install crawlbase beautifulsoup4

Unter Windows aktivieren Sie die Umgebung mit airbnb_env\Scripts\activate anstelle der source-Zeile. Zwei Abhängigkeiten erledigen die Arbeit: crawlbase ist der offizielle Client für die Crawling API, und beautifulsoup4 parst das zurückgegebene HTML, damit Sie einzelne Felder per CSS-Selector extrahieren können.

Schritt 1: Das gerenderte Angebot abrufen

Beginnen Sie mit dem Abruf der fertigen Seite. Importieren Sie die CrawlingAPI-Klasse, initialisieren Sie sie mit Ihrem JS-Token und fordern Sie die Angebots-URL mit angehängten Daten an. Die Überprüfung des Statuscodes vor dem Parsen sorgt dafür, dass Fehler auffallen statt still zu scheitern.

python
from crawlbase import CrawlingAPI

api = CrawlingAPI({"token": "YOUR_CRAWLBASE_JS_TOKEN"})

def crawl(page_url):
    options = {"ajax_wait": "true", "page_wait": 5000}
    response = api.get(page_url, options)
    if response["status_code"] == 200:
        return response["body"].decode("latin1")
    print(f"Request failed: {response['status_code']}")
    return None

if __name__ == "__main__":
    page_url = (
        "https://www.airbnb.com/rooms/721540609203378406"
        "?check_in=2026-07-09&check_out=2026-07-12&adults=2"
    )
    html = crawl(page_url)
    print(html[:500] if html else "No HTML returned")

Die Parameter check_in, check_out und adults sind für die Preisanzeige nicht optional. Ohne sie wird die Seite zwar gerendert, der Nachtpreis bleibt jedoch verborgen, sodass das Preisfeld unabhängig von der Qualität Ihres Selectors leer bleibt. Die beiden Wait-Optionen sind bei einem clientseitig gerenderten Ziel wie diesem wichtig: ajax_wait weist die API an, auf den Abschluss des asynchronen Ladens zu warten, und page_wait hält nach dem Laden für eine feste Anzahl Millisekunden inne, sodass spät gerenderte Elemente erscheinen, bevor die Seite erfasst wird. Fünf Sekunden sind ein vernünftiger Ausgangswert; erhöhen Sie den Wert, wenn der Preis leer zurückkommt. Airbnb liefert Seiten in verschiedenen Zeichensätzen, daher vermeidet die Dekodierung mit latin1 die Byte-Fehler, die eine strenge UTF-8-Dekodierung verursachen kann. Führen Sie das Skript aus, und Sie sollten echtes Angebots-Markup sehen, nicht die leere Hülle eines einfachen Abrufs.

Crawlbase Airbnb Scraper

Airbnb benötigt eine gerenderte Seite hinter einer vertrauenswürdigen IP, in einem einzigen Aufruf. Die Crawling API nimmt ein JS-Token, führt die Seite in einem echten Browser aus, rotiert serverseitig durch Residential-IPs und übergibt Ihnen fertiges HTML. So entfällt das Betreiben einer Headless-Flotte und eines Proxy-Pools. Probieren Sie es zunächst mit einem öffentlichen Angebot im kostenlosen Tarif aus.

Schritt 2: Angebotsfelder mit BeautifulSoup parsen

Mit dem gerenderten HTML laden Sie es in BeautifulSoup und extrahieren jedes Feld anhand seines Selectors. Airbnb ordnet die Kerndetails in stabilen Abschnitts-Containern an, sodass Sie Titel, Preis, Bewertung und Standort einzelnen Selectors zuordnen können. Kapseln Sie die gesamte Extraktion in einem try/except, damit ein fehlendes Feld den Lauf nicht zum Absturz bringt.

python
from bs4 import BeautifulSoup

def text_of(soup, selector):
    el = soup.select_one(selector)
    return el.get_text(strip=True) if el else None

def scrape_listing(html):
    soup = BeautifulSoup(html, "html.parser")

    return {
        "title": text_of(soup, 'div[data-section-id="TITLE_DEFAULT"] h1'),
        "price": text_of(soup, 'div[data-testid="book-it-default"] span > span'),
        "rating": text_of(soup, 'div[data-testid="pdp-reviews-highlight-banner-host-rating"] span'),
        "location": text_of(soup, 'div[data-section-id="LOCATION_DEFAULT"] h3'),
    }

Der Hilfs-Helper text_of erledigt zwei nützliche Dinge auf einmal: Er fragt ein einzelnes Element ab und gibt None zurück, wenn das Element fehlt, anstatt bei einem .get_text()-Aufruf auf nichts zu werfen. Das macht die Extraktion robust, wenn ein Feld fehlt, was häufig vorkommt, da ein brandneues Angebot möglicherweise noch keine Bewertung hat. Die Attribute data-section-id und data-testid von Airbnb sind stabiler als seine gehashten CSS-Klassenbezeichnungen, bevorzugen Sie also diese Datenattribute als Anker, wo immer möglich.

Selectors driften

Das Markup von Airbnb, insbesondere seine gehashten Klassennamen, ändert sich ohne Vorankündigung. Behandeln Sie die oben genannten Selectors als Startvorlage, nicht als Vertrag. Wenn ein Feld als None zurückkommt, untersuchen Sie die Live-Seite in den Entwicklertools Ihres Browsers und aktualisieren Sie den Selector. Periodische Selector-Pflege ist bei jedem Produktions-Scraper normal, kein Zeichen dafür, dass etwas kaputt ist.

Schritt 3: Alles zusammensetzen

Verbinden Sie jetzt den Abruf und das Parsen zu einem lauffähigen Skript. Rufen Sie das gerenderte HTML ab, übergeben Sie es an den Parser und geben Sie den strukturierten Datensatz als JSON aus.

python
import json
from crawlbase import CrawlingAPI
from bs4 import BeautifulSoup

api = CrawlingAPI({"token": "YOUR_CRAWLBASE_JS_TOKEN"})

def crawl(page_url):
    options = {"ajax_wait": "true", "page_wait": 5000}
    response = api.get(page_url, options)
    if response["status_code"] == 200:
        return response["body"].decode("latin1")
    print(f"Request failed: {response['status_code']}")
    return None

def text_of(soup, selector):
    el = soup.select_one(selector)
    return el.get_text(strip=True) if el else None

def scrape_listing(html):
    soup = BeautifulSoup(html, "html.parser")
    return {
        "title": text_of(soup, 'div[data-section-id="TITLE_DEFAULT"] h1'),
        "price": text_of(soup, 'div[data-testid="book-it-default"] span > span'),
        "rating": text_of(soup, 'div[data-testid="pdp-reviews-highlight-banner-host-rating"] span'),
        "location": text_of(soup, 'div[data-section-id="LOCATION_DEFAULT"] h3'),
    }

def main():
    page_url = (
        "https://www.airbnb.com/rooms/721540609203378406"
        "?check_in=2026-07-09&check_out=2026-07-12&adults=2"
    )
    html = crawl(page_url)
    if not html:
        return
    data = scrape_listing(html)
    print(json.dumps(data, indent=2))

if __name__ == "__main__":
    main()

Wie die Ausgabe aussieht

Führen Sie das vollständige Skript mit python scraper.py aus und erhalten Sie einen sauber strukturierten Datensatz für das Angebot, bereit zum Schreiben in JSON, CSV oder eine Datenbank.

json
{
  "title": "Lovely Studio with Burj Khalifa views from Balcony",
  "price": "$187 per night",
  "rating": "4.92",
  "location": "Dubai, United Arab Emirates"
}

Preise über mehrere Daten scrapen

Ein einzelner Datumsbereich ist eine Demo; die interessante Preisarbeit vergleicht dasselbe Angebot über viele Daten, weil sich Airbnb-Preise mit dem Kalender ändern. Die Struktur bleibt dieselbe: Halten Sie eine Liste von Datumspaaren bereit, erstellen Sie für jedes die URL, rufen Sie sie über die Crawling API ab und parsen Sie sie mit derselben Funktion. Da sich die Angebotsstruktur nicht ändert, funktioniert der bereits geschriebene Parser für jedes Datum ohne Änderungen.

python
room_id = "721540609203378406"
date_ranges = [
    ("2026-07-09", "2026-07-12"),
    ("2026-08-13", "2026-08-16"),
]

results = []
for check_in, check_out in date_ranges:
    url = (
        f"https://www.airbnb.com/rooms/{room_id}"
        f"?check_in={check_in}&check_out={check_out}&adults=2"
    )
    html = crawl(url)
    if html:
        row = scrape_listing(html)
        row["check_in"] = check_in
        results.append(row)

with open("airbnb_prices.json", "w") as f:
    json.dump(results, f, indent=2)

Um zunächst Angebots-URLs zu finden, können Sie Airbnbs öffentliche Suchergebnisse mit demselben Muster abrufen, die Zimmer-Links einsammeln und sie dann jeweils mit Daten aufrufen. Halten Sie das Volumen dabei vernünftig und beachten Sie die nachfolgend beschriebenen Erwartungen an die Anfragerate. Wenn Sie dies in ein Preismodell einspeisen möchten, zeigt unsere Anleitung zum Einsatz von Web Scraping für Preisintelligenz, wie Teams einen Datenstrom von Preisen in etwas Entscheidungsrelevantes verwandeln.

Nicht geblockt bleiben

Auch mit gehandhabtem Rendering beobachtet Airbnb scraper-ähnlichen Datenverkehr. Ein paar Gewohnheiten halten einen Lauf gesund, und sie gelten für jedes schwere, JavaScript-lastige Ziel.

  • Anfragen dosieren. Ein Angebot über Dutzende von Datumsbereichen in einer engen Schleife abzufragen ist der schnellste Weg zur Drosselung. Verteilen Sie Anfragen und variieren Sie Ihre Ziele, anstatt einen Pfad mit voller Geschwindigkeit zu crawlen.
  • Auf Rotation setzen. Ein Pool von Residential-IPs verteilt Anfragen auf viele Adressen echter Nutzer, sodass keine einzelne einen Rate-Limit-Trigger auslöst. Die Crawling API erledigt das für Sie; wenn Sie Ihren eigenen Stack aufbauen, ist dies der Teil, den Sie richtig machen müssen.
  • Statuscodes lesen. Ein Lauf, der beginnt, Herausforderungen oder Fehler zurückzugeben, signalisiert Ihnen, dass die aktuelle Rate oder IP-Stufe nicht mehr ausreicht. Behandeln Sie das als Signal zum Zurückrudern, nicht als Rauschen, das Sie ignorieren.

Für das breitere Vorgehen lesen Sie wie man Websites scrapt, ohne blockiert zu werden und den tieferen Einblick in wie man CAPTCHAs beim Web Scraping umgeht. Da Airbnb so JavaScript-lastig ist, lohnt sich auch unsere Anleitung zum Crawlen von JavaScript-Websites. Wenn Sie Ihren eigenen Datenverkehr lieber durch einen rotierenden Pool leiten möchten statt die verwaltete API zu nutzen, bietet der Smart AI Proxy dieselbe Residential-IP-Rotation als Drop-in-Proxy-Endpunkt.

Ob das Scrapen von Airbnb erlaubt ist, hängt von Airbnbs Nutzungsbedingungen, Ihrer Rechtsordnung und dem ab, was Sie mit den Daten machen. Airbnbs Bedingungen schränken den automatisierten Zugriff ausdrücklich ein, sodass Scraping unabhängig von der Sorgfalt Ihrer Werkzeuge gegen diese Bedingungen verstoßen kann. Keiner der hier aufgeführten Codes ändert daran etwas; er macht nur den technischen Teil möglich. Lesen Sie Airbnbs Nutzungsbedingungen und seine robots.txt und behandeln Sie beides als Grenze dessen, was Sie sammeln dürfen.

Ein paar Grundsätze, an denen es sich lohnt festzuhalten. Sammeln Sie nur öffentliche Angebotsdaten: den Titel, den Nachtpreis, die öffentliche Bewertung und den Standort, den Airbnb auf dem Angebot ohne Konto anzeigt. Respektieren Sie Airbnbs angegebene Anfragerate-Erwartungen und halten Sie Ihr Anfragevolumen niedrig genug, dass Sie seine Server nicht belasten. Diese Anleitung beschränkt sich bewusst auf öffentliche Angebotsseiten, da das die Linie ist, die die Arbeit vertretbar macht.

Was sie nicht abdeckt, ist genauso wichtig. Sammeln Sie keine persönlichen Daten von Gastgebern oder Gästen, keine Kontaktinformationen oder Nachrichten. Berühren Sie keine durch Login gesperrten Seiten, keine Konto- oder Buchungsdaten hinter einer Anmeldung oder irgendetwas, das die Umgehung einer Authentifizierung erfordert. Diese Bereiche liegen außerhalb des Umfangs dieser Anleitung und verstoßen gegen Airbnbs Bedingungen. Für kommerzielle oder großvolumige Nutzung ist der richtige Weg eine offizielle Partnerschaft oder API-Vereinbarung mit Airbnb, kein ausgefeilterer Scraper. Nur öffentliche Angebotsdaten.

Zusammenfassung

Wichtigste Erkenntnisse

  • Airbnb ist clientseitig gerendert. Ein einfacher Abruf gibt eine leere Hülle zurück, daher müssen Sie die Seite rendern, bevor Sie sie parsen.
  • Preise brauchen Daten. Übergeben Sie check_in, check_out und adults in der URL, sonst wird der Nachtpreis nie gerendert; Preise sind dynamisch und ändern sich mit dem Kalender.
  • Sie benötigen Rendering und eine vertrauenswürdige IP zusammen. Die Crawling API mit einem JS-Token erledigt beides in einem Aufruf; ajax_wait und page_wait steuern, wie lange auf Inhalte gewartet wird.
  • BeautifulSoup übernimmt die Extraktion. Verankern Sie auf data-section-id- und data-testid-Attributen für Titel, Preis, Bewertung und Standort, und rechnen Sie damit, dass Selectors driften.
  • Bleiben Sie bei öffentlichen Daten. Respektieren Sie Airbnbs AGB und robots.txt, bevorzugen Sie bei kommerzieller Nutzung eine offizielle Partnerschaft und berühren Sie niemals persönliche Daten von Gastgebern oder Gästen, Nachrichten oder durch Login gesperrte Seiten.

Häufig gestellte Fragen

Warum gibt ein einfacher Abruf keinen Preis von Airbnb zurück?

Zwei Gründe. Erstens rendert Airbnb seinen Angebotsinhalt clientseitig mit JavaScript, sodass das rohe HTML eine Hülle ist, die erst nach dem Ausführen der Seitenscripte befüllt wird. Zweitens wird der Nachtpreis erst gerendert, wenn die URL Ein- und Auscheckterminen sowie eine Gästeanzahl enthält. Eine einfache HTTP-Anfrage ohne Daten gibt Status 200 und keinen Preis zurück. Das Rendern der Seite mit dem JS-Token der Crawling API, mit Daten in der URL, ist das, was den Preis erscheinen lässt.

Benötige ich das normale Token oder das JS-Token für Airbnb?

Das JS-Token. Das normale Token ruft statisches HTML ab, das bei Airbnb dieselbe leere Hülle ist wie ein einfacher Abruf. Das JS-Token rendert die Seite in einem echten Browser, bevor es das HTML zurückgibt, sodass die Angebotsfelder einschließlich des Preises vorhanden sind, wenn BeautifulSoup sie parst.

Warum zeigt dasselbe Angebot unterschiedliche Preise?

Airbnb verwendet dynamische Preisgestaltung. Der Nachtpreis ändert sich je nach angeforderten Daten, Wochenenden vs. Werktagen, Nachfrage und Jahreszeit, und einige Gastgeber gewähren Rabatte für längere Aufenthalte. Das ist erwartet, kein Fehler in Ihrem Scraper. Wenn Sie Preise vergleichen möchten, durchlaufen Sie mehrere Datumsbereiche für dasselbe Zimmer und erfassen Sie den Preis für jeden, wie es das Mehrfachdatums-Beispiel in dieser Anleitung zeigt.

Meine Selectors geben None zurück. Was hat sich geändert?

Mit ziemlicher Sicherheit das Markup von Airbnb. Seine gehashten CSS-Klassennamen ändern sich häufig, und Abschnittslayouts verschieben sich im Laufe der Zeit, sodass Selectors, die letzten Monat funktionierten, jetzt brechen können. Verankern Sie auf den stabileren data-section-id- und data-testid-Attributen, wo immer möglich, untersuchen Sie eine Live-Seite in den Entwicklertools Ihres Browsers, wenn ein Feld leer zurückkommt, und aktualisieren Sie den Selector. Periodische Selector-Pflege ist bei jedem Produktions-Scraper normal.

Wie vermeide ich es, beim Scrapen von Airbnb blockiert zu werden?

Halten Sie Ihre Pro-IP-Anfragerate niedrig, variieren Sie Ihre Ziele, anstatt ein Angebot über viele Daten nacheinander zu durchlaufen, und leiten Sie durch rotierende Residential-IPs, damit keine einzelne Adresse einen Rate-Limit auslöst. Die Crawling API verwaltet Rotation und einen vertrauenswürdigen IP-Pool für Sie; wenn Sie Ihren eigenen Stack aufbauen, ist das der Teil, in den Sie investieren sollten. Beobachten Sie die Statuscodes und ziehen Sie sich zurück, wenn Sie beginnen, Herausforderungen zu sehen.

Bleiben Sie bei öffentlichen Angebotsdaten: dem Titel, dem Nachtpreis, der öffentlichen Bewertung und dem Standort, der auf dem Angebot ohne Anmeldung angezeigt wird. Sammeln Sie keine persönlichen Daten von Gastgebern oder Gästen, keine Kontaktdaten, Nachrichten oder irgendetwas hinter einem Login, und umgehen Sie niemals die Authentifizierung. Respektieren Sie Airbnbs Nutzungsbedingungen und robots.txt, und verfolgen Sie bei kommerzieller oder Massennutzung eine offizielle Partnerschaft oder API-Vereinbarung, anstatt einen Scraper gegen die öffentliche Website zu skalieren.

Jetzt loslegen

Crawlen Sie jede Website im großen Maßstab, ohne gegen die Infrastruktur zu kämpfen.

Crawlbase übernimmt Proxys, Fingerprints und CAPTCHAs, damit Ihr Team Datenpipelines ausliefert, statt Crawl-Infrastruktur zu pflegen. 1.000 Anfragen kostenlos, keine Karte erforderlich.

Self-Service · Kein Verkaufsgespräch erforderlich · Enterprise-Crawl-Volumen verfügbar