Anmelden

Wie das SDK aufgebaut ist

Das Go SDK ist bewusst schlank gehalten. Ein Client, CrawlingAPI, deckt jedes Crawlbase-Produkt über den einheitlichen Crawling API Endpoint ab:

AnwendungsfallIn options übergeben
Einfacher Crawl(nichts, der Standard)
Integrierter Scraper"scraper": "amazon-product-details" (und der Rest des Katalogs)
Screenshot"screenshot": "true"
E-Mail-Extraktion"scraper": "email-extractor"
Async + Webhook"async": "true" + "callback": "https://..."
An Enterprise Crawler übergeben"async": "true" + "callback" + "crawler": "YourCrawler"

Die eigenständigen Endpoints /scraper, /leads und /screenshots (die ältere Crawlbase SDKs mit separaten Client-Klassen umhüllen) sind seit 2024 für Neuanmeldungen geschlossen. Das Go SDK liefert nur den modernen Weg: ein Client, jedes Produkt, keine Altlasten-Klassen.

Was Sie davon haben, es statt net/http direkt zu verwenden:

  • URL-Encoding, Parameter-Validierung und Response-Parsing werden out of the box erledigt.
  • Idiomatische Go-Oberfläche: (result, error)-Rückgaben, benannte Struct-Felder, keine Panics bei Transport-Fehlern.
  • context.Context-Unterstützung bei jedem Verb über *WithContext-Varianten für Cancellation / Deadlines / Trace-Propagation.
  • Sinnvolle Standardwerte (90 Sekunden Timeout, transparente gzip-Dekompression, automatisches JSON-Parsing von format=json- / scraper=-Responses).

Quellcode auf github.com/crawlbase/crawlbase-go. Referenz auf pkg.go.dev. Issues + PRs willkommen.

Installation

Aktuelle Version auf pkg.go.dev. Erfordert Go 1.21+.

go get github.com/crawlbase/crawlbase-go@latest

# Or pin a specific version
go get github.com/crawlbase/[email protected]

Authentifizierung

Jede Crawlbase API authentifiziert sich mit demselben Token-Modell. Zwei Token-Typen existieren in 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, alles, was Inhalte hinter clientseitigem Rendering verbirgt. Erforderlich für die Nutzung von page_wait, ajax_wait, scroll und css_click_selector.

Verwenden Sie in der Produktion Umgebungsvariablen. Das SDK liest die env-Variablen nicht selbst, das ist Absicht, damit Sie die Kontrolle darüber behalten, woher die Credentials kommen. Muster:

package main

import (
 "log"
 "os"

 "github.com/crawlbase/crawlbase-go"
)

func main() {
 // Pick the right token at instantiation; the SDK doesn't switch
 // tokens per-call, so keep two clients if you alternate.
 api, err := crawlbase.NewCrawlingAPI(os.Getenv("CRAWLBASE_TOKEN"))
 if err != nil {
 log.Fatal(err)
 }
 js, err := crawlbase.NewCrawlingAPI(os.Getenv("CRAWLBASE_JS_TOKEN"))
 if err != nil {
 log.Fatal(err)
 }

 api.Get("https://github.com/anthropic", nil)
 js.Get("https://feed.example.com", map[string]string{"page_wait": "2000"})
}

Der Konstruktor gibt crawlbase.ErrTokenRequired zurück, wenn der Token-String leer ist. Vollständiges Token-Modell + Dashboard-Speicherorte auf der Seite Authentifizierung.

Schnellstart

Drei Zeilen vom Import zum gecrawlten HTML:

package main

import (
 "fmt"
 "log"

 "github.com/crawlbase/crawlbase-go"
)

func main() {
 api, err := crawlbase.NewCrawlingAPI("YOUR_TOKEN")
 if err != nil {
 log.Fatal(err)
 }
 res, err := api.Get("https://github.com/anthropic", nil)
 if err != nil {
 log.Fatal(err)
 }
 if res.StatusCode == 200 {
 fmt.Println(res.Body)
 }
}

Verzweigen Sie über res.StatusCode (HTTP-Status des SDK gegenüber Crawlbase) und res.PCStatus (das Crawlbase-Urteil, siehe Errors unten), wenn Sie entscheiden, ob ein Retry erfolgen soll. Übergeben Sie map[string]string{"format": "json"}, um statt rohem Seiteninhalt eine JSON-Hülle zu erhalten (automatisch in res.JSON geparst).

Häufige Muster

JavaScript-Rendering

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

