Tri des erreurs HTTP
Une erreur HTTP vous indique qu'une requête a échoué. Elle ne vous dit généralement pas pourquoi. Conclure « la clé est morte » à partir d'un 403 est une supposition déguisée en chiffre.
Né d'un incident réel (2026-07-30) : une API tierce d'enrichissement de contacts
renvoyait 403 error code: 1010 à chaque appel pendant six jours. Cela a été interprété comme « clé
non autorisée », « crédits épuisés », « quota mensuel atteint ». Une solution de contournement automatisée par navigateur de 756 lignes a été construite sur cette croyance, et un client a failli être invité
à vérifier un plan qui était pourtant en règle. La cause réelle était un User-Agent manquant, donc
le CDN a banni le client à la périphérie. Un seul en-tête a tout réglé : 200 OK, toutes les données,
et le solde de crédits était là depuis le début.
Exécutez ces trois contrôles avant de diagnostiquer
1. Le contrôle d'identifiant invalide. Envoyez la même requête avec un identifiant délibérément invalide, puis sans aucun identifiant.
for label, key in [("réel", CLE_REAL), ("invalide", "0"*36), ("vide", "")]:
... # même URL, même méthode, mêmes en-têtes
Si les trois renvoient le même statut et le même corps, l'erreur ne concerne pas votre identifiant. Elle ne porte aucune information sur les droits, le quota ou la validité. Arrêtez de raisonner sur la clé.
2. Le contrôle de chemin absurde. Faites une requête vers un chemin qui n'existe certainement pas, et vers la racine du site.
GET https://api.example.com/absolument-pas-un-chemin-réel-12345
GET https://api.example.com/
GET https://www.example.com/ # leur site marketing
Si l'erreur de l'API revient aussi depuis le site marketing, vous êtes bloqué en amont de l'origine. Rien concernant l'appel API ne vous aidera.
3. Lisez les en-têtes de réponse, pas seulement le corps.
except urllib.error.HTTPError as e:
print(e.code, e.headers.get("server"), e.read()[:200])
server: cloudflare sur une erreur « auth » est le révélateur. De même pour cf-ray,
x-amzn-waf, akamai. Ce sont des infrastructures, pas l'API.
Signatures connues
| Symptôme | Cause réelle | Correctif |
|---|---|---|
403 + corps error code: 1010, server: cloudflare | Cloudflare a banni la signature du client | Envoyer un vrai User-Agent de navigateur |
Même erreur pour chaque chemin, y compris / | Blocage Edge/WAF ou bannissement IP | Changer User-Agent, puis IP/proxy |
402 | Crédits réellement épuisés : la requête s'est authentifiée | Recharger ; la clé est bonne |
429 juste après un succès | Vraie limite de débit | Espacer les requêtes, ajouter un backoff |
400 avec un message de champ | Vous avez atteint l'API et l'auth a réussi | Corriger le payload ; c'est une bonne nouvelle |
Une erreur de validation 400 est un signal de succès pour le tri : elle prouve que l'authentification a été
acceptée.
En-têtes par défaut pour tout appel d'API côté serveur
Le urllib de Python envoie User-Agent: Python-urllib/3.x, que de nombreux WAF bannissent
carrément. Toujours définir :
headers = {
"User-Agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) "
"AppleWebKit/537.36 (KHTML, like Gecko) Chrome/126.0 Safari/537.36",
"Accept": "application/json",
"Content-Type": "application/json",
}
Ensuite, mesurez le coût avant toute action générale
Une fois que cela fonctionne, n'estimez pas la dépense. Lisez l'utilisation avant et après un appel, et lisez le champ de facturation propre au fournisseur dans la réponse.
avant = usage(); resultat = appel(); apres = usage()
print("facturé :", resultat.get("billing"), "| mesuré :", avant - apres)
Que rapporter
Indiquez ce que vous avez testé et ce qui reste inconnu. « Les deux clés renvoient 403 » n'est pas une conclusion si une clé vide renvoie le même 403. Dites plutôt : « Le 403 n'est pas informatif ici, un identifiant nul le renvoie aussi ; la cause est en amont de l'auth. »