Explainers

Gestion des User-Agent dans vos workflows CAPTCHA internes

Périmètre sûr : ce guide s'applique à vos propres applications — développement, recette, préproduction, production — ou à des systèmes pour lesquels vous détenez une autorisation écrite. Il ne couvre ni l'automatisation de sites tiers, ni les techniques visant à masquer l'origine d'un trafic.

Une suite de tests qui part avec python-requests/2.31 ne teste pas la page que vos utilisateurs voient. La règle tient en une ligne : le User-Agent de vos scripts doit correspondre à une version de navigateur que votre application prend officiellement en charge, et rester identique du début à la fin d'une session. Dès qu'un défi CAPTCHA — reCAPTCHA v2 ou v3, Cloudflare Turnstile, GeeTest v3 — s'intercale dans le parcours testé, cette cohérence sépare un rapport de recette exploitable d'une série d'échecs que personne ne sait rejouer.

Pourquoi le User-Agent fausse vos résultats de recette

En-tête envoyé par vos tests Ce que vous observez ensuite
python-requests/2.31 laissé par défaut Vos assertions portent sur une variante de page que vos utilisateurs ne voient pas
Chrome 90 quand votre matrice démarre à Chrome 124 Vous validez des chemins de compatibilité obsolètes
Une valeur différente à chaque requête Session invalidée, cookie perdu, échec impossible à rejouer
User-Agent Chrome mais en-têtes Sec-Fetch-* absents Le client décrit ne correspond à aucun navigateur du parc

Aucun de ces cas n'est un problème de détection : ce sont des tests qui décrivent mal leur client.

Choisir la valeur : partez de votre matrice de support

Ne piochez pas dans une liste trouvée en ligne. Ouvrez la matrice de navigateurs que votre équipe s'engage à supporter et dérivez-en un profil par entrée : chrome-desktop, firefox-esr, chrome-android. Chaque profil porte une chaîne figée, versionnée à côté de vos fixtures.

Un profil figé, pas une valeur tirée au hasard

Une chaîne aléatoire par exécution rend vos rapports incomparables d'un jour à l'autre. Faites évoluer le profil comme une dépendance : à chaque version majeure qui entre dans votre matrice, mettez à jour la valeur, relancez la campagne, consignez la date.

Le même User-Agent du début à la fin de la session

Le point le plus souvent raté : la valeur change entre l'authentification et l'étape qui déclenche le CAPTCHA. Le serveur voit deux clients partager un cookie, la session tombe, et l'échec est imputé à la résolution alors qu'il vient de votre client HTTP. Une session par scénario, l'en-tête posé à la création, et plus rien ensuite.

Le User-Agent ne voyage jamais seul

Un navigateur réel envoie un bloc cohérent : Accept, Accept-Language, Accept-Encoding, la famille Sec-Fetch-* et, côté Chromium, sec-ch-ua. Un profil qui annonce Chrome sans ces en-têtes décrit un client qui n'existe pas.

Le cas le plus parlant pour un produit francophone est Accept-Language. Une valeur fr-FR,fr;q=0.9 bascule le widget CAPTCHA en français : les libellés changent, la hauteur du bloc change, vos sélecteurs et vos captures de référence avec. Déclarez donc la locale au même endroit que le User-Agent.

Transmettre le même User-Agent à l'API CaptchaAI

Pour les tâches reCAPTCHA, l'endpoint in.php accepte un champ userAgent aux côtés de key, method=userrecaptcha, googlekey et pageurl. Renseignez-y la chaîne exacte du client qui a chargé la page ; le token revient ensuite dans g-recaptcha-response. La mécanique complète figure dans le guide de prise en main de l'API.

Sur navigateur piloté, même discipline : passez user-agent=... aux options du driver Selenium, puis vérifiez avec navigator.userAgent que la valeur effective correspond au profil.

Tracer et mesurer chaque appel CAPTCHA

Un User-Agent absent des logs est un paramètre invisible : le jour où un bug ne touche qu'un profil, rien ne permet de le rattacher. Journalisez la chaîne à l'ouverture de chaque session, avec l'identifiant du scénario.

Exemple Python :

import requests
session = requests.Session()
session.headers['User-Agent'] = 'qa-suite/1.0 (Chrome/124.0)'
r = session.get(QA_BASE_URL + '/health', timeout=15)
print(r.status_code)

Une chaîne explicite du type qa-suite/1.0 rend d'ailleurs le trafic de test immédiatement identifiable dans vos journaux serveur.

Autour de l'appel de résolution, relevez la durée d'obtention du token, le code retour HTTP, l'identifiant de tâche et le profil actif : c'est ce qui permet de comparer deux profils au lieu de les moyenner. Séparez les journaux par environnement et propagez un identifiant de corrélation vers votre traçage distribué (OpenTelemetry).

Exemple : une équipe SaaS qui teste son parcours d'inscription

Six personnes, application hébergée chez OVHcloud, runners d'intégration continue sur AWS à Paris (région eu-west-3). La matrice couvre Chrome et Firefox ESR, en fr-FR et fr-BE : quatre profils, décrits dans un YAML versionné, rejouent chaque nuit le formulaire d'inscription protégé par Turnstile.

Le plan BASIC ($15/mois, 5 threads) suffit, les quatre profils s'exécutant en parallèle. Quand la suite couvre aussi la connexion et le paiement en préproduction, STANDARD ($30/mois, 15 threads) évite que les scénarios s'attendent. La facturation reste en dollars US.

Côté conformité, l'équipe journalise le profil et l'horodatage, pas les identifiants de comptes réels : sur des jeux de données fictifs, la minimisation prévue par le RGPD est respectée sans perdre en traçabilité.

Liste de contrôle avant de lancer une campagne

  • Périmètre limité à vos applications ou à des sources explicitement autorisées.
  • Chaîne figée et versionnée par profil, alignée sur la matrice de support.
  • User-Agent et locale posés une seule fois par session.
  • La même chaîne part vers l'application testée et vers l'API de résolution.
  • Clé CaptchaAI dans un secret d'intégration continue ou un coffre, jamais dans le code.
  • Durées, codes retour et identifiants de tâche tracés à chaque exécution.
  • Retry idempotent avec backoff exponentiel borné sur les erreurs transitoires.
  • Campagne rejouable depuis votre chaîne d'intégration continue.

Questions fréquentes

Faut-il envoyer à l'API le même User-Agent qu'au navigateur de test ?

Oui, sans exception dans un même scénario : le champ userAgent de in.php décrit le client qui a chargé la page.

Quels types de CAPTCHA puis-je couvrir dans ces tests ?

reCAPTCHA v2 et v3 (Enterprise compris), Cloudflare Turnstile et Cloudflare Challenge, GeeTest v3, les CAPTCHA image/OCR et les grilles d'images, plus CaptchaFox (bêta), Friendly Captcha (bêta) et Lemin (bêta). hCaptcha et FunCaptcha (Arkose Labs) ne sont pas pris en charge ; GeeTest v4 est annoncé comme à venir.

Journaliser le User-Agent relève-t-il du RGPD ?

Seul, sur un environnement alimenté par des comptes fictifs, non. Croisé avec une adresse IP et un identifiant réel, la question se pose : gardez le strict nécessaire, fixez une durée de rétention, faites valider par votre référent conformité.

Que faire en cas d'erreur transitoire de l'API ?

Appliquez un backoff exponentiel borné — trois tentatives, délai doublé, plafond à 30 s — et tracez chaque échec avec son identifiant de tâche. Si l'erreur persiste, vérifiez le réseau (DNS, certificats) et le solde de votre clé.

Guides connexes

Des profils stables, des journaux lisibles, des campagnes rejouables : c'est ce qu'il faut pour que vos tests CAPTCHA disent la vérité. – Obtenez votre clé CaptchaAI.

Les commentaires sont désactivés pour cet article.