Anmelden

Wie das SDK aufgebaut ist

Das Python SDK ist ein dünner, abhängigkeitsarmer Wrapper um dieselbe HTTP-API, die in der API Reference dokumentiert ist. Jeder Crawling API Parameter, den Sie bei einem rohen HTTP-Aufruf als Query-String anhängen würden, ist im SDK als Keyword im Options-Dict erreichbar - Namen, Defaults und Verhalten sind eins zu eins gemappt. Es gibt keinen Parameter, den das SDK hinzufügt; es gibt keinen Parameter, den das SDK versteckt.

Was Sie davon haben, es statt requests direkt zu verwenden:

  • URL-Encoding, Parameter-Validierung und Response-Parsing werden out of the box erledigt - Ihr Anwendungscode liest sich wie Produktcode, nicht wie HTTP-Plumbing.
  • Eine einzige Client-Klasse pro Crawlbase API, alle mit derselben Konstruktor- / Aufrufform — wenn Sie eine benutzt haben, haben Sie alle benutzt.
  • Sinnvolle Defaults (90-Sekunden-Timeout, JSON-Parsing von format=json-Responses, automatisches UTF-8-Decoding), die dem entsprechen, was die meisten Teams bei ihrer ersten Integration von Hand konfigurieren.
  • Eine kleine Oberfläche zum Lernen - fünf Client-Klassen, zwei Verben (get / post), eine Response-Form.

Das SDK ist Open Source, MIT-lizenziert und nimmt Community-PRs auf github.com/crawlbase/crawlbase-python entgegen. Die meisten gemeldeten Issues landen innerhalb eines Sprints in einem Release.

Installation

Aktuelle Version auf PyPI. Erfordert Python 3.7+; getestet bis Python 3.13.

pip install crawlbase

# Or via Poetry / uv / pip-tools
poetry add crawlbase
uv add crawlbase

Quellcode auf GitHub. Issues + PRs willkommen.

Authentifizierung

Jede Crawlbase API authentifiziert sich mit demselben Token-Modell - es gibt keinen separaten API-Key pro Produkt. Zwei Token-Typen liegen auf einem einzigen Konto:

  • Normal Token (TCP) - für statisches HTML, JSON-Endpoints, alles, was keinen Browser benötigt. Schneller + günstiger.
  • JavaScript Token - für SPAs, lazy-loaded Feeds und jedes Ziel, das Inhalte hinter clientseitigem Rendering versteckt. Erforderlich für die Nutzung von page_wait, ajax_wait, scroll und css_click_selector.

Verwenden Sie in Produktion Umgebungsvariablen, anstatt Tokens hart zu kodieren. Das SDK liest selbst keine Env-Variablen - das ist eine bewusste Entscheidung, damit Sie die Kontrolle darüber behalten, woher die Credentials kommen - aber das idiomatische Muster ist:

import os
from crawlbase import CrawlingAPI

# Pick the right token at instantiation; the SDK doesn't switch
# tokens per-call, so keep two clients if you alternate.
api = CrawlingAPI({'token': os.environ['CRAWLBASE_TOKEN']})
js  = CrawlingAPI({'token': os.environ['CRAWLBASE_JS_TOKEN']})

res = api.get('https://github.com/anthropic')
res = js.get('https://feed.example.com', {'page_wait': 2000})

Vollständiges Token-Modell + Dashboard-Speicherorte auf der Authentication-Seite.

Schnellstart

Drei Zeilen vom Import bis zum gecrawlten HTML:

from crawlbase import CrawlingAPI

api = CrawlingAPI({'token': 'YOUR_TOKEN'})
res = api.get('https://github.com/anthropic')

if res['status_code'] == 200:
    print(res['body'])

Verzweigen Sie über status_code (den HTTP-Status der SDK-Anfrage an Crawlbase) und pc_status (das Crawlbase-Urteil - siehe Errors unten), wenn Sie entscheiden, ob ein Retry erfolgen soll. Der Body ist standardmäßig Bytes; übergeben Sie 'format': 'json', um stattdessen einen JSON-Envelope statt rohen Seiteninhalt zu erhalten.

Alle APIs in einem Paket

Jede Crawlbase API hat eine passende Client-Klasse. Gleicher Konstruktor, gleiche get / post-Verben. Wählen Sie die Klasse danach aus, was Sie tun; im Hintergrund treffen sie alle einen anderen Endpoint derselben Plattform.

from crawlbase import (
    CrawlingAPI,    # general-purpose page fetch (HTML / JSON / etc.)
    ScraperAPI,     # parsed JSON for supported sites (Amazon, Google, etc.)
    LeadsAPI,       # domain-scoped email extraction (legacy)
    ScreenshotsAPI, # screenshots of any URL
    StorageAPI,     # Cloud Storage CRUD
)

token = {'token': 'YOUR_TOKEN'}

