Périmètre sûr : Ce guide s'applique exclusivement à vos propres applications, environnements de QA, de préproduction ou de production, ou à des systèmes pour lesquels vous disposez d'une autorisation écrite. Il ne décrit ni l'automatisation de sites tiers, ni le contournement de protections, ni l'évasion d'anti-bot.
Un test Playwright bloqué devant un widget Turnstile ne signale pas un bug applicatif, mais un trou dans votre outillage de test. La réponse tient en trois gestes — récupérer le sitekey du formulaire, demander le token à l'API CaptchaAI, l'injecter dans le formulaire avant la soumission — regroupés dans un helper Node.js que vos fichiers *.spec.ts appellent comme n'importe quel utilitaire.
À préparer avant votre premier test Playwright
Trois éléments suffisent : Node.js 18 ou plus récent (fetch global, sans dépendance HTTP), @playwright/test avec un navigateur installé, et une clé API CaptchaAI en variable d'environnement. Comme vous connaissez le sitekey de vos propres formulaires, lisez-le depuis votre configuration de test plutôt que dans le DOM.
CaptchaAI facture des threads simultanés et non des résolutions : un thread correspond à une résolution en cours, avec un nombre illimité de résolutions par thread. Pour une suite sur cinq workers, BASIC ($15/mois, 5 threads) suffit ; si votre CI lance plusieurs pipelines en parallèle, STANDARD ($30/mois, 15 threads) donne de la marge.
Étape 1 : isolez l'appel CaptchaAI dans un helper Node.js
Un module captchaai expose deux fonctions : la première envoie la tâche à in.php avec le sitekey et l'URL de la page, la seconde interroge res.php jusqu'à obtenir le token. Vos tests ignorent tout des paramètres de l'API et du polling.
Deux réglages comptent ici. Le rythme d'interrogation : cinq secondes d'attente initiale, puis une requête toutes les cinq secondes ; un token Cloudflare Turnstile revient généralement en moins de 10 s, inutile de marteler l'endpoint. Le budget global ensuite : plafonnez l'attente (60 à 90 s) et remontez une erreur explicite, sinon votre rapport affichera « test timeout » là où le motif réel était « token non obtenu ».
Le test lui-même reste très court :
import { test, expect } from '@playwright/test';
import { createTurnstileTask } from './captchaai';
test('login form with captcha', async ({ page }) => {
await page.goto(process.env.QA_BASE_URL + '/login');
const taskId = await createTurnstileTask(process.env.SITEKEY, page.url());
// ... récupère le token via getTaskResult puis l'injecte
await page.fill('#email', 'qa@example.test');
await page.click('button[type=submit]');
});
Étape 2 : injectez le token puis soumettez
Le token doit rejoindre le champ caché que le widget aurait rempli lui-même — cf-turnstile-response pour Cloudflare Turnstile — avant le clic sur le bouton d'envoi. Passez par page.evaluate() et remplissez tous les champs correspondants : certaines pages en contiennent plusieurs. Vérifiez ensuite la réponse côté serveur, pas l'apparence de la page : un test validé sur un simple message de succès dans le DOM passe au vert alors que le backend a rejeté le token.
Demandez le token au dernier moment : il est lié à l'URL soumise et sa durée de vie est courte. Le récupérer en début de scénario reste la première cause de rejet.
Étape 3 : parallélisez vos tests Playwright sans mélanger les sessions
Playwright exécute les fichiers de test en parallèle. Chaque worker doit avoir son propre contexte de navigateur, ses cookies et son token : un storageState partagé produit des échecs intermittents que personne ne reproduit en local. Alignez --workers sur les threads de votre plan — au-delà, les demandes attendent leur tour et vos tests mesurent une latence de file d'attente.
Sur un runner GitLab CI auto-hébergé chez OVHcloud ou Scaleway, tenez compte du trajet réseau : depuis l'Europe face à une préproduction européenne, la marge est confortable ; depuis l'Amérique du Nord, prévoyez un plafond plus large.
Journalisation des appels CAPTCHA et RGPD
Instrumentez chaque appel : durée d'obtention du token, code retour HTTP, identifiant de tâche, nombre de tentatives. Ces quatre valeurs distinguent « l'API a mis du temps » de « mon test a mal attendu ».
Corrélez l'identifiant de tâche avec votre traçage distribué, OpenTelemetry par exemple : un seul identifiant suffit alors à rejouer un scénario. Côté données personnelles, restez sobre : comptes fictifs de type qa@example.test, jamais de token complet ni d'adresse e-mail réelle dans les journaux, durée de conservation définie pour les artefacts de CI. C'est la lecture RGPD la plus simple qui soit : ce que vous ne collectez pas n'a pas à être protégé.
Dépannage : les échecs fréquents
| Problème | Cause probable | Correctif |
|---|---|---|
| Sitekey introuvable | Widget injecté après le chargement | Attendre .cf-turnstile avant de lire l'attribut |
| Token refusé par le backend | Token expiré ou lié à une autre URL | Le demander juste avant la soumission, pour l'URL exacte |
| Vert en local, rouge en CI | Clé absente du runner | Injecter la clé par un secret CI et la vérifier au démarrage |
networkidle qui expire |
Scripts en long-polling | Basculer sur domcontentloaded puis une attente explicite |
| Délais qui explosent en parallèle | Plus de workers que de threads | Réduire --workers ou monter de plan |
Liste de contrôle avant la mise en CI
- Périmètre limité à vos applications ou à des environnements formellement autorisés.
- Clé API dans un secret CI ou un coffre, jamais dans le dépôt ni dans un
.envversionné. - Durées, codes retour et identifiants de tâche tracés à chaque exécution.
- Retry avec backoff exponentiel borné sur les erreurs transitoires : trois tentatives, plafond à 30 s.
- Nombre de workers aligné sur les threads du plan souscrit.
- Exécution reproductible : même commande, même résultat, sans intervention manuelle.
Questions fréquentes
CaptchaAI prend-il en charge hCaptcha ?
Non — pas encore pris en charge, pas plus que FunCaptcha (Arkose Labs). Vos tests peuvent s'appuyer sur reCAPTCHA v2 et v3, Cloudflare Turnstile, Cloudflare Challenge, GeeTest v3, les CAPTCHA image/OCR et les grilles d'images. CaptchaFox (bêta), Friendly Captcha (bêta) et Lemin (bêta) complètent la liste ; GeeTest v4 est annoncé comme à venir.
Combien de threads pour une suite de trente tests ?
Le nombre de threads borne les résolutions simultanées, pas le nombre de tests. Avec --workers=5, cinq résolutions au maximum sont en vol au même instant : BASIC ($15/mois, 5 threads) couvre ce cas. Passez à STANDARD ($30/mois, 15 threads) dès que plusieurs pipelines tournent ensemble.
Où stocker la clé API dans une chaîne CI ?
Dans le gestionnaire de secrets du runner — variables protégées GitLab, secrets GitHub Actions, coffre interne — injectée en variable d'environnement à l'exécution. Ajoutez une vérification au démarrage : une clé absente doit provoquer un échec immédiat, pas une cascade de tests rouges quinze minutes plus tard.
Combien de temps prévoir pour obtenir un token ?
Comptez moins de 10 s pour un token Cloudflare Turnstile, avec un plafond de 60 à 90 s dans votre helper. Au-delà, mieux vaut échouer proprement, identifiant de tâche à l'appui, et relancer le scénario plutôt que d'immobiliser un worker.
Guides connexes
- Le démarrage rapide
- La QA CAPTCHA en environnement autorisé
- Tester vos formulaires via l'API
- Brancher la résolution sur votre CI
- Résoudre reCAPTCHA v2 via l'API
- Résoudre Cloudflare Turnstile via l'API
Une suite de tests désactivée à cause d'un CAPTCHA n'est plus une suite de tests. – Obtenez votre clé CaptchaAI.