Scarnox · Blog

Solver captcha in Node.js: esempio funzionante con fetch (2026)

Un solver captcha in Node.js è una sola richiesta HTTP. Node 18 e successivi includono fetch, quindi non serve alcun pacchetto per chiamare l'API. Invii la sitekey e l'URL della pagina, aspetti la risposta e metti il token nel form. Questa guida mostra l'intero flusso per PopularCaptcha, che Scarnox risolve oggi in modalità proxyless.

Inizia con crediti di prova gratuiti, senza carta di credito ed esegui il codice qui sotto su una pagina di test prima di tutto il resto.

Requisiti

Il modulo solver

Il modulo seguente è una singola funzione. Invia la richiesta all'API con un header Bearer, interrompe dopo 185 secondi e lancia un errore quando errorId non è 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), // la chiamata ritorna quando il token è pronto
  });

  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;
}

Non c'è polling. La richiesta resta aperta finché il token non è pronto, e il token è in solution.token in caso di successo.

Retry

Una risoluzione fallita restituisce errorId diverso da 0, e non viene addebitata. Un breve ciclo di retry basta per gli errori temporanei. Tieni basso il numero di tentativi, così una sitekey o un URL di pagina sbagliati non consumano tempo:

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;
}

Per una politica di errori più completa, vedi gestione degli errori del solver captcha.

Invio del token

Il token va nel campo del form che il sito si aspetta. La maggior parte delle pagine PopularCaptcha legge h-captcha-response, e molte leggono anche g-recaptcha-response. Inviali entrambi per sicurezza:

// 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);

Eseguilo con:

SCARNOX_API_KEY=scarnox_YOURAPIKEY node submit.mjs

Il fetch semplice non mantiene i cookie tra una richiesta e l'altra. Molte pagine di registrazione e ricerca legano il captcha a un cookie di sessione, quindi un token inviato senza il cookie corrispondente può essere rifiutato. Ci sono due modi per gestirlo:

Scegli il primo quando il form è semplice e il sito non usa molto JavaScript. Scegli il secondo per tutto ciò che è più complesso.

Un controllo pratico: dopo la POST, guarda lo stato HTTP e l'URL finale. Un reindirizzamento a una pagina di successo di solito significa che il token è stato accettato. Una pagina che mostra di nuovo il widget di solito significa che è stato rifiutato, oppure che il cookie della GET non è stato inviato. Registra il corpo della risposta per le prime esecuzioni, così capisci in quale caso ti trovi.

Tempistiche

Il token scade in circa due minuti. Risolvi vicino al momento dell'invio. L'errore più comune è risolvere all'inizio di un job lungo e inviare molto dopo. Risolvi, poi invia subito. Scadenza del token captcha approfondisce il tema.

Captcha invisibili

Se il widget della pagina ha data-size="invisible", passa { invisible: true }. La funzione invia allora is_invisible: true con la richiesta:

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

Se la pagina collega anche una callback al widget, il form potrebbe richiedere che quella funzione venga chiamata con il token. Leggi lo script della pagina per trovarla. La guida sul captcha invisibile tratta i pattern.

Scraping con il solver

A volte il captcha compare su una pagina che fai scraping, non su un form che invii. Lo stesso pattern funziona: individua il widget nell'HTML, risolvilo, poi invialo all'URL a cui il widget invia i dati. Mantieni basso il ritmo delle richieste e controlla prima i termini del sito. Fai scraping in modo responsabile: rispetta robots.txt, evita i dati personali che non ti servono e non martellare il server.

Prezzi

Scarnox addebita per ogni risoluzione riuscita. Le risoluzioni fallite non vengono addebitate. Per le tariffe attuali, consulta la pagina dei prezzi. Per iniziare, inizia con crediti di prova gratuiti, senza carta di credito.

Prossimi passi