Je fais plusieurs appels API en utilisant le nœud HTTP Request, mais après un certain temps, je commence à recevoir des erreurs 429 Too Many Requests. Quelle est la meilleure façon de gérer les limites de débit des API.
Salut @Victory1, en attendant une réponse, voici quelques ressources qui pourraient t’aider :
Ressources suggérées
Automatiquement associées à ta question.
Documentation :
Forum :
@Yo_its_prakash, @MutedJam, @Niffzy - vous avez déjà aidé avec des problèmes similaires, pouvez-vous jeter un œil ?
Suggéré automatiquement par le bot communautaire n8n. C’est un pilote - veuillez partager vos commentaires ici.
Étalez vos demandes pour éviter de surcharger le point de terminaison de l’API.
Ajoutez un délai d’attente suffisant
Une erreur 429 signifie que vous avez dépassé la limite de requêtes de l’API.
Essayez d’ajouter un nœud Wait entre les requêtes, traitez les éléments par lots en utilisant Loop Over Items (Batching), ou implémentez une logique de retry avec backoff exponentiel.
Il est aussi judicieux de consulter la documentation de l’API pour connaître les directives de limitation de débit et éviter les défaillances inutiles.
Salut @Victory1
Une petite mais importante distinction en plus de ce qui précède — le nœud HTTP Request a sa propre option Batching, qui est différente du batching Loop Over Items et ne nécessite aucun nœud supplémentaire :
1. HTTP Request → Options → Add Option → Batching
Items per Batch 1, Batch Interval 1000 = une requête/seconde. Pas de Loop Over Items, pas de nœud Wait, pas de recâblage.
2. Deux points importants à connaître
- Au sein d’un batch, les requêtes s’exécutent en parallèle — Items per Batch
10signifie 10 connexions simultanées, pas 10 espacées. Gardez-le à 1 si l’API limite la concurrence. - Le Retry On Fail intégré d’n8n utilise un intervalle fixe et ignore
Retry-After— ce n’est donc pas un backoff exponentiel. Pour un vrai backoff, vous avez besoin d’une boucle IF + Wait qui lit vous-même l’en-tête.
3. Déterminez quelle limite vous atteint en premier
Loggez x-ratelimit-limit / -remaining / -reset à partir d’une réponse réussie :
- rafale par seconde → le pacing la corrige
- quota quotidien → le pacing ne l’aidera pas, vous avez besoin de moins d’appels
- limite de concurrence → seul Items per Batch 1 le corrige
Même 429, trois problèmes différents.
4. Si le workflow s’exécute plusieurs fois en parallèle
Le pacing dans une seule exécution ne sera d’aucune aide — chaque exécution attend poliment et elles inondent quand même l’API ensemble. Auto-hébergé : N8N_CONCURRENCY_PRODUCTION_LIMIT=1.
Quelle API est-ce ? Heureux d’être plus précis.
Bonjour @Victory1
Si l’API dispose d’un endpoint en masse ou par lot, le nombre de requêtes lui-même peut diminuer. Placez un nœud Aggregate avant le nœud HTTP Request avec Aggregate défini sur All Item Data, et l’ensemble arrive comme un seul élément sous data. Référencez-le dans le corps JSON :
{{ JSON.stringify($json.data) }}
Cinquante éléments sortent alors en une seule requête au lieu de cinquante.
Bonne analyse de @Hammad_gaming. Je complète la partie qu’il a signalée mais n’a pas construite, plus une catégorie de 429 qu’aucune des solutions ci-dessus ne corrige.
La boucle Retry-After, puisqu’elle a été mentionnée mais non montrée
Nœud HTTP Request : désactivez Retry On Fail et définissez Options >
Response > Never Error = true. Vous avez besoin que le 429 revienne
comme données, pas comme une erreur levée, sinon vous ne pouvez pas
lire l’en-tête.
Ensuite IF sur {{ $json.statusCode }} égal 429 → Nœud Code pour
calculer l’attente → Nœud Wait → boucle de retour au nœud HTTP.
Nœud Code :
const h = $json.headers || {};
let sec = 1;
if (h[‘retry-after’]) {
const v = h[‘retry-after’];
// Retry-After est soit delta-secondes soit une date HTTP
sec = isNaN(v) ? Math.max(0, (new Date(v) - Date.now()) / 1000)
: Number(v);
} else if (h[‘x-ratelimit-reset’]) {
const r = Number(h[‘x-ratelimit-reset’]);
// certaines APIs envoient les secondes epoch, d’autres les secondes restantes
sec = r > 1e9 ? r - Math.floor(Date.now() / 1000) : r;
} else {
const n = $runIndex || 0;
sec = Math.min(2 ** n, 60);
}
// gigue — cette ligne compte plus qu’il n’y paraît
sec = sec * (0.5 + Math.random() * 0.5);
return [{ json: { waitSeconds: Math.ceil(sec) } }];
Trois choses là-dedans qu’on oublie facilement :
Retry-After peut être une date HTTP, pas seulement un nombre de
secondes. L’analyser comme un entier vous donne silencieusement NaN
et une attente de zéro seconde, donc vous réessayez instantanément
et obtenez 429 à nouveau.
x-ratelimit-reset est incohérent selon les APIs — GitHub envoie les
secondes epoch, d’autres envoient les secondes restantes. Le contrôle
de magnitude traite les deux.
La ligne de gigue est celle qu’on saute. Sans elle, si vous avez 20
éléments qui tous atteindent 429 au même moment, ils attendent tous
exactement la même durée et réessaient tous au même instant. Vous
avez recréé le problème initial avec une étape supplémentaire.
Randonniser l’attente les étale.
L’orage de tentatives, que le rythme ne résout pas
Ça vaut le coup d’être explicite : Retry On Fail réessaye par
élément. Cinquante éléments, trois tentatives chacun, et un 429 qui
frappe à l’élément 20 signifie que vous pouvez envoyer 90 requêtes
supplémentaires à une API qui vient de vous dire d’arrêter. Certaines
APIs répondent à cela en prolongeant le blocage.
Si vous utilisez Retry On Fail sur un lot, définissez Max Tries sur 2
et gérez les vrais réessais avec la boucle ci-dessus, où le rythme
est sous votre contrôle.
Le seul que personne n’a mentionné : limites de tokens, pas limites de requêtes
@Victory1 — si c’est OpenAI, Anthropic, Cohere ou toute API LLM,
chances sont que vous ne frappez pas du tout une limite de requête.
Ces fournisseurs appliquent deux limites distinctes : requêtes par
minute et tokens par minute. TPM est habituellement celle que vous
atteindre d’abord, et aucun des conseils de rythme ci-dessus ne la
touche, car la contrainte est la taille de la charge utile plutôt que
la fréquence des appels.
Le symptôme qui vous dit lequel : si les 429 s’aggravent quand vos
documents d’entrée s’allongent, mais le nombre d’appels n’a pas
changé, c’est TPM.
Les solutions sont différentes aussi — vous réduisez les tokens plutôt
que de ralentir. Rogner l’invite, baisser max_tokens si vous l’avez
défini haut (certains fournisseurs comptent la réservation contre
votre budget, pas la sortie réelle), diviser les longs documents, ou
routeur les appels courts vers un modèle plus petit.
Les en-têtes de réponse le nomment directement si vous les enregistrez :
x-ratelimit-remaining-requests vs x-ratelimit-remaining-tokens.
Celui qui atteint zéro d’abord est votre limite réelle.
Et une qui gâche un après-midi
Certaines APIs ne retournent pas 429 du tout. Le point de terminaison
GraphQL de Shopify retourne 200 avec un statut d’accélération dans le
corps. Tout comme plus d’un fournisseur de paiement.
Si votre workflow « ne fait pas d’erreur » mais les données
disparaissent silencieusement, vérifiez le corps de la réponse plutôt
que le code d’état. Un IF sur statusCode ne l’attrapera jamais.
Quelle API est-ce ? La bonne solution est différente pour les trois cas.