Réponse rapide
Quelles erreurs l'API LLMWebSearch peut-elle renvoyer, et sont-elles facturées ?
LLMWebSearch compte six erreurs HTTP : 400 invalid_parameter, 401 invalid_api_key, 402 insufficient_credits, 429 rate_limited, 502 search_failed et 504 search_timeout. Aucune n'est facturée. Les pages qui ne peuvent pas être lues affichent un content_status au sein d'un 200 à la place. Une requête qui aboutit coûte 1 crédit, d'après 1,20 $US/1K requêtes en octobre 2026. Sans KYC ; payer en crypto.
Quelles erreurs HTTP existent ?
Le corps est toujours {"error": {"code": "…", "message": "…"}}. Aucune erreur ne consomme de crédit.
| HTTP | code | Cause | Réessayer ? |
|---|---|---|---|
| 400 | invalid_parameter | Un paramètre requis est manquant ou une valeur est hors limites | Non : corriger la requête |
| 401 | invalid_api_key | La clé est manquante, erronée ou révoquée | Non : vérifier la clé |
| 402 | insufficient_credits | Le solde ne peut pas payer cet appel | Non : acheter un pack |
| 429 | rate_limited | Plus d'appels par minute que le compte ne l'autorise | Oui, après une pause |
| 502 | search_failed | La requête n'a pas pu être terminée | Oui, avec backoff |
| 504 | search_timeout | Aucun résultat de recherche en 30 secondes | Oui, avec backoff |
En quoi un statut de page diffère-t-il d'une erreur ?
Un statut de page décrit un résultat, pas l'appel. La recherche s'est exécutée, les résultats sont là et credits_used est défini comme d'habitude. Seul le contenu de cette page manque, et content_status en indique la raison : blocked_by_robots, blocked_by_site_policy, target_refused, fetch_failed, fetch_timeout ou unsupported_content.
Ne traitez pas ces cas comme des échecs nécessitant de relancer toute la recherche. Utilisez les autres résultats, l'extrait de la page manquante, ou une autre source. La page format de réponse explique chaque statut dans un tableau.
Pourquoi ne relancez-vous jamais en cas de refus ?
Parce qu'un refus est la réponse du site, et nous la respectons. Notre lecteur respecte robots.txt : il s'annonce comme LLMWebSearch, suit les règles qu'un site écrit pour lui ou pour tous les robots, et laisse de côté le contenu de toute page qu'il n'est pas autorisé à lire. Un site qui définit Content-Signal: ai-input=no dans son robots.txt garde ses pages hors du contenu de vos résultats. Quand un site rejette notre lecteur avec un 403, un 429 ou une page de challenge, nous le signalons comme target_refused avec le statut du site dans target_status.
Quand un site refuse notre lecteur, le résultat revient sans contenu et avec le statut du site : nous ne résolvons jamais de CAPTCHA, ne nous connectons pas à des comptes et ne contournons ni un blocage ni un paywall. Nous ne relançons pas non plus avec une autre identité ou un navigateur déguisé. Votre agent ne doit pas boucler sur une telle page : le résultat ne changera pas et le site a dit non.
Quand mon code doit-il réessayer ?
Uniquement sur 429, 502 et 504. Attendez, puis réessayez en doublant le délai à chaque fois et en ajoutant un peu d'aléatoire pour que les workers parallèles ne réessaient pas en cadence. Trois à cinq tentatives suffisent ; ensuite, signalez l'échec.
Ne réessayez jamais sur 400, 401 ou 402 : la même requête donne la même réponse tant que vous ne changez rien. Pour les pages, fetch_failed et fetch_timeout peuvent fonctionner plus tard, via une nouvelle recherche ou un appel /extract. target_refused, blocked_by_robots et blocked_by_site_policy sont définitifs.
import os
import random
import time
import requests
API = "https://llmwebsearch.com/api/v1/search"
HEADERS = {"Authorization": "Bearer " + os.environ["LLMWEBSEARCH_API_KEY"]}
RETRY_ON = {429, 502, 504}
def search(body, attempts=5):
delay = 1.0
for attempt in range(1, attempts + 1):
resp = requests.post(API, headers=HEADERS, json=body, timeout=60)
if resp.status_code == 200:
return resp.json()
err = resp.json().get("error", {})
if resp.status_code not in RETRY_ON or attempt == attempts:
raise RuntimeError(f"{resp.status_code} {err.get('code')}: {err.get('message')}")
time.sleep(delay + random.uniform(0, delay / 2))
delay = min(delay * 2, 30)
data = search({"q": "how to rotate api keys without downtime"})
unread = [r["url"] for r in data["results"] if r["content_status"] not in ("ok", "not_requested")]
print("credits:", data["credits_used"], "| pages not read:", unread)
Que faire en cas de 402 insufficient_credits ?
Arrêtez et rechargez. L'appel n'a pas été exécuté et n'a rien coûté. Pour éviter de vous arrêter au milieu d'une longue tâche, vérifiez d'abord votre solde avec GET https://llmwebsearch.com/api/v1/credits, qui est gratuit, et comparez-le au nombre de recherches prévues. Rappelez-vous qu'une recherche avec read supérieur à 3 nécessite 2 crédits.
Les crédits proviennent de packs achetés avec votre solde crypto. Les crédits de recherche n'ont pas de date d'expiration : ce que vous n'utilisez pas ce mois-ci est toujours là l'année prochaine.
Comment rester sous la limite de débit ?
Limitez le nombre d'appels simultanés dans votre propre code. Chaque compte a une limite d'appels par minute, affichée dans le dashboard ; demandez au support et elle peut être augmentée. Un petit pool de workers parallèles, quatre à huit pour la plupart des agents, maintient un rythme régulier sans pics. Les pages Python et Node.js montrent chacune un tel pool.
Quand vous recevez un 429, marquez une pause avant la tentative suivante au lieu de la lancer immédiatement. Réessayer tout de suite ne fait qu'ajouter des appels refusés.
Erreurs : questions fréquentes
Une recherche dont toutes les pages sont refusées coûte-t-elle quand même un crédit ?
Oui, si la recherche elle-même a fonctionné : vous obtenez quand même les résultats classés et les extraits. Le prix d'une recherche ne dépend pas du nombre de ses pages qui ont pu être lues.
Un 401 peut-il être causé par une clé révoquée ?
C'est possible. Une clé révoquée, une faute de frappe, un préfixe Bearer manquant ou un header qui ne nous est jamais parvenu donnent tous 401 invalid_api_key. Créez une clé API par agent, application ou coéquipier et révoquez n'importe laquelle depuis le dashboard sans toucher aux autres.
Pourquoi une page a-t-elle renvoyé fetch_timeout ?
Les pages sont lues en parallèle, et une page qui prend plus de 15 secondes est renvoyée sans contenu pour ne pas bloquer toute la réponse. Les sites lents répondent parfois lors d'une tentative ultérieure.
Puis-je voir mes appels échoués ?
Oui. L'historique du dashboard liste vos appels sur 30 jours, y compris ceux qui ont échoué, avec leur statut et leurs crédits. Les appels échoués affichent 0 crédit.