api, _ := crawlbase.NewCrawlingAPI("YOUR_JS_TOKEN")
res, err := api.Get("https://spa.example.com", map[string]string{
 "page_wait": "2000",
 "ajax_wait": "true",
 "scroll": "true",
})

Einen integrierten Scraper verwenden

Sparen Sie sich den Parser auf unterstützten Seiten komplett. Ü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. Der Body wird zusätzlich in res.JSON vorab dekodiert, sodass Sie die Felder direkt auslesen können.

api, _ := crawlbase.NewCrawlingAPI("YOUR_TOKEN")
res, err := api.Get(
 "https://www.amazon.com/dp/1098145356",
 map[string]string{"scraper": "amazon-product-details"},
)
if err != nil {
 log.Fatal(err)
}

if name, ok := res.JSON["name"].(string); ok {
 fmt.Println(name)
}

Geo-Routing

Übergeben Sie "country": "ISO", um den Crawl über die Exit-Nodes des jeweiligen Landes zu leiten. Verwenden Sie das immer dann, wenn das Ziel basierend auf der IP lokalisierten Content ausliefert.

api, _ := crawlbase.NewCrawlingAPI("YOUR_TOKEN")

// Hit the German Amazon catalog from a German residential IP
res, _ := api.Get(
 "https://www.amazon.com/dp/1098145356",
 map[string]string{"country": "DE"},
)

Retry mit Backoff

Empfohlene Retry-Form: exponentielles Backoff, gedeckelt auf 3-5 Versuche, Retry nur bei transienten Fehlern (5xx oder leerer Body), kein Retry bei 4xx.

import (
 "fmt"
 "math"
 "math/rand"
 "time"

 "github.com/crawlbase/crawlbase-go"
)