crawl   = CrawlingAPI(token)
scraper = ScraperAPI(token)
leads   = LeadsAPI(token)
shots   = ScreenshotsAPI(token)
storage = StorageAPI(token)

# Push high-volume async jobs to the Enterprise Crawler via the
# Crawling API: api.get(url, {'async': True, 'callback': '...',
# 'crawler': 'YourCrawler'}). See /docs/crawler for the queue
# workflow.

Häufige Muster

JavaScript-Rendering

Für SPAs, lazy-geladene Feeds und Seiten, deren initiales HTML leer ist, instanziieren Sie mit dem JavaScript token und übergeben eine beliebige Kombination aus page_wait, ajax_wait, scroll und css_click_selector. Reihenfolge zum Mitdenken: ein fester Wait, dann Network-Idle, dann Scroll für Lazy-Load, dann Click für ein etwaiges Gating-UI-Element.

api = CrawlingAPI({'token': 'YOUR_JS_TOKEN'})
res = api.get('https://spa.example.com', {
    'page_wait': 2000,
    'ajax_wait': True,
    'scroll': True,
})

Einen eingebauten Scraper verwenden

Überspringen Sie den Parser komplett auf unterstützten Sites. Übergeben Sie 'scraper': 'NAME', und der Response-body wird zu einem JSON-String mit den strukturierten Feldern, die auf der jeweiligen Scraper-Seite dokumentiert sind.

import json
from crawlbase import ScraperAPI

api = ScraperAPI({'token': 'YOUR_TOKEN'})
res = api.get(
    'https://www.amazon.com/dp/1098145356',
    {'scraper': 'amazon-product-details'}
)
data = json.loads(res['body'])
print(data['name'], data['price'])

Geo-Routing

Übergeben Sie 'country'='ISO', um den Crawl über die Exit-Nodes des entsprechenden Landes zu leiten. Verwenden Sie dies immer, wenn das Ziel lokalisierten Inhalt basierend auf der IP ausliefert - die meisten Retailer, alle SERPs, geo-eingeschränkte Streaming-Seiten.

api = CrawlingAPI({'token': 'YOUR_TOKEN'})

# Hit the German Amazon catalog from a German residential IP
res = api.get(
    'https://www.amazon.com/dp/1098145356',
    {'country': 'DE'}
)

Async mit Retries

Die empfohlene Retry-Form: exponentielles Backoff, gedeckelt auf 3-5 Versuche, Retry nur bei vorübergehenden Fehlern (5xx oder leerer Body), kein Retry bei 4xx (die Anfrageform ist falsch und korrigiert sich nicht von selbst).

import time, random
from crawlbase import CrawlingAPI

api = CrawlingAPI({'token': 'YOUR_TOKEN'})

def crawl(url, attempts=5):
    for i in range(attempts):
        res = api.get(url)
        # 200 from Crawlbase + non-empty body from the target
        if res['status_code'] == 200 and int(res.get('pc_status', 0)) == 200:
            return res
        # Don't bother retrying client errors (4xx)
        if 400 <= res['status_code'] < 500:
            raise ValueError(f"client error {res['status_code']}: {url}")
        # Exponential backoff with jitter
        time.sleep(random.uniform(0, 2 ** i))
    raise RuntimeError(f'Failed: {url}')

Async-Crawls + Webhooks

Fire-and-forget-Modus. Der SDK-Aufruf kehrt sofort mit einer rid zurück; Crawlbase POSTet das Ergebnis an Ihre Callback-URL, sobald die Seite bereit ist. Nützlich für Batch-Jobs und langsame Ziele, bei denen Sie nicht möchten, dass eine synchrone Anfrage 30+ Sekunden lang einen Concurrency-Slot belegt.

api = CrawlingAPI({'token': 'YOUR_TOKEN'})
res = api.get('https://example.com', {
    'async': True,
    'callback': 'https://your-app.com/webhook',
})
rid = res['rid']  # use this to correlate the eventual webhook delivery

# Webhook handler (Flask / FastAPI / etc.) receives a POST with:
#   { rid, url, original_status, pc_status, body }

Für sehr hohe Volumina (Millionen von URLs) verwenden Sie den Enterprise Crawler, der vor genau dieser Async-Pipeline sitzt — mit Retries, Rate-Management und Ergebniszustellung.

Sticky Sessions

Manche Flows benötigen dieselbe Residential-IP über mehrere Aufrufe hinweg - ein Checkout, eine paginierte Suche, eine eingeloggte Session. Übergeben Sie 'cookies_session' mit einem stabilen Identifier, und Crawlbase verwendet denselben Exit-Node für ca. 30 Minuten wieder.

api = CrawlingAPI({'token': 'YOUR_JS_TOKEN'})

session = f'checkout-{user_id}'
api.get('https://shop.example.com/cart',     {'cookies_session': session})
api.get('https://shop.example.com/checkout', {'cookies_session': session})
api.get('https://shop.example.com/confirm',  {'cookies_session': session})

Errors & Retries

Die Crawlbase-Plattform liefert zwei Statuscodes bei jeder Response: den SDK-eigenen status_code (den HTTP-Status der Anfrage an Crawlbase selbst) und pc_status (das Crawlbase-Urteil über das Ziel - siehe die Crawling API Errors-Tabelle für die vollständige Liste). Verzweigen Sie immer über pc_status, wenn Sie entscheiden, ob ein Retry erfolgen soll - ein Ziel kann 200 mit leerem Body zurückgeben, dann ist status_code gleich 200, aber pc_status ist 520.

res = api.get(url)
pc = int(res.get('pc_status', 0))

if pc == 200:
    use(res['body'])
elif pc in (520, 525):
    # 520 = empty body, 525 = anti-bot couldn't be solved.
    # Switch to JS token and retry.
    retry_with_js_token(url)
elif pc in (521, 522, 523):
    # Target unreachable or timed out. Retry with backoff.
    schedule_retry(url)
else:
    log.error('crawl failed', extra={'url': url, 'pc_status': pc})

Alle Retries gegen die Plattform sind kostenlos - nur erfolgreiche Responses (pc_status: 200) werden auf Ihre Quota angerechnet. Das macht aggressives Backoff günstig; die einzigen realen Kosten eines Retries sind zusätzliche Latenz.

Performance & Best Practices

  • Verwenden Sie einen einzigen Client pro Token wieder. Der Konstruktor ist günstig, aber jede Instanz öffnet ihren eigenen Connection-Pool. Bauen Sie ihn einmal auf Modul-Ebene und teilen Sie ihn über alle Aufrufe.
  • Verwenden Sie den günstigsten Token, der funktioniert. Setzen Sie nicht standardmäßig auf das JavaScript token «zur Sicherheit» - Requests mit dem Normal token sind schneller und nutzen weniger Concurrency. Steigen Sie erst auf JS um, wenn die Normal-Response leer oder anti-bot-blockiert ist.
  • Bevorzugen Sie ajax_wait gegenüber page_wait. Feste Verzögerungen verbrauchen Concurrency bei jeder Anfrage, selbst bei schnellen. ajax_wait kehrt in dem Moment zurück, in dem die Seite Network-Idle erreicht.
  • Für Batch-Jobs: async + Webhook, oder Push an den Enterprise Crawler. Der synchrone Modus ist der richtige Default für Ad-hoc- und interaktive Nutzung; für anhaltend hochvolumige Submission wechseln Sie auf async, sodass Ihr Concurrency-Slot in dem Moment frei wird, in dem eine Anfrage eingereiht ist, statt erst, wenn sie abgeschlossen ist.
  • Beobachten Sie den Response-Header remaining. Er enthält die Anzahl der Concurrency-Slots, die Ihnen noch übrig bleiben - ein gesunder Client fährt proaktiv zurück, bevor er das Limit erreicht, anstatt auf 429er zu reagieren.

Methodenreferenz

Alle Client-Klassen teilen dieselbe Oberfläche. Der Konstruktor nimmt ein einzelnes Options-Dict; die Verben spiegeln die zugrunde liegenden HTTP-Methoden.

CrawlingAPI({'token': T, 'timeout': N})
Konstruktor
Initialisiert einen Client mit Ihrem Token. Optional: 'timeout' in Sekunden (Default 90) - gilt für den HTTP-Call des SDK an Crawlbase, nicht für den Upstream-Crawl.
.get(url, options=None)
Methode
Sendet einen GET. options ist ein Dict, das einen beliebigen Crawling API-Parameter auf seinen Wert abbildet. Gibt ein Response-Dict zurück.
.post(url, data, options=None)
Methode
Sendet einen POST. data ist der Body - übergeben Sie ein Dict für form-encoded, einen String für raw. options funktioniert genauso wie bei .get.

Form der Response (Dict, alle Keys vorhanden, auch wenn ihr Wert leer ist):

status_code
int
HTTP-Status der Anfrage des SDK an Crawlbase. 200 bedeutet, dass der Request angenommen wurde; prüfen Sie pc_status für das Ergebnis beim Ziel.
pc_status
int
Crawlbase-Urteil zum Ziel. Verzweigen Sie hieran für Retry-Entscheidungen.
original_status
int
HTTP-Status, den die Zielseite an Crawlbase zurückgegeben hat.
url
str
Finale URL nach Redirects auf Zielseite.
body
bytes | str
Seiteninhalt (oder JSON-String, wenn format=json / scraper= verwendet wurde).
headers
dict
Response-Header von der Zielseite.
rid
str
Request-ID (wenn async=true oder store=true).