Envoyer un jeton résolu dans une requête JSON Playwright
Interceptez la requête POST JSON connue de l’application et remplacez son champ CAPTCHA par solution.token. Remplir une zone de texte n’aidera pas si l’application construit sa requête à partir de l’état JavaScript.
L’exemple ci-dessous cible le point de terminaison de soumission de même origine d’une application dont vous êtes propriétaire. Il conserve les autres champs JSON et les en-têtes de requête plutôt que de reconstruire la requête.
Sur cette page
Adapter l’exemple à votre application
- 1.
Préparer le service de résolution
Utilisez Node.js 22+, Playwright et le SDK JavaScript officiel. Suivez les instructions d’installation du SDK ; utilisez le téléchargement du paquet indiqué dans la documentation plutôt que de présumer de sa disponibilité sur le registre npm. Conservez
SOLVETHREE_API_KEYdans le processus Node.js, pas dans le code du navigateur. - 2.
Configurer le site et le proxy
Définissez
TARGET_URLsur l’URL de votre page de test etSOLVETHREE_PROXYsur l’URL de son proxy HTTP ou HTTPS. L’exemple demande l’actionloginpour le nom d’hôte de la page. Ce nom d’hôte nécessite un profil actif dans l’espace de travail ; configurez d’abord le profil du site. Modifiez l’action si votre application en utilise une autre. - 3.
Identifier précisément la requête d’envoi
Définissez
TARGET_SUBMIT_URLsur le point de terminaison POST JSON, chemin compris. Il doit avoir la même origine que la page. L’exemple attend un objet contenantrecaptchaTokenet un bouton dont le nom accessible est exactementSubmit. Modifiez ensemble ces éléments propres à l’application.
Pour votre dispositif de test, utilisez une page qui envoie un objet JSON à ce point de terminaison et renvoie une réponse que vous pouvez inspecter. Incluez un autre champ ainsi qu’un champ CSRF pour vérifier qu’aucun des deux ne change. Un dispositif local qui se contente de renvoyer les données reçues peut démontrer la réécriture du JSON, mais ne vérifie pas l’acceptation du CAPTCHA. L’exemple fourni effectue tout de même une résolution réelle et nécessite un site configuré, accessible via le proxy.
Résoudre, intercepter et envoyer
import { chromium } from 'playwright';
import { Solvethree } from '@solvethree/sdk';
const client = new Solvethree({ apiKey: process.env.SOLVETHREE_API_KEY });
const target = new URL(process.env.TARGET_URL);
const proxy = new URL(process.env.SOLVETHREE_PROXY);
const result = await client.solve({ site: target.hostname, action: 'login', proxy: process.env.SOLVETHREE_PROXY });
const proxyConfig = { server: `${proxy.protocol}//${proxy.host}`, username: decodeURIComponent(proxy.username), password: decodeURIComponent(proxy.password) };
const submit = new URL(process.env.TARGET_SUBMIT_URL);
if (submit.origin !== target.origin) throw new Error('Use this demo with a same-origin submission URL');
const browser = await chromium.launch();
try {
const context = await browser.newContext({ proxy: proxyConfig, userAgent: result.solution.userAgent,
extraHTTPHeaders: { 'sec-ch-ua': result.solution.secChUa } });
const page = await context.newPage();
await page.route(submit.href, async route => {
if (route.request().method() !== 'POST') return route.continue();
const body = route.request().postDataJSON();
if (!body || typeof body !== 'object' || Array.isArray(body)) throw new Error('Expected the known JSON object');
await route.continue({ postData: JSON.stringify({ ...body, recaptchaToken: result.solution.token }),
headers: { ...route.request().headers(), 'content-type': 'application/json' } });
});
await page.goto(target.href);
const outcome = page.waitForResponse(r => r.url() === submit.href && r.request().method() === 'POST');
await page.getByRole('button', { name: 'Submit', exact: true }).click();
console.log('Application HTTP status:', (await outcome).status());
// recaptchaToken, the Submit button and this endpoint belong to this demo app.
// Adapt them to the real application, retaining its session/CSRF data.
await context.close();
} finally { await browser.close(); }client.solve crée la tâche et interroge son état jusqu’à ce qu’elle soit prête ou qu’une exception soit levée. L’exemple crée ensuite un contexte de navigateur avec solution.userAgent, solution.secChUa et le même proxy unique que celui fourni pour la résolution. Le SDK n’applique pas la solution au navigateur ; c’est le gestionnaire de route qui s’en charge.
Le contexte de navigateur est nouveau. Si l’envoi nécessite une authentification ou une autre préparation de session, effectuez-la dans ce contexte avant l’envoi. L’exemple n’importe pas de session de navigateur existante.
Remplacer le jeton, pas toute la requête
La route est enregistrée avant la navigation et limitée à l’URL d’envoi configurée. Les requêtes autres que POST continuent sans modification. Pour une requête POST, le gestionnaire lit l’objet JSON existant, copie ses champs et remplace uniquement recaptchaToken.
Cela préserve les champs du corps, comme les valeurs du formulaire et les données CSRF. Le gestionnaire copie également les en-têtes de la requête et définit le type de contenu sur JSON. Conservez le fonctionnement existant de l’application pour la session et la protection CSRF ; un jeton résolu ne remplace ni l’une ni l’autre.
N’étendez pas la route à toutes les requêtes et ne remplacez pas un champ simplement parce qu’il ressemble à un jeton. Inspectez la requête sortante de votre application et utilisez le véritable nom du champ. Cet exemple ne détecte pas les widgets, n’appelle pas de fonctions de rappel arbitraires et ne prend pas en charge n’importe quelle page tierce. La documentation réseau de Playwright décrit le mécanisme d’interception.
Vérifiez la réponse de l’application
L’attente de la réponse commence avant le clic et cible l’URL d’envoi ainsi que la méthode POST. Le statut consigné est celui de la réponse de l’application, pas celui de la tâche solvethree. Inspectez le corps de cette réponse ou l’état résultant de l’application selon ses propres critères de réussite. Ni une tâche prête ni un statut HTTP de succès ne prouvent à eux seuls que l’application a accepté le jeton.
- L’attente de la réponse ne se termine jamais.
Vérifiez que le bouton Submit exact déclenche bien une requête POST vers l’URL configurée.
Essayez ceci : Corrigez le localisateur du bouton, le point de terminaison ou la méthode pour qu’ils correspondent à l’application. N’étendez pas l’interception au trafic sans rapport.
- La route ne parvient pas à lire un objet JSON.
Inspectez le corps de la requête et le type de contenu.
Essayez ceci : Utilisez ce gestionnaire uniquement pour le point de terminaison connu qui attend un objet JSON. Les données de formulaire, les tableaux et les autres formats de charge utile nécessitent un traitement différent.
- La tâche est prête, mais l’application rejette l’envoi.
Inspectez le JSON sortant pour y vérifier la présence de
solution.token, puis vérifiez les données de session et CSRF, l’action, l’identité de navigateur renvoyée et le proxy.Essayez ceci : Corrigez les incohérences de la requête avant de payer une autre résolution. Gardez le navigateur sur le proxy de la résolution et utilisez l’identité renvoyée.
- La résolution échoue avant l’ouverture du navigateur.
Distinguez une erreur de requête HTTP d’un échec définitif de la tâche. Pour une tâche en échec, inspectez
errorCodeeterror.Essayez ceci : Corrigez le problème signalé concernant les données d’entrée, le profil ou la connectivité plutôt que de réessayer avec des données inchangées. Consultez la gestion des erreurs de l’API.
Sources et référence de l’API
Lancez votre première tâche.
Démarrez avec $5 de crédit dans votre espace de travail.