C# / .NET
Offizieller .NET-Client für die Crawlbase-Plattform. Jede Methode hat eine Sync-Version (z. B. Get) und eine Async-Version (GetAsync) - dasselbe Artefakt, jede API, sinnvolle Defaults.
Aufbau des SDK
Das .NET SDK ist ein dünner Wrapper um dieselbe HTTP API, die in der API Reference dokumentiert ist. Jeder Crawling API-Parameter, den Sie bei einem rohen HTTP-Call als Query String anhängen würden, ist als Dictionary<string, object>-Option erreichbar - Namen, Defaults und Verhalten stimmen eins zu eins überein.
Eine Eigenheit, die Sie vorab kennen sollten: Das .NET SDK legt den Response-Zustand auf der API-Instanz selbst ab, nicht auf einem zurückgegebenen Value-Objekt. Aufrufe wie api.Get(url) geben void zurück; Sie lesen das Ergebnis über api.StatusCode, api.Body und so weiter. Das unterscheidet sich von den Python- / Node- / Ruby- / PHP-SDKs (die ein Response-Objekt zurückgeben). Die Storage API ist die Ausnahme - ihre Methoden geben ein Response-Objekt zurück, das Sie direkt auslesen.
Was Sie bekommen, wenn Sie es statt HttpClient direkt verwenden:
- URL-Encoding, Parameter-Validierung und Response-Parsing out of the box.
- Sync- und Async-Paar bei jedem Verb - wählen Sie, was zu Ihrer Aufrufstelle passt.
- Eine einzige Client-Klasse pro Crawlbase API, alle mit demselben Konstruktor- / Aufruf-Schema.
- Sinnvolle Defaults (90-Sekunden-Timeout, automatisches JSON-Parsing von
format=json-Responses).
Quellcode auf github.com/crawlbase/crawlbase-net.
Installation
Aktuelle Version auf NuGet. Zielt auf .NET 6+; getestet bis .NET 9.
# .NET CLI
dotnet add package CrawlbaseAPI
# Package Manager Console
Install-Package CrawlbaseAPI
# Or in csproj:
# <PackageReference Include="CrawlbaseAPI" Version="1.1.0" />Authentifizierung
Jede Crawlbase API authentifiziert sich mit demselben Token-Modell. Auf einem einzigen Konto liegen zwei Token-Typen:
- Normal Token (TCP) - für statisches HTML, JSON-Endpoints, alles, was keinen Browser benötigt. Schneller und günstiger.
- JavaScript Token
- für SPAs, lazy-geladene Feeds, alles, was Inhalte hinter Client-seitigem Rendering versteckt. Erforderlich, um
page_wait,ajax_wait,scrollundcss_click_selectorzu nutzen.
Verwenden Sie in Produktion Umgebungsvariablen oder die Konfiguration Ihres DI-Containers. Muster:
// Pick the right token at instantiation; the SDK doesn't switch
// tokens per-call, so keep two clients if you alternate.
var api = new Crawlbase.API(Environment.GetEnvironmentVariable("CRAWLBASE_TOKEN"));
var js = new Crawlbase.API(Environment.GetEnvironmentVariable("CRAWLBASE_JS_TOKEN"));
await api.GetAsync("https://github.com/anthropic");
var opts = new Dictionary<string, object> { ["page_wait"] = 2000 };
await js.GetAsync("https://feed.example.com", opts);Vollständiges Token-Modell + Dashboard-Pfade auf der Seite Authentication.
Schnellstart
Drei Zeilen vom Namespace bis zur gecrawlten Response. Beachten Sie, dass der Response-State auf der api-Instanz liegt:
var api = new Crawlbase.API("YOUR_TOKEN");
await api.GetAsync("https://github.com/anthropic");
if (api.StatusCode == 200) {
Console.WriteLine(api.Body);
}Verzweigen Sie auf api.StatusCode (der HTTP-Status des SDK gegenüber Crawlbase) und api.CrawlbaseStatus (das Crawlbase-Urteil - siehe Errors unten), wenn Sie entscheiden, ob ein Retry erfolgen soll. Übergeben Sie new Dictionary<string,object> { ["format"] = "json" }, um einen JSON-Envelope statt rohem Seiteninhalt zu erhalten.
Alle APIs in einem Paket
Jedes Crawlbase-Produkt hat eine passende Client-Klasse. Selber Konstruktor (einzelner Token-String), selbe Get / GetAsync / Post / PostAsync-Form.
string token = "YOUR_TOKEN";
var crawl = new Crawlbase.API(token); // Crawling API
var scraper = new Crawlbase.ScraperAPI(token); // parsed JSON for supported sites
var leads = new Crawlbase.LeadsAPI(token); // domain-scoped email extraction (legacy)
var shots = new Crawlbase.ScreenshotsAPI(token); // body is base64-encoded image
var storage = new Crawlbase.StorageAPI(token); // Cloud Storage CRUD
// Push high-volume async jobs to the Enterprise Crawler via the Crawling API:
// api.Get(url, options) where options carries `callback=true` + `crawler=YourCrawler`.
// See /docs/crawler for the queue-management workflow.Gängige Muster
JavaScript-Rendering
Für SPAs, Lazy-Loaded-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. Sinnvolle Reihenfolge: erst ein fester Wait, dann Network-Idle, dann Scroll für Lazy-Load, dann Click für jegliche Gating-UI-Elemente.
var api = new Crawlbase.API("YOUR_JS_TOKEN");
await api.GetAsync("https://spa.example.com", new Dictionary<string, object> {
["page_wait"] = 2000,
["ajax_wait"] = true,
["scroll"] = true,
});Eingebauten Scraper verwenden
Auf unterstützten Seiten überspringen Sie den Parser komplett. Übergeben Sie ["scraper"] = "NAME", und der body wird zu einem JSON-String mit den strukturierten Feldern, die auf der jeweiligen Scraper-Seite dokumentiert sind.
using System.Text.Json;
var api = new Crawlbase.ScraperAPI("YOUR_TOKEN");
await api.GetAsync(
"https://www.amazon.com/dp/1098145356",
new Dictionary<string, object> { ["scraper"] = "amazon-product-details" }
);
var data = JsonSerializer.Deserialize<JsonElement>(api.Body);
Console.WriteLine($"{data.GetProperty("name")} - {data.GetProperty("price")}");Geo-Routing
Übergeben Sie ["country"] = "ISO", um den Crawl über die Exit-Nodes des jeweiligen Landes zu routen. Verwenden Sie es immer dann, wenn die Zielseite IP-basiert lokalisierte Inhalte ausliefert.
var api = new Crawlbase.API("YOUR_TOKEN");
// Hit the German Amazon catalog from a German residential IP
await api.GetAsync(
"https://www.amazon.com/dp/1098145356",
new Dictionary<string, object> { ["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.
public async Task<bool> CrawlAsync(Crawlbase.API api, string url, int attempts = 5) {
var rand = new Random();
for (int i = 0; i < attempts; i++) {
try {
await api.GetAsync(url);
} catch (Exception) {
// SDK throws on transport failures - fall through to retry
}
if (api.StatusCode == 200 && api.CrawlbaseStatus == 200) {
return true;
}
if (api.StatusCode is >= 400 and < 500) {
throw new InvalidOperationException($"client error {api.StatusCode}: {url}");
}
// Exponential backoff with jitter
var ms = (int) (rand.NextDouble() * Math.Pow(2, i) * 1000);
await Task.Delay(ms);
}
return false;
}Async-Crawls + Webhooks
Fire-and-Forget-Modus. Übergeben Sie ["async"] = true zusammen mit einer ["callback"]-URL; der Aufruf kehrt sofort zurück, und Crawlbase POSTet das Ergebnis an Ihren Webhook, sobald die Seite bereit ist. Nützlich für Batch-Jobs und langsame Ziele.
var api = new Crawlbase.API("YOUR_TOKEN");
await api.GetAsync("https://example.com", new Dictionary<string, object> {
["async"] = true,
["callback"] = "https://your-app.com/webhook",
});
// api.Body is a JSON envelope { rid: ... } - use that to correlate
// the eventual webhook delivery.
//
// Your ASP.NET / Minimal API endpoint 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 derselben Async-Pipeline sitzt.
Sticky Sessions
Manche Flows benötigen über mehrere Aufrufe hinweg dieselbe Residential-IP. Übergeben Sie cookies_session mit einem stabilen Identifier, und Crawlbase verwendet ~30 Minuten lang denselben Exit-Node wieder.
var api = new Crawlbase.API("YOUR_JS_TOKEN");
var session = $"checkout-{userId}";
var opts = new Dictionary<string, object> { ["cookies_session"] = session };
await api.GetAsync("https://shop.example.com/cart", opts);
await api.GetAsync("https://shop.example.com/checkout", opts);
await api.GetAsync("https://shop.example.com/confirm", opts);Cloud Storage CRUD
Die Storage API ist die Ausnahme vom Muster «Response auf der API-Instanz» - ihre Methoden geben ein Response-Objekt zurück, das Sie direkt auslesen. Nützlich, wenn Sie Ergebnisse zurücklesen, die aus einem früheren Crawling API-Aufruf gespeichert wurden (store=true).
var storage = new Crawlbase.StorageAPI("YOUR_TOKEN");
// Fetch by URL
var response = storage.GetByUrl("https://www.apple.com");
Console.WriteLine(response.OriginalStatus);
Console.WriteLine(response.CrawlbaseStatus);
Console.WriteLine(response.URL);
Console.WriteLine(response.RID);
Console.WriteLine(response.StoredAt);
// Or fetch by RID, delete, bulk-fetch, list RIDs, total count
var item = storage.GetByRID(rid);
bool deleted = storage.Delete(rid);
var items = storage.Bulk(new List<string> { rid1, rid2 });
var rids = storage.RIDs(100); // optional limit
var total = storage.TotalCount();Errors & Retries
Die Plattform liefert in jeder Response zwei Status-Codes: den eigenen api.StatusCode des SDK (HTTP-Status des Requests an Crawlbase selbst) und api.CrawlbaseStatus (das Urteil von Crawlbase über das Ziel - siehe die Crawling API Errors-Tabelle für die vollständige Liste). Verzweigen Sie immer auf api.CrawlbaseStatus, wenn Sie entscheiden, ob ein Retry erfolgen soll - ein Ziel kann 200 mit leerem body zurückgeben, in welchem Fall StatusCode gleich 200 ist, aber CrawlbaseStatus gleich 520.
try {
await api.GetAsync(url);
} catch (Exception ex) {
log.LogError(ex, "transport error");
return;
}
int pc = api.CrawlbaseStatus;
switch (pc) {
case 200:
UseBody(api.Body);
break;
case 520 or 525:
// 520 = empty body, 525 = anti-bot couldn't be solved.
// Switch to JS token and retry.
await RetryWithJsTokenAsync(url);
break;
case 521 or 522 or 523:
// Target unreachable or timed out. Retry with backoff.
ScheduleRetry(url);
break;
default:
log.LogError("crawl failed url={Url} crawlbase_status={CrawlbaseStatus}", url, pc);
break;
}Alle Retries gegen die Plattform sind kostenlos - nur erfolgreiche Responses (CrawlbaseStatus: 200) werden auf Ihr Kontingent angerechnet.
Performance & Best Practices
- Verwenden Sie pro Token einen einzigen Client wieder.
Registrieren Sie sie als Singleton in Ihrem DI-Container - jede Instanz öffnet ihren eigenen zugrundeliegenden
HttpClient. Erstellen Sie nicht eine pro Request. - Verwenden Sie das günstigste Token, das funktioniert. Verwenden Sie nicht standardmäßig das JavaScript token «nur für den Fall» - Requests mit Normal token sind schneller und nutzen weniger Concurrency.
- Bevorzugen Sie
ajax_waitgegenüberpage_wait. Feste Delays verbrauchen bei jedem Request Concurrency, auch bei schnellen. - Achten Sie auf gemeinsamen State auf der API-Instanz.
Da die Crawling-/Scraper-/Leads-/Screenshots-APIs den Response-Zustand auf das api-Objekt schreiben (nicht als Return Value), teilen Sie nicht eine Instanz über mehrere parallele
Tasks hinweg - ein zweitesGetAsync()-await überschreibt den Response-Zustand des ersten Tasks mitten im Lesen. Pooling: eine Instanz pro Worker, oder verwenden Sie die Return-Object-Methoden der StorageAPI, die sich gefahrlos verschränken lassen. - Für Batch-Jobs: async + Webhook, oder Push an den Enterprise Crawler. Awaitable Tasks, die auf synchrone Aufrufe blockieren, lasten Concurrency-Limits schnell aus; async + Webhook gibt den Slot frei, sobald ein Request in die Queue gestellt wird.
Methodenreferenz
Alle Client-Klassen außer Storage haben dieselbe Oberfläche. Konstruktoren nehmen einen Token-String entgegen; Verben kommen als Sync-/Async-Paare und schreiben den Response-State auf die api-Instanz.
Crawlbase.ScraperAPI, Crawlbase.LeadsAPI, Crawlbase.ScreenshotsAPI, Crawlbase.StorageAPI.Task. Gleiches Response-Modell.data ist der body - übergeben Sie ein Dictionary für form-encoded oder einen String für raw.Response-Zustand - Properties auf der api-Instanz nach einem Aufruf:
format=json / scraper= verwendet wurde). Für ScreenshotsAPI ist dies base64-kodiert - konvertieren Sie mit Convert.FromBase64String(api.Body).store=true enthielt. Verwenden Sie diese Werte, um die gespeicherte Response über die StorageAPI wieder abzurufen.