Limites de débit
Crawlbase applique des limites de concurrence par token, et non un nombre de requêtes par minute. Envoyez aussi vite que vous le souhaitez, gardez simplement le nombre de requêtes parallèles en cours sous votre plafond.
Limites par défaut
Chaque compte démarre avec les mêmes valeurs par défaut généreuses. Vous n'avez pas besoin de les demander : elles sont déjà appliquées à chaque token dès votre inscription.
| Limite | Par défaut | Portée |
|---|---|---|
| Requêtes simultanées | 20 | par token |
| Requêtes par seconde | ~ 20 (dérivé) | par token |
| Total des requêtes mensuelles | jusqu'à 51,000,000 | par token |
| Délai d'expiration d'une requête | 90 secondes | par requête |
| Taille de la file du Crawler | 100,000 URLs | par crawler |
« Simultané » signifie en cours d'exécution au même moment. Si chaque crawl prend 2 secondes et que vous en maintenez 20 en parallèle, vous ferez environ 10 req/s en continu : ce calcul revient à ~864K requêtes par jour et par token.
N'essayez pas de limiter à « X requêtes par seconde » : plafonnez simplement votre pool de workers à 20 et laissez la latence des requêtes dicter le débit. C'est plus simple et cela correspond au fonctionnement réel de la limite côté serveur.
Que se passe-t-il quand vous atteignez la limite
Dépassez le plafond de concurrence et Crawlbase répond avec un 429 Too Many Requests HTTP. La requête est rejetée, elle n'est pas mise en file d'attente, vous devez donc réessayer avec un backoff.
// HTTP/1.1 429 Too Many Requests
// Retry-After: 1
// X-Crawlbase-Concurrency: 20
{ "error": "Concurrency limit reached", "limit": 20 }L'en-tête Retry-After vous indique le nombre minimum de secondes à attendre avant de réessayer. Respectez-le toujours.
Gérer les limites de débit avec élégance
Le bon pattern est le backoff exponentiel avec jitter. La plupart des clients HTTP l'intègrent nativement ; voici le minimum si vous devez l'implémenter vous-même.
import time, random
from crawlbase import CrawlingAPI
api = CrawlingAPI({'token': 'YOUR_TOKEN'})
def crawl_with_retry(url, attempts=5):
for i in range(attempts):
res = api.get(url)
if res['status_code'] != 429:
return res
wait = (2 ** i) + random.random()
time.sleep(wait)
raise RuntimeError('Rate limit exhausted')const { CrawlingAPI } = require('crawlbase');
const api = new CrawlingAPI({ token: 'YOUR_TOKEN' });
async function crawlWithRetry(url, attempts = 5) {
for (let i = 0; i < attempts; i++) {
const res = await api.get(url);
if (res.statusCode !== 429) return res;
const wait = (2 ** i) * 1000 + Math.random() * 1000;
await new Promise(r => setTimeout(r, wait));
}
throw new Error('Rate limit exhausted');
}Pour les charges de travail qui poussent constamment le plafond, utilisez un worker pool plutôt qu'un fire-and-forget. Plafonnez le pool à votre limite de concurrence et vous ne verrez jamais de 429.
Passer à l'échelle au-delà des valeurs par défaut
Trois options lorsque 20 requêtes simultanées ne suffisent plus :
Bonnes pratiques
- Plafonnez les pools de workers à la limite de votre token. Ne survendez pas en vous reposant sur les 429 : la requête rejetée consomme tout de même un aller-retour.
- Utilisez
async=truepour les cibles lentes. Les crawls longs avec rendu JS bloquent un slot de concurrence pendant toute la durée de la requête. Le mode async libère le slot immédiatement et livre le résultat via webhook. - Respectez toujours
Retry-After. L'ignorer ne fait que générer davantage de 429 et gaspille des allers-retours réseau. - Ajoutez du jitter aux réessais. Si 50 workers réessaient tous exactement 1 s après un pic transitoire, vous provoquerez simplement un nouveau pic.
- Alertez sur un taux de 429 soutenu. Un 429 occasionnel n'est pas grave. Un taux soutenu de 5 % ou plus signifie que vous avez besoin d'une concurrence plus élevée ou d'une planification plus intelligente.