Scarnox · Blog

Solver captcha di Node.js: contoh kerja dengan fetch (2026)

Solver captcha di Node.js adalah satu request HTTP. Node 18 dan yang lebih baru sudah menyertakan fetch, jadi Anda tidak perlu package untuk memanggil API. Kirim sitekey dan URL halaman, tunggu responsnya, lalu masukkan token ke form. Panduan ini menunjukkan seluruh alur untuk PopularCaptcha, yang saat ini di-solve Scarnox secara proxyless.

Mulai dengan kredit uji coba gratis, tanpa kartu dan jalankan kode di bawah ini terhadap halaman uji terlebih dahulu.

Kebutuhan

Modul solver

Modul di bawah ini berupa satu fungsi. Ia mengirim POST ke API dengan header Bearer, membatalkan request setelah 185 detik, dan melempar error jika errorId bukan 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), // panggilan kembali saat token siap
  });

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

Tidak ada polling. Request tetap terbuka sampai token siap, dan token ada di solution.token saat berhasil.

Retry

Solve yang gagal mengembalikan errorId selain 0, dan Anda tidak dikenai biaya untuknya. Loop retry yang singkat sudah cukup untuk kegagalan sementara. Jaga jumlah percobaan tetap rendah, agar captcha dengan sitekey atau URL halaman yang salah tidak menghabiskan waktu:

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

Untuk kebijakan error yang lebih lengkap, lihat penanganan error solver captcha.

Mengirim token

Token dimasukkan ke field form yang diharapkan situs. Kebanyakan halaman PopularCaptcha membaca h-captcha-response, dan banyak yang juga membaca g-recaptcha-response. Kirim keduanya agar aman:

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

Jalankan dengan:

SCARNOX_API_KEY=scarnox_YOURAPIKEY node submit.mjs

fetch biasa tidak menyimpan cookie di antara request. Banyak halaman signup dan pencarian mengikat captcha ke cookie sesi, sehingga token yang dikirim tanpa cookie yang cocok bisa ditolak. Ada dua cara untuk menanganinya:

Pilih cara pertama jika form-nya sederhana dan situsnya tidak banyak menjalankan JavaScript. Pilih cara kedua untuk hal yang lebih rumit.

Cara praktis untuk memeriksa: setelah POST, lihat kode status dan URL akhirnya. Redirect ke halaman sukses biasanya berarti token diterima. Halaman yang menampilkan widget lagi biasanya berarti token ditolak, atau cookie dari GET tidak ikut terkirim. Catat body respons untuk beberapa run pertama agar Anda tahu kasus mana yang sedang terjadi.

Waktu

Token kedaluwarsa dalam sekitar dua menit. Lakukan solve mendekati saat Anda mengirim. Kesalahan yang umum adalah melakukan solve di awal job yang panjang lalu mengirim jauh setelahnya. Solve, lalu kirim segera. Masa berlaku token captcha membahas ini lebih detail.

Captcha invisible

Jika widget halaman memiliki data-size="invisible", berikan { invisible: true }. Fungsi kemudian mengirim is_invisible: true bersama request:

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

Jika halaman juga memasang callback ke widget, form mungkin memerlukan fungsi tersebut dipanggil dengan token. Baca script halaman untuk menemukannya. Panduan captcha invisible membahas polanya.

Scraping dengan solver

Kadang captcha muncul di halaman yang Anda scrape, bukan di form yang Anda kirim. Polanya tetap sama: deteksi widget di HTML, solve, lalu kirim ke URL tempat widget tersebut mengirim data. Jaga rate request tetap rendah dan cek terms situs terlebih dahulu. Scrape secara bertanggung jawab: patuhi robots.txt, hindari data pribadi yang tidak Anda perlukan, dan jangan membebani server.

Harga

Scarnox menagih per solve yang berhasil. Solve yang gagal tidak dikenai biaya. Untuk tarif terkini, lihat halaman harga. Untuk memulai, mulai dengan kredit uji coba gratis, tanpa kartu.

Langkah selanjutnya