C# / .NET
Client .NET officiel pour la plateforme Crawlbase. Chaque méthode dispose d'une version synchrone (par ex. Get) et d'une version asynchrone (GetAsync) : même artefact, toutes les APIs, des valeurs par défaut sensées.
Comment le SDK est conçu
Le SDK .NET est une fine surcouche de la même API HTTP documentée dans la référence de l'API. Chaque paramètre de la Crawling API que vous ajouteriez en query string dans un appel HTTP brut est accessible comme option Dictionary<string, object> : noms, valeurs par défaut et comportement, tout correspond un pour un.
Une particularité à connaître d'emblée : le SDK .NET expose l'état de la réponse sur l'instance de l'API elle-même, et non sur un objet de valeur retourné. Les appels comme api.Get(url) renvoient void ; vous lisez le résultat via api.StatusCode, api.Body, etc. Cela diffère des SDKs Python / Node / Ruby / PHP (qui renvoient un objet de réponse). La Storage API fait exception : ses méthodes renvoient un objet de réponse que vous lisez directement.
Ce que vous y gagnez par rapport à l'utilisation directe de HttpClient :
- Encodage d'URL, validation des paramètres et parsing de la réponse pris en charge nativement.
- Paire sync + async sur chaque verbe : choisissez celle qui correspond à votre site d'appel.
- Une seule classe client par API Crawlbase, toutes partageant la même forme de constructeur / d'appel.
- Des valeurs par défaut sensées (timeout de 90 secondes, parsing JSON automatique des réponses
format=json).
Code source sur github.com/crawlbase/crawlbase-net.
Installation
Dernière version sur NuGet. Cible .NET 6+ ; testé jusqu'à .NET 9.
# .NET CLI
dotnet add package CrawlbaseAPI
# Package Manager Console
Install-Package CrawlbaseAPI
# Or in csproj:
# <PackageReference Include="CrawlbaseAPI" Version="1.1.0" />Authentification
Toutes les APIs Crawlbase s'authentifient avec le même modèle de token. Deux types de tokens existent sur un même compte :
- Normal Token (TCP) - pour le HTML statique, les endpoints JSON, tout ce qui ne nécessite pas de navigateur. Plus rapide + moins coûteux.
- JavaScript Token
- pour les SPAs, les flux chargés en lazy, tout ce qui cache du contenu derrière un rendu côté client. Requis pour utiliser
page_wait,ajax_wait,scrolletcss_click_selector.
Utilisez des variables d'environnement ou la configuration de votre conteneur DI en production. Modèle :
// 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);Modèle complet des tokens + emplacements dans le tableau de bord sur la page Authentication.
Démarrage rapide
Trois lignes entre le namespace et une réponse crawlée. Notez que l'état de la réponse réside sur l'instance api :
var api = new Crawlbase.API("YOUR_TOKEN");
await api.GetAsync("https://github.com/anthropic");
if (api.StatusCode == 200) {
Console.WriteLine(api.Body);
}Branchez-vous sur api.StatusCode (le statut HTTP du SDK vers Crawlbase) et api.CrawlbaseStatus (le verdict de Crawlbase : voir Erreurs ci-dessous) pour décider de retenter ou non. Passez new Dictionary<string,object> { ["format"] = "json" } pour recevoir une enveloppe JSON au lieu du contenu brut de la page.
Toutes les APIs dans un seul package
Chaque produit Crawlbase a une classe client correspondante. Même constructeur (une seule chaîne de token), même forme Get / GetAsync / Post / PostAsync.
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.Patterns courants
Rendu JavaScript
Pour les SPAs, les flux à chargement différé et les pages où le HTML initial est vide, instanciez avec le JavaScript token et passez n'importe quelle combinaison de page_wait, ajax_wait, scroll et css_click_selector. Ordre à envisager : un délai fixe, puis l'inactivité réseau, puis le scroll pour le lazy-load, puis le clic pour tout élément d'UI bloquant.
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,
});Utiliser un scraper intégré
Évitez complètement le parser sur les sites pris en charge. Passez ["scraper"] = "NAME" et le body devient une chaîne JSON contenant les champs structurés documentés sur la page de chaque scraper.
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")}");Routage géographique
Passez ["country"] = "ISO" pour router le crawl à travers les nœuds de sortie de ce pays. À utiliser dès que la cible sert un contenu localisé en fonction de l'IP.
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" }
);Réessayer avec backoff
La forme de retry recommandée : backoff exponentiel plafonné à 3-5 tentatives, retry uniquement sur les erreurs transitoires (5xx ou body vide), pas de retry sur les 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;
}Crawls async + webhooks
Mode fire-and-forget. Passez ["async"] = true avec une URL ["callback"] ; l'appel retourne immédiatement et Crawlbase envoie le résultat en POST sur votre webhook lorsque la page est prête. Utile pour les jobs en lot et les cibles lentes.
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 }Pour de très grands volumes (millions d'URLs), utilisez l'Enterprise Crawler qui se place devant ce même pipeline async.
Sessions persistantes
Certains flux nécessitent la même IP résidentielle sur plusieurs appels. Passez cookies_session avec un identifiant stable et Crawlbase réutilise le même nœud de sortie pendant environ 30 minutes.
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);CRUD Cloud Storage
La Storage API est l'exception au modèle « réponse sur l'instance api » : ses méthodes renvoient un objet de réponse que vous lisez directement. Utile pour relire des résultats stockés lors d'un précédent appel à la Crawling API (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();Erreurs & retries
La plateforme expose deux codes de statut sur chaque réponse : le api.StatusCode propre au SDK (statut HTTP de la requête vers Crawlbase elle-même) et api.CrawlbaseStatus (le verdict de Crawlbase sur la cible : voir la table des erreurs de la Crawling API pour la liste complète). Branchez-vous toujours sur api.CrawlbaseStatus pour décider de retenter : une cible peut renvoyer 200 avec un body vide, auquel cas StatusCode vaut 200 mais CrawlbaseStatus vaut 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;
}Tous les retries contre la plateforme sont gratuits : seules les réponses réussies (CrawlbaseStatus: 200) sont décomptées de votre quota.
Performance & bonnes pratiques
- Réutilisez un seul client par token.
Enregistrez-la en singleton dans votre conteneur d'injection de dépendances : chaque instance ouvre son propre
HttpClientsous-jacent. N'en construisez pas une par requête. - Utilisez le token le moins cher qui fonctionne. Ne basculez pas sur le JavaScript token « au cas où » par défaut : les requêtes avec le Normal token sont plus rapides et consomment moins de concurrence.
- Préférez
ajax_waitàpage_wait. Les délais fixes brûlent de la concurrence sur chaque requête, même les rapides. - Attention à l'état partagé sur l'instance d'API.
Comme les APIs Crawling/Scraper/Leads/Screenshots écrivent l'état de la réponse sur l'objet api (et non dans une valeur de retour), ne partagez pas une même instance entre plusieurs
Taskconcurrentes : un secondGetAsync()awaité écrasera l'état de réponse de la première tâche en pleine lecture. Maintenez un pool d'une instance par worker, ou utilisez les méthodes de la StorageAPI à objet de retour, qui peuvent être entrelacées sans risque. - Pour les jobs en lot : async + webhook, ou push vers l'Enterprise Crawler. Les Tasks awaitables qui bloquent sur des appels synchrones saturent rapidement les plafonds de concurrence ; async + webhook libère le slot dès qu'une requête est mise en file d'attente.
Référence des méthodes
Toutes les classes client hors Storage partagent la même surface. Les constructeurs prennent une chaîne de token ; les verbes viennent en paires sync + async et écrivent l'état de la réponse sur l'instance api.
Crawlbase.ScraperAPI, Crawlbase.LeadsAPI, Crawlbase.ScreenshotsAPI, Crawlbase.StorageAPI.Task. Même modèle de réponse.data correspond au body : passez un Dictionary pour un encodage form, une string pour du brut.État de la réponse : propriétés sur l'instance api après un appel :
format=json / scraper= a été utilisé). Pour ScreenshotsAPI, le contenu est encodé en base64 : convertissez-le avec Convert.FromBase64String(api.Body).store=true. Utilisez-les pour récupérer la réponse stockée via StorageAPI.