Scarnox · Blog

Solveur de captcha en Node.js : exemple complet avec fetch (2026)

Un solveur de captcha en Node.js tient en une seule requête HTTP. Node 18 et les versions suivantes fournissent fetch, vous n'avez donc besoin d'aucun paquet pour appeler l'API. Envoyez la sitekey et l'URL de la page, attendez la réponse, et placez le token dans le formulaire. Ce guide montre le flux complet pour PopularCaptcha, que Scarnox résout aujourd'hui sans proxy.

Démarrez avec un crédit d'essai gratuit, sans carte bancaire et exécutez d'abord le code ci-dessous sur une page de test.

Prérequis

Le module du solveur

Le module ci-dessous est une seule fonction. Elle envoie une requête à l'API avec un en-tête Bearer, s'interrompt après 185 secondes, et lève une erreur lorsque errorId n'est pas 0 :

// solver.mjs
const API_URL = "https://api.scarnox.com/api/tasks/create";

export async function solveCaptcha(sitekey, pageUrl, { invisible = false } = {}) {
  const body = {
    captcha_type: "PopularCaptchaTaskProxyless",
    site_key: sitekey,
    site_url: pageUrl,
  };
  if (invisible) body.is_invisible = true;

  const res = await fetch(API_URL, {
    method: "POST",
    headers: {
      Authorization: `Bearer ${process.env.SCARNOX_API_KEY}`,
      "Content-Type": "application/json",
    },
    body: JSON.stringify(body),
    signal: AbortSignal.timeout(185_000), // l'appel revient lorsque le token est prêt
  });

  const data = await res.json().catch(() => null);
  if (!data) throw new Error(`HTTP ${res.status}: response was not JSON`);

  if (data.errorId !== 0) {
    throw new Error(`${data.errorCode}: ${data.errorDescription}`);
  }
  return data.solution.token;
}

Il n'y a pas de polling. La requête reste ouverte jusqu'à ce que le token soit prêt, et le token se trouve dans solution.token en cas de succès.

Réessais

Une résolution échouée renvoie un errorId différent de 0, et elle n'est pas facturée. Une courte boucle de réessai suffit pour les échecs transitoires. Limitez le nombre de tentatives, pour qu'une sitekey ou une URL de page erronée ne consomme pas du temps inutilement :

export async function solveWithRetry(sitekey, pageUrl, attempts = 3) {
  let lastError;
  for (let i = 1; i <= attempts; i++) {
    try {
      return await solveCaptcha(sitekey, pageUrl);
    } catch (err) {
      lastError = err;
      console.warn(`Attempt ${i} failed: ${err.message}`);
      await new Promise((r) => setTimeout(r, 1000 * i));
    }
  }
  throw lastError;
}

Pour une politique d'erreur plus complète, consultez la gestion des erreurs du solveur de captcha.

Soumettre le token

Le token va dans le champ de formulaire attendu par le site. La plupart des pages PopularCaptcha lisent h-captcha-response, et beaucoup lisent aussi g-recaptcha-response. Envoyez les deux par prudence :

// submit.mjs
import { solveWithRetry } from "./solver.mjs";

const pageUrl = "https://example.com/signup";
const token = await solveWithRetry("YOUR-SITEKEY-UUID", pageUrl);

const form = new URLSearchParams({
  email: "you@example.com",
  "h-captcha-response": token,
  "g-recaptcha-response": token,
});

const res = await fetch(pageUrl, {
  method: "POST",
  body: form,
  redirect: "manual",
});
console.log("Status:", res.status);

Exécutez-le avec :

SCARNOX_API_KEY=scarnox_YOURAPIKEY node submit.mjs

Cookies et sessions

Un fetch simple ne conserve pas les cookies entre les requêtes. Beaucoup de pages d'inscription et de recherche rattachent le captcha à un cookie de session, si bien qu'un token envoyé sans le cookie correspondant peut être rejeté. Il y a deux façons de gérer cela :

Choisissez la première option lorsque le formulaire est simple et que le site n'exécute pas beaucoup de JavaScript. Choisissez la seconde pour tout ce qui est plus complexe.

Un contrôle pratique : après le POST, regardez le code de statut et l'URL finale. Une redirection vers une page de succès signifie généralement que le token a été accepté. Une page qui réaffiche le widget signifie en général qu'il a été rejeté, ou que le cookie du GET n'a pas été transmis. Journalisez le corps de la réponse pendant les premières exécutions pour savoir dans quel cas vous vous trouvez.

Timing

Le token expire en environ deux minutes. Résolvez au plus près du moment où vous soumettez. L'erreur habituelle consiste à résoudre au début d'un long job et à soumettre plus tard. Résolvez, puis soumettez immédiatement. L'expiration des tokens de captcha détaille ce point.

Captchas invisibles

Si le widget de la page a data-size="invisible", passez { invisible: true }. La fonction envoie alors is_invisible: true avec la requête :

const token = await solveCaptcha("YOUR-SITEKEY-UUID", pageUrl, { invisible: true });

Si la page rattache aussi un callback au widget, le formulaire peut nécessiter l'appel de cette fonction avec le token. Lisez le script de la page pour la trouver. Le guide sur le captcha invisible couvre les schémas à suivre.

Scraper avec le solveur

Il arrive que le captcha apparaisse sur une page que vous scrapez plutôt que sur un formulaire que vous soumettez. Le même schéma fonctionne : détectez le widget dans le HTML, résolvez-le, puis soumettez-le à l'URL vers laquelle le widget envoie ses données. Gardez un faible rythme de requêtes et vérifiez d'abord les conditions du site. Scrapez de manière responsable : respectez le robots.txt, évitez les données personnelles dont vous n'avez pas besoin, et ne martelez pas le serveur.

Tarifs

Scarnox facture par résolution réussie. Les résolutions échouées ne sont pas facturées. Pour les tarifs actuels, consultez la page tarifs. Pour commencer, démarrez avec un crédit d'essai gratuit, sans carte bancaire.

Étapes suivantes