func Crawl(api *crawlbase.CrawlingAPI, url string, attempts int) (*crawlbase.Response, error) {
 for i := 0; i < attempts; i++ {
 res, err := api.Get(url, nil)
 if err != nil {
 return nil, err
 }
 if res.StatusCode == 200 && res.PCStatus == 200 {
 return res, nil
 }
 if res.StatusCode >= 400 && res.StatusCode < 500 {
 return nil, fmt.Errorf("client error %d: %s", res.StatusCode, url)
 }
 // Exponential backoff with jitter
 d := time.Duration(rand.Float64() * math.Pow(2, float64(i)) * float64(time.Second))
 time.Sleep(d)
 }
 return nil, fmt.Errorf("failed: %s", 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.

api, _ := crawlbase.NewCrawlingAPI("YOUR_TOKEN")
res, _ := api.Get("https://example.com", map[string]string{
 "async": "true",
 "callback": "https://your-app.com/webhook",
})
rid := res.RID // correlate the eventual webhook delivery

// Your net/http handler receives a POST with:
// { rid, url, original_status, pc_status, body }

Für sehr hohe Volumen (Millionen von URLs) übergeben Sie an den Enterprise Crawler, indem Sie "crawler": "YourCrawlerName" zusätzlich zu den async- + callback-Optionen ergänzen.

Sticky Sessions

Manche Flows benötigen dieselbe Residential-IP über mehrere Aufrufe hinweg. Übergeben Sie cookies_session mit einem stabilen Identifier, und Crawlbase verwendet rund 30 Minuten lang denselben Exit-Node weiter.

api, _ := crawlbase.NewCrawlingAPI("YOUR_JS_TOKEN")

session := fmt.Sprintf("checkout-%d", userID)
opts := map[string]string{"cookies_session": session}

api.Get("https://shop.example.com/cart", opts)
api.Get("https://shop.example.com/checkout", opts)
api.Get("https://shop.example.com/confirm", opts)

Screenshots

Übergeben Sie "screenshot": "true", um einen ganzseitigen Screenshot zu erfassen. Der Body kommt als base64-kodiertes Bild zurück; verwenden Sie crawlbase.ImageBytes(res), um in rohe Bytes für os.WriteFile / image.Decode zu dekodieren.

api, _ := crawlbase.NewCrawlingAPI("YOUR_JS_TOKEN")
res, _ := api.Get("https://www.apple.com", map[string]string{
 "screenshot": "true",
})

img, err := crawlbase.ImageBytes(res)
if err != nil {
 log.Fatal(err)
}
os.WriteFile("apple.png", img, 0o644)

Context für Cancellation

Jede Methode hat eine *WithContext-Variante zur Nutzung mit context.Context: nützlich, wann immer der Aufruf Upstream-Cancellation, Deadlines oder Trace-Propagation respektieren soll (HTTP-Handler, gRPC-Server, alles in einer Request-Schleife).

import (
 "context"
 "time"
)

api, _ := crawlbase.NewCrawlingAPI("YOUR_TOKEN")

ctx, cancel := context.WithTimeout(context.Background(), 30*time.Second)
defer cancel()

res, err := api.GetWithContext(ctx, "https://example.com", nil)

Errors & Retries

Die Plattform liefert bei jeder Response zwei Statuscodes: den eigenen res.StatusCode des SDK (HTTP-Status der Anfrage an Crawlbase selbst) und res.PCStatus (Crawlbases Urteil über das Ziel, herausgelöst aus dem pc_status-Response-Header für typisierten Zugriff; die vollständige Liste finden Sie in der Crawling API Errors-Tabelle). Verzweigen Sie immer über PCStatus, wenn Sie entscheiden, ob ein Retry erfolgen soll: Ein Ziel kann 200 mit leerem Body zurückgeben, in welchem Fall StatusCode 200 ist, PCStatus aber 520.

res, err := api.Get(url, nil)
if err != nil {
 return err
}

switch res.PCStatus {
case 200:
 use(res.Body)
case 520, 525:
 // 520 = empty body, 525 = anti-bot couldn't be solved.
 // Switch to JS token and retry.
 retryWithJSToken(url)
case 521, 522, 523:
 // Target unreachable or timed out. Retry with backoff.
 scheduleRetry(url)
default:
 log.Printf("crawl failed: url=%s pc_status=%d", url, res.PCStatus)
}

Alle Retries gegen die Plattform sind kostenlos: nur erfolgreiche Responses (PCStatus: 200) werden auf Ihr Kontingent angerechnet.

Performance & Best Practices

  • Verwenden Sie einen einzigen Client pro Token wieder. Der Konstruktor ist günstig, aber jede *CrawlingAPI-Instanz hat ihren eigenen http.Client mit eigenem Connection-Pool. Erstellen Sie ihn einmal beim Service-Init und teilen Sie ihn über alle Goroutines hinweg (das SDK ist goroutine-safe).
  • Nutzen Sie das günstigste Token, das funktioniert. Greifen Sie nicht standardmäßig zum JavaScript token «für alle Fälle»: Anfragen mit dem Normal token sind schneller und benötigen weniger Concurrency. Eskalieren Sie bei einem PCStatus == 520 oder 525.
  • Bevorzugen Sie ajax_wait gegenüber page_wait. Feste Delays verbrauchen bei jedem Request Concurrency, auch bei schnellen.
  • Für Batch-Jobs: async + Webhook oder Push an den Enterprise Crawler. Goroutine-Pools, die auf synchronen Aufrufen blockieren, lasten Concurrency-Caps schnell aus; async + Webhook gibt den Slot frei, sobald ein Request in die Queue gestellt wurde.
  • Verwenden Sie GetWithContext / PostWithContext in Server-Code. Ein request-bezogener Context propagiert Cancellation, wenn der Caller wegfällt: ohne ihn läuft ein hängender Crawl über die Deadline des Callers hinaus weiter.

Response-Felder

Vollständige Methodensignaturen, godoc und Beispiele pro Methode finden Sie auf pkg.go.dev. Die folgenden Felder sind der Teil, nach dem Crawlbase-Nutzer am häufigsten greifen: das typisierte Urteil über das Ziel, zurückgegeben bei jeder *crawlbase.Response:

StatusCode
int
HTTP-Status der SDK-Anfrage an Crawlbase.
PCStatus
int
Crawlbase-Urteil zum Ziel. Aus dem Response-Header pc_status (oder cb_status) für typisierten Zugriff extrahiert. Verzweigen Sie hierauf für Retry-Entscheidungen.
OriginalStatus
int
HTTP-Status, den die Ziel-Site an Crawlbase zurückgegeben hat.
URL
string
Finale URL nach Redirects auf Zielseite.
Body
string
Seiteninhalt (oder JSON-String, wenn format=json / scraper= verwendet wurde; oder base64-kodiertes Bild bei screenshot=true).
Headers
map[string]string
Response-Header in Kleinbuchstaben.
RID
string
Request-ID: gesetzt, wenn der Aufruf "async": "true" oder "store": "true" enthielt.
JSON
map[string]any
Vorgeparstes JSON, wenn der Response-Content-Type JSON ist. Spart bei Scraper- / format=json-Aufrufen einen json.Unmarshal-Schritt.