Périmètre : ce guide s'applique uniquement à vos propres environnements QA et staging, ou à des environnements explicitement autorisés. Il décrit des étapes de diagnostic et de vérification pour votre propre intégration CAPTCHA, pas pour des sites tiers ni pour des workflows non autorisés.
Quand un CAPTCHA fait échouer un test de staging, la cause est rarement lisible depuis l'interface : le widget s'est-il chargé, avec quel sitekey, et la réponse est-elle remontée jusqu'au backend ? Le Chrome DevTools Protocol (CDP) répond à ces questions en exposant l'activité réseau et l'état du DOM du navigateur. Associé à CaptchaAI, il ne sert pas à automatiser : c'est une surface de diagnostic qui relie chaque maillon de votre intégration, du widget jusqu'à la validation côté serveur.
À quoi sert CDP dans un diagnostic CAPTCHA
CDP tranche des questions que l'interface seule laisse ouvertes : le widget se charge-t-il au bon moment, la page utilise-t-elle le bon sitekey, la vérification atteint-elle le backend avec les bons paramètres, et les codes d'erreur suivent-ils le contrat de test ? Aucune logique de dissimulation n'entre en jeu : tout reste traçable chez vous. Sous RGPD, vérifiez aussi que vos journaux de test ne capturent aucune donnée personnelle superflue.
Lire le trafic réseau du widget avec CDP
Une session CDP expose plusieurs signaux à la fois :
| Signal observé | Intérêt en QA | À contrôler |
|---|---|---|
| Requête réseau du widget | Confirme que le script CAPTCHA se charge | Hôte, paramètres, code de statut |
| État DOM du widget | Vérifie sitekey et callback | data-sitekey, conteneur, état d'erreur |
| Requête de vérification | Trace le chemin backend | Endpoint, identifiant de requête, latence |
| Réponse serveur | Explique la réussite ou l'échec du test | success, code d'erreur, métadonnées staging |
Une configuration minimale suffit pour ouvrir cette session sur un Chrome lancé en mode debug, par exemple sur un agent de CI ou une instance de staging chez OVHcloud :
import http from "node:http";
import WebSocket from "ws";
async function connectToCdp(port = 9222) {
const targets = await new Promise((resolve, reject) => {
http.get(`http://127.0.0.1:${port}/json/list`, (res) => {
let body = "";
res.on("data", (chunk) => (body += chunk));
res.on("end", () => resolve(JSON.parse(body)));
}).on("error", reject);
});
const pageTarget = targets.find((target) => target.type === "page");
const ws = new WebSocket(pageTarget.webSocketDebuggerUrl);
await new Promise((resolve, reject) => {
ws.once("open", resolve);
ws.once("error", reject);
});
let id = 0;
const send = (method, params = {}) => {
const requestId = ++id;
ws.send(JSON.stringify({ id: requestId, method, params }));
return requestId;
};
send("Page.enable");
send("Runtime.enable");
send("Network.enable");
return { ws, send };
}
Extraire le sitekey depuis la page de staging
Plutôt que de le supposer, lisez le sitekey directement depuis la page de staging : vous repérez les dérives de configuration au plus tôt.
async function readSitekey(pageUrl) {
const targetResponse = await fetch(
"http://127.0.0.1:9222/json/new?" + encodeURIComponent(pageUrl)
);
const target = await targetResponse.json();
const ws = new WebSocket(target.webSocketDebuggerUrl);
await new Promise((resolve, reject) => {
ws.once("open", resolve);
ws.once("error", reject);
});
ws.send(JSON.stringify({ id: 1, method: "Runtime.evaluate", params: {
expression: `(() => {
const widget = document.querySelector('[data-sitekey]');
if (!widget) return null;
return {
sitekey: widget.getAttribute('data-sitekey'),
widgetType: widget.className,
pageUrl: location.href,
};
})()`,
returnByValue: true,
}}));
return await new Promise((resolve) => {
ws.on("message", (payload) => {
const message = JSON.parse(payload);
if (message.id === 1) {
resolve(message.result.result.value);
ws.close();
}
});
});
}
Au-delà de la commande, c'est l'alignement avec votre configuration de staging qui compte :
| Contrôle sur le sitekey | Attendu |
|---|---|
| Environnement | Le sitekey correspond à l'environnement ciblé |
| Portée | Le widget n'apparaît que sur les formulaires prévus |
Callback / action |
Le nom figure dans vos données de test |
Déclencher une résolution CaptchaAI dans le test
Une fois la page et le sitekey confirmés, déclenchez une tâche CaptchaAI dans le même test et intégrez son résultat à la chaîne de diagnostic.
async function submitCaptchaTask({ apiKey, pageUrl, sitekey }) {
const body = new URLSearchParams({
key: apiKey,
method: "userrecaptcha",
googlekey: sitekey,
pageurl: pageUrl,
json: "1",
});
const submit = await fetch("https://ocr.captchaai.com/in.php", {
method: "POST",
body,
});
const submitJson = await submit.json();
if (submitJson.status !== 1) {
throw new Error(`CaptchaAI submit failed: ${submitJson.request}`);
}
for (let attempt = 0; attempt < 30; attempt += 1) {
await new Promise((resolve) => setTimeout(resolve, 5000));
const poll = await fetch(
`https://ocr.captchaai.com/res.php?key=${apiKey}&action=get&id=${submitJson.request}&json=1`
);
const pollJson = await poll.json();
if (pollJson.status === 1) {
return pollJson.request;
}
}
throw new Error("CaptchaAI result timeout in QA run");
}
L'objectif reste de retracer toute la chaîne : widget détecté, tâche envoyée, token reçu. CaptchaAI couvre ici reCAPTCHA v2 et v3, Cloudflare Turnstile et Cloudflare Challenge ; la validation finale se fait contre votre endpoint de test.
Contrôler la validation côté backend
L'étape décisive n'est souvent pas dans le navigateur, mais dans votre chemin de vérification. Faites en sorte que la suite QA enregistre la réponse backend avec un identifiant de requête.
async function verifyInQaBackend({ token, testRunId }) {
const response = await fetch("https://staging.example-app.test/qa/captcha/verify", {
method: "POST",
headers: { "content-type": "application/json" },
body: JSON.stringify({
token,
testRunId,
expectedAction: "signup",
environment: "staging",
}),
});
if (!response.ok) {
throw new Error(`QA verify endpoint returned ${response.status}`);
}
return response.json();
}
Une bonne réponse QA contient plus qu'un success: true ; elle vous laisse rejouer chaque cas sans toucher à la production :
| Champ de la réponse QA | Ce qu'il permet de vérifier |
|---|---|
| Identifiant de requête ou de trace | Rejouer un cas de test précis |
| Action ou identifiant de widget | Confirmer que le bon widget a été validé |
| Temps de réponse du backend | Suivre la latence du chemin de vérification |
| Code d'erreur | Couvrir les cas de test négatifs |
Environnement (staging, qa, preprod) |
Éviter toute confusion avec la production |
Dépannage
| Problème | Cause probable | Correctif |
|---|---|---|
| Le widget ne se charge pas | Mauvais script ou feature flag | Inspecter les requêtes réseau de staging |
| Le sitekey ne correspond pas | Dérive d'environnement | Comparer la valeur déployée et celle lue dans le DOM |
| L'endpoint QA renvoie 400 | Champs attendus manquants | Aligner le journal backend sur votre schéma |
| Timeout pendant le polling | File saturée en test | Augmenter le délai et mesurer la charge à part |
| Réponse backend incohérente | Données de test variables | Fixer des comptes et des fixtures reproductibles |
Questions fréquentes
CDP remplace-t-il un outil de test end-to-end comme Playwright ?
Non. CDP est une couche de diagnostic bas niveau, pas un framework de test. Vous l'utilisez en complément : Playwright ou Puppeteer pilotent le scénario, CDP observe le réseau et le DOM sous-jacents.
Peut-on intégrer ce diagnostic dans un pipeline CI ?
Oui. Lancez Chrome avec le port de debug distant sur l'agent CI, connectez la session CDP depuis le test, puis archivez les journaux réseau comme artefacts. Une instance de staging sur Scaleway ou en région AWS eu-west-3 (Paris) sert d'environnement de référence.
CaptchaAI ne prend-il en charge que reCAPTCHA v2 ?
Non. Il couvre reCAPTCHA v2 et v3, Cloudflare Turnstile et Cloudflare Challenge, GeeTest v3 et les CAPTCHA image/OCR. hCaptcha et FunCaptcha ne sont pas pris en charge.
Guides connexes
- Le guide de démarrage rapide CaptchaAI
- Les tests QA CAPTCHA en environnement autorisé
- Tester vos endpoints CAPTCHA dans les formulaires web
- Les tests CAPTCHA en intégration continue
Reliez chaque maillon de votre intégration CAPTCHA à des données traçables — CaptchaAI facilite des exécutions reproductibles dans vos environnements.