Périmètre sûr : ce guide s'applique à vos propres applications — QA, préproduction, production — ou à des systèmes pour lesquels vous disposez d'une autorisation écrite. Il ne décrit ni l'automatisation de sites tiers, ni l'évasion d'anti-bot.
Dans une suite Puppeteer, ce n'est pas la résolution du défi CAPTCHA qui coûte cher : c'est l'attente. Un scénario bloqué une dizaine de secondes sur un Cloudflare Turnstile immobilise un navigateur entier, et quarante scénarios en série transforment un pipeline de trois minutes en pause-café. Les trois patterns décrits ici — pool de pages, retry avec backoff borné, concurrence calée sur vos threads — récupèrent ce temps sans toucher à la logique de vos tests. Ils supposent les bases en place : clé API dans un secret de CI, helper qui interroge le résultat, token injecté dans le formulaire.
Le temps d'attente du token CAPTCHA dicte la durée du pipeline
CaptchaAI facture des threads, pas des résolutions : un thread correspond à un défi en cours, avec un nombre de résolutions illimité par thread. Le plafond de votre suite n'est donc pas un quota mensuel, mais un produit : threads × vitesse de résolution du type concerné.
Les ordres de grandeur : Cloudflare Turnstile se résout en moins de 10 s, GeeTest v3 en moins de 12 s, reCAPTCHA v2 en moins de 60 s, avec un taux de réussite élevé sur les types pris en charge. Avec 5 threads (plan BASIC, $15/mois), une suite de 40 défis Turnstile cumule de l'ordre de 80 s d'attente si la concurrence est exploitée — contre plus de six minutes en séquentiel. C'est l'écart que ces patterns viennent chercher.
Pattern 1 : un pool de pages Puppeteer plutôt qu'un navigateur par test
Le réflexe le plus coûteux consiste à appeler puppeteer.launch() dans chaque fichier de test : chaque instance recharge un profil, un moteur de rendu et son cache, soit plusieurs centaines de mégaoctets et une à deux secondes de démarrage.
Lancez un navigateur unique à l'ouverture de la session, puis distribuez des pages depuis un pool de taille fixe. Chaque test emprunte une page et la rend en fin de scénario ; un page.close() dans un bloc finally évite qu'une exception ne fasse fuir une page. Deux règles écartent les faux positifs : dimensionnez le pool sur la mémoire disponible (50 à 100 Mo par page) et videz cookies et stockage local entre deux emprunts.
Pattern 2 : un retry avec backoff exponentiel borné
Une erreur transitoire — timeout réseau, 502, DNS capricieux sur le runner — ne justifie pas de faire échouer un pipeline. Une nouvelle tentative immédiate non plus : elle tombe pendant que la cause est encore là.
Retenez un schéma borné : trois tentatives au maximum, un délai doublé à chaque essai (2 s, 4 s, 8 s), un plafond à 30 s et un jitter aléatoire pour éviter que dix workers ne repartent à la même milliseconde. Ne réessayez que ce qui est transitoire : une clé invalide ou un sitekey erroné se reproduira à l'identique, et le retry ne fait que retarder le diagnostic.
Exemple Node.js :
import fetch from 'node-fetch';
const API_KEY = process.env.CAPTCHAAI_KEY;
export async function createTurnstileTask(siteKey, pageUrl) {
const res = await fetch('https://api.captchaai.com/createTask', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
clientKey: API_KEY,
task: {
type: 'TurnstileTaskProxyless',
websiteURL: pageUrl,
websiteKey: siteKey,
},
}),
});
const data = await res.json();
return data.taskId;
}
Ce helper crée la tâche ; la fonction appelante interroge le résultat et applique le backoff.
Pattern 3 : aligner la concurrence Puppeteer sur vos threads CaptchaAI
L'erreur classique consiste à régler la concurrence de Jest ou de Mocha sur le nombre de cœurs du runner. Le facteur limitant n'est pas le CPU : c'est le nombre de défis en vol simultanément.
Prenez la plus petite des deux valeurs : threads du plan et pages que la mémoire du runner supporte. Sur un runner Scaleway ou OVHcloud de 8 Go, huit à dix pages tiennent confortablement ; avec le plan BASIC ($15/mois, 5 threads), la concurrence utile reste donc de 5 pour les scénarios porteurs d'un CAPTCHA. Quand plusieurs suites partagent la même clé, passez à STANDARD ($30/mois, 15 threads) ou à ADVANCE ($90/mois, 50 threads) plutôt que d'allonger les timeouts.
Comparez enfin des exécutions issues de la même région : un runner en eu-west-3 (Paris) ne mesure pas les mêmes temps de bout en bout qu'un runner outre-Atlantique.
Ce qu'il faut journaliser pour trancher un pipeline lent
Sans mesure, impossible de savoir si la lenteur vient du réseau, de votre application ou de la file d'attente. Quatre champs suffisent : durée d'obtention du token, code retour HTTP, identifiant de tâche et profondeur de la file. Ajoutez l'identifiant de trace de votre outillage (OpenTelemetry) : un scénario complet se rejoue depuis une seule ligne de log.
Séparez les journaux par environnement et gardez-les assez longtemps pour lire une tendance : une dérive du temps de résolution se voit sur plusieurs semaines, pas sur une exécution isolée. Côté conformité, appliquez la minimisation RGPD à vos artefacts — une capture d'écran de formulaire rempli avec de vraies adresses est un traitement de données personnelles. Utilisez des jeux de données synthétiques et purgez les artefacts de CI.
Liste de contrôle avant d'ouvrir la merge request
-
Le périmètre reste limité à vos applications ou à des environnements autorisés.
-
La clé CaptchaAI vit dans un secret de CI, jamais dans le dépôt.
-
La concurrence est plafonnée par le nombre de threads du plan.
-
Le retry est borné, idempotent et réservé aux erreurs transitoires.
-
Chaque exécution trace durée, code retour HTTP et identifiant de tâche.
-
Les artefacts de test sont synthétiques et purgés.
Questions fréquentes
Ces patterns fonctionnent-ils aussi avec Playwright ?
Oui. Le pool de contextes remplace le pool de pages, mais le raisonnement reste le même : borner la concurrence sur les threads, borner le retry, tracer les durées.
Combien de threads prévoir pour une suite exécutée en parallèle ?
Comptez un thread par défi simultané, pas un thread par test. Si 12 scénarios sur 200 rencontrent un CAPTCHA et s'exécutent par vagues de 5, le plan BASIC ($15/mois, 5 threads) suffit.
Peut-on réutiliser un token déjà obtenu ?
Oui, tant que sa TTL n'est pas écoulée et que la page cible n'a pas été rechargée. C'est utile quand un test échoue après l'injection, sur la soumission : redemander une résolution mobiliserait un thread sans raison. Passé la TTL, le token est refusé côté serveur.
CaptchaAI prend-il en charge hCaptcha dans ces scénarios ?
Non — hCaptcha et FunCaptcha (Arkose Labs) ne sont pas pris en charge, et GeeTest v4 est annoncé comme à venir. Ces patterns valent pour les types pris en charge : reCAPTCHA v2 et v3, Cloudflare Turnstile, Cloudflare Challenge, GeeTest v3, CAPTCHA image et grilles d'images.
Guides connexes
- Le démarrage rapide de l'API
- La QA CAPTCHA en environnement autorisé
- Valider l'endpoint sur vos formulaires
- Brancher la résolution sur votre CI
- Résoudre reCAPTCHA v2 via l'API
- Résoudre Cloudflare Turnstile via l'API
Mesurez d'abord le temps réellement passé à attendre un token, optimisez ensuite. – Obtenez votre clé CaptchaAI.