Cara Memecahkan CaptchaFox di Node.js dengan User Agent yang Tepat

Untuk memecahkan CaptchaFox di Node.js, panggil metode captchafox dari paket capskip dengan sitekey dan URL halaman, lalu kirim token yang dikembalikannya di field cf-captcha-response. Kirim permintaan itu dengan tiga hal yang tidak akan ditambahkan fetch untuk Anda: cookie yang disetel halaman, Referer, dan user agent yang dikembalikan CapSkip bersama token. User agent inilah jebakan yang paling sering menjerat kode Node. Fungsi fetch bawaan Node memberi tahu setiap server bahwa user agent-nya adalah node, dan situs yang mengharapkan token datang dari browser yang menerbitkannya akan menolak permintaan itu, sebagus apa pun pemecahannya. CapSkip menambahkan CaptchaFox pada versi 1.4.0. Panduan ini membahas cara membaca key, pemanggilan, pengiriman, percobaan ulang, dan menjalankan banyak pendaftaran sekaligus.
Apa yang Anda butuhkan
- CapSkip 1.4.0 atau lebih baru yang berjalan di komputer Windows. Rilis itu menambahkan CaptchaFox, bersama Friendly Captcha dan Capy Puzzle.
- Node.js 20.18.1 atau lebih baru, rilis tertua yang didukung cheerio. Untuk proyek baru, gunakan 22 atau 24, karena masa dukungan Node 20 sudah berakhir (end of life) pada April 2026.
- Paket capskip versi 1.3.0 atau lebih baru, rilis pertama yang memiliki metode captchafox, ditambah cheerio untuk membaca HTML.
- URL halaman yang menampilkan widget. Sitekey, field form, dan build widget semuanya diambil dari halaman itu.
- Sebuah alamat untuk pemecah CAPTCHA. Dalam mode Local, CapSkip menjawab di 127.0.0.1 hanya untuk perangkat itu; dalam mode Server, CapSkip mendengarkan di alamat jaringan atau IP publik Anda, sehingga skrip di mesin lain dapat memanggilnya melalui API. Keduanya diatur di pengaturan koneksi.
# capskip 1.3.0 added captchafox(); cheerio reads the HTML npm install capskip cheerio
Contoh kodenya berupa modul ES dengan top-level await. Simpan dengan ekstensi .mjs, atau setel field type di package.json Anda menjadi module, karena npm init sekarang menulis commonjs di sana. Paket capskip juga bisa dimuat dengan require jika proyek Anda memakai CommonJS.
Langkah 1: ambil halaman, simpan cookie-nya, dan baca sitekey
Fungsi fetch milik Node tidak menyimpan cookie di antara pemanggilan, sehingga cookie sesi yang disetel halaman sudah hilang saat Anda mengirim form. Situs yang mengikat token CSRF-nya ke sesi itu lalu menolak kiriman tersebut. Bawa sendiri cookie itu dengan Headers.getSetCookie(), yang mengembalikan setiap baris Set-Cookie secara terpisah. Panduan memecahkan Friendly Captcha di Node.js menjelaskan jar kecil ini secara lebih rinci.
// npm install capskip cheerio
import * as cheerio from "cheerio";
const PAGE_URL = "https://example.com/signup";
// fetch() keeps no cookies between calls, so carry the page's own.
const jar = new Map();
const page = await fetch(PAGE_URL);
for (const line of page.headers.getSetCookie()) {
const pair = line.split(";")[0];
const eq = pair.indexOf("=");
jar.set(pair.slice(0, eq).trim(), pair.slice(eq + 1).trim());
}
const html = await page.text();
const $ = cheerio.load(html);Sitekey bersifat publik, sama untuk setiap pengunjung, dan secara konvensi diawali sk_. Sebagian besar halaman menaruhnya di container widget, yaitu sebuah div dengan class captchafox dan atribut data-sitekey. Halaman yang membangun widget dari skripnya sendiri justru memberikan key itu ke pemanggilan captchafox.render. Jika tidak satu pun dari keduanya ada di HTML yang Anda ambil, buka DevTools: key-nya adalah segmen path setelah /captcha/ dalam permintaan ke api.captchafox.com, atau ke mam-api.captchafox.com di halaman MAM.
Selagi Anda di sana, periksa build mana yang memuat widget. Sebagian besar situs memuatnya dari cdn.captchafox.com dan mengharapkan token biasa. Beberapa platform justru menyematkan paket dari s.uicdn.com/mampkg/, dan situs tersebut mengharapkan token yang diawali MAM_. Halaman MAM bisa menyimpan key di alamat milik skrip itu sendiri, setelah ?key=. CDN yang sama juga menyajikan paket lain yang tidak berhubungan, jadi cocokkan path paket captchafox, bukan host-nya.
// The container, matched on the whole class name.
const widget = $(".captchafox").first();
// MAM pages may carry the key in the package's script src instead.
const mamSrc = $('script[src*="mampkg/@mamdev/core.frontend.libs.captchafox"]').attr("src");
const sitekey = widget.attr("data-sitekey")
?? (mamSrc && new URL(mamSrc, PAGE_URL).searchParams.get("key"))
?? html.match(/captchafox\.render\([\s\S]{0,300}?sitekey\s*:\s*["']([^"']+)/)?.[1];
const form = widget.length ? widget.closest("form") : $("form").first();
console.log(sitekey, Boolean(mamSrc)); // a MAM page needs a MAM_ tokenSelector class milik cheerio mencocokkan nama class secara utuh, sehingga elemen pembungkus dengan class seperti captchafox-wrapper tidak ikut terambil secara tidak sengaja. Fallback terakhir membaca key yang diberikan langsung (inline) ke pemanggilan render. Key yang berada di file skrip hasil bundle sama sekali tidak ada di HTML, dan DevTools adalah cara untuk menemukannya. Tanpa container, kode ini mengambil form pertama di halaman. Jika halaman juga punya kotak pencarian atau form kedua, pilih form pendaftaran berdasarkan id atau action-nya.
Langkah 2: pemanggilan captchafox
Untuk memecahkan CaptchaFox di Node.js, Anda cukup memakai satu metode. Metode ini menerima sitekey, URL halaman, dan objek opsi yang bersifat opsional, dan untuk widget standar, hanya dua yang pertama yang dibutuhkan.
import { CapSkip } from "capskip";
const solver = new CapSkip({ host: "127.0.0.1", port: 8080 });
// Copied from the script tag on MAM pages.
const MAM_PACKAGE = "https://s.uicdn.com/mampkg/@mamdev/core.frontend.libs.captchafox/";
const result = await solver.captchafox(sitekey, PAGE_URL, {
// undefined is dropped, so the standard widget sends nothing extra.
apiServer: mamSrc ? MAM_PACKAGE : undefined,
});
console.log(result.token.slice(0, 24)); // goes in cf-captcha-response
console.log(result.userAgent); // the browser that minted itresult.token dan result.code berisi string yang sama, dan result.captchaId adalah id yang diberikan CapSkip untuk job tersebut. result.userAgent adalah identitas browser yang menerbitkan token, yaitu browser milik CapSkip sendiri, bukan apa pun yang Anda kirim. Nilai ini hanya diisi jika pemecahan melaporkannya, jadi periksa dulu sebelum Anda memakainya.
URL halaman harus berupa halaman tempat widget benar-benar berjalan. CaptchaFox mendaftarkan setiap key terhadap daftar domain yang diizinkan dan memeriksa host sebelum menerbitkan apa pun. URL halaman di domain lain mana pun ditolak di setiap percobaan, jadi tautan yang dipendekkan, hasil pencarian, atau redirect dari domain lain tidak akan berhasil.
Opsi yang diterima metode ini
apiServer adalah alias dari api_server, yaitu build widget yang akan dipecahkan. Metode ini membuang opsi apa pun yang bernilai undefined atau null, itulah sebabnya baris di atas bisa memberikannya di setiap pemanggilan. Metode ini juga menerima objek proxy dengan key type dan uri, serta useragent, yang diterima tetapi sengaja tidak diterapkan, karena CapSkip memecahkan di browser sungguhan dengan identitasnya sendiri. Opsi timeout per panggilan, dalam detik, menggantikan recaptchaTimeout milik klien untuk satu pemecahan itu. Batas atas interval polling juga bisa disetel per panggilan, tetapi hanya sebagai polling_interval: pollingInterval dalam camelCase adalah milik konstruktor, dan jika diberikan per panggilan, opsi itu melempar ValidationException. Sitekey atau URL yang kosong, opsi yang tidak dikenal, dan tipe proxy selain HTTP, HTTPS, SOCKS5 atau SOCKS5H juga melempar ValidationException, sebelum permintaan apa pun meninggalkan mesin Anda.
Di TypeScript, tipe bawaan paket masih mendeskripsikan token sebagai opsional dan ditujukan untuk ALTCHA, sehingga strict mode membutuhkan non-null assertion pada result.token. Nilainya selalu ada untuk setiap pemecahan CaptchaFox.
Langkah 3: kirim dengan user agent yang menerbitkan token
Saat Anda memecahkan CaptchaFox di Node.js, inilah langkah yang menentukan apakah situs menerima token. Secara bawaan, fetch milik Node mengirim header User-Agent yang hanya berisi satu kata, node, baik di Node 20 maupun di Node 25. Itu bukan browser yang menghasilkan token, jadi salin nilai yang dikembalikan ke permintaan yang membawa token itu:
// The form's own fields, hidden CSRF token included.
const body = new URLSearchParams(
form.serializeArray().map((f) => [f.name, f.value]),
);
body.set("email", "YOUR_EMAIL");
body.set("cf-captcha-response", result.token);
const headers = {
cookie: [...jar].map(([k, v]) => `${k}=${v}`).join("; "),
// Browsers send the page as Referer; strict servers want one.
referer: PAGE_URL,
};
// Without this line, fetch announces itself as user-agent: node.
if (result.userAgent) headers["user-agent"] = result.userAgent;
const res = await fetch(new URL(form.attr("action") || PAGE_URL, PAGE_URL), {
method: "POST",
headers,
body,
});
console.log(res.status);serializeArray mengumpulkan field yang akan dikirim browser, termasuk token CSRF tersembunyi dan checkbox apa pun yang dicentang, sehingga Anda tidak perlu menyebut namanya satu per satu. Tombol submit tidak ikut dikumpulkan, jadi jika server memeriksa nama tombol, tambahkan dengan body.set. Referer sama pentingnya dengan cookie. Fungsi fetch tidak mengirim Referer maupun Origin, dan beberapa framework, salah satunya Django, menolak form post HTTPS yang tidak memiliki keduanya, bahkan dengan cookie dan token yang benar.
Dua aturan lagi berasal dari cara CaptchaFox memeriksa token di sisi situs. Setiap token hanya bisa diverifikasi sekali dan hanya dalam waktu singkat, jadi pecahkan saat Anda sudah siap, lalu langsung kirim. Selain itu, perlakukan token sebagai string opaque: jangan pernah memotong atau meng-encode ulang token. Sebagian situs mengirimnya di body JSON dari skrip mereka sendiri, jadi kirim form sekali secara manual dengan DevTools terbuka, lalu tiru apa yang dikirim halaman itu. Panduan memulai di dokumentasi CaptchaFox menunjukkan markup widget dan pemeriksaan di sisi server.
Langkah 4: percobaan ulang, tipe challenge, dan timeout
Anda tidak memilih challenge mana yang ditampilkan CaptchaFox. Sebagian besar pemecahan tidak menampilkan apa pun, karena bukti dari browser sudah lolos dengan sendirinya, dan jika puzzle geser muncul, CapSkip biasanya menyelesaikannya. Challenge pilih gambar dan audio jarang muncul dan tidak dipecahkan: keduanya kembali sebagai ApiException yang pesannya berisi ERROR_CAPTCHA_UNSOLVABLE, dalam hitungan detik, bukan di akhir timeout. Percobaan baru biasanya memunculkan challenge lain, jadi mencoba ulang itu sepadan, baik di CapSkip maupun di kode Anda.
import { ApiException } from "capskip";
async function solveCaptchaFox(sitekey, url, options = {}, attempts = 3) {
for (let attempt = 1; ; attempt++) {
try {
return await solver.captchafox(sitekey, url, options);
} catch (err) {
// Select, audio and unreadable slide draws come back unsolvable;
// redraw. Anything else, such as a wrong API key, is final.
const redraw = err instanceof ApiException && err.message.includes("UNSOLVABLE");
if (!redraw || attempt === attempts) throw err;
}
}
}Pesan ApiException adalah balasan mentah dari CapSkip, jadi pemeriksaan ini membaca kode error langsung dari pesan itu. Satu jebakan: key yang ditolak situs, misalnya di domain yang salah, juga terbaca sebagai tidak bisa dipecahkan, sehingga ikut dicoba ulang. Key itu gagal dalam hitungan detik di setiap percobaan dan tidak pernah berhasil, dan itulah tandanya. Cara lainnya adalah pengaturan Retries di baris CaptchaFox pada pengaturan CapSkip. Nilainya 0 sampai 3, dan 0 secara default. Dengan pengaturan ini, CapSkip mencoba ulang sendiri challenge yang tidak didukung, percobaan yang kehabisan waktu, dan error browser, tetapi tidak pernah mencoba ulang key yang ditolak.
captchafox melakukan polling dengan recaptchaTimeout milik klien, 300 detik secara default, karena ini adalah sesi browser sungguhan. CapSkip juga menjalankan timer-nya sendiri: sebuah tugas bisa menunggu hingga 250 detik (Wait Timeout) untuk salah satu dari 10 thread CaptchaFox (Max. Threads), dan satu percobaan mendapat 150 detik (Row Timeout). Jika ada thread yang kosong, percobaan yang gagal sampai ke Anda sebagai ApiException jauh sebelum 300 detik milik SDK habis. Setelah antrean yang panjang, SDK bisa mencapai batasnya lebih dulu dan melempar TimeoutException selagi CapSkip masih bekerja. Jadi berikan timeout yang lebih panjang saat Anda mengantrekan banyak pemecahan atau menaikkan Retries, karena setiap percobaan ulang bisa menambah satu Row Timeout lagi. SDK juga tetap melakukan polling meski terjadi error koneksi, jadi jika CapSkip berhenti di tengah pemecahan, pemanggilan berakhir dengan TimeoutException, bukan NetworkException.
Contoh lengkap yang berfungsi
Berikut seluruh prosesnya dalam satu file. signUp mengambil halaman, membaca key, memecahkan dengan percobaan ulang, lalu mengirim form beserta cookie-nya, Referer, dan user agent yang menerbitkan token.
// npm install capskip cheerio
// signup.mjs: run with node signup.mjs
import * as cheerio from "cheerio";
import {
CapSkip, ApiException, CapSkipError, TimeoutException, ValidationException,
} from "capskip";
const PAGE_URL = "https://example.com/signup";
// Copied from the script tag on MAM pages.
const MAM_PACKAGE = "https://s.uicdn.com/mampkg/@mamdev/core.frontend.libs.captchafox/";
const solver = new CapSkip({
apiKey: process.env.CAPSKIP_API_KEY ?? "capskip",
host: process.env.CAPSKIP_HOST ?? "127.0.0.1",
port: Number(process.env.CAPSKIP_PORT ?? 8080),
});
async function solveCaptchaFox(sitekey, url, options = {}, attempts = 3) {
for (let attempt = 1; ; attempt++) {
try {
return await solver.captchafox(sitekey, url, options);
} catch (err) {
// Select, audio and unreadable slide draws come back unsolvable.
const redraw = err instanceof ApiException && err.message.includes("UNSOLVABLE");
if (!redraw || attempt === attempts) throw err;
console.log(`attempt ${attempt}: ${err.message}`);
}
}
}
async function signUp(pageUrl, email) {
// One jar per run, so runs side by side never share a session.
const jar = new Map();
const page = await fetch(pageUrl);
for (const line of page.headers.getSetCookie()) {
const pair = line.split(";")[0];
const eq = pair.indexOf("=");
jar.set(pair.slice(0, eq).trim(), pair.slice(eq + 1).trim());
}
const html = await page.text();
const $ = cheerio.load(html);
const widget = $(".captchafox").first();
const mamSrc = $('script[src*="mampkg/@mamdev/core.frontend.libs.captchafox"]').attr("src");
const sitekey = widget.attr("data-sitekey")
?? (mamSrc && new URL(mamSrc, pageUrl).searchParams.get("key"))
?? html.match(/captchafox\.render\([\s\S]{0,300}?sitekey\s*:\s*["']([^"']+)/)?.[1];
if (!sitekey) throw new Error("No sitekey in the HTML; find it in DevTools.");
const form = widget.length ? widget.closest("form") : $("form").first();
const result = await solveCaptchaFox(sitekey, pageUrl, {
apiServer: mamSrc ? MAM_PACKAGE : undefined,
});
const body = new URLSearchParams(form.serializeArray().map((f) => [f.name, f.value]));
body.set("email", email);
body.set("cf-captcha-response", result.token);
const headers = {
cookie: [...jar].map(([k, v]) => `${k}=${v}`).join("; "),
referer: pageUrl,
};
if (result.userAgent) headers["user-agent"] = result.userAgent;
const action = new URL(form.attr("action") || pageUrl, pageUrl);
return fetch(action, { method: "POST", headers, body });
}
try {
const res = await signUp(PAGE_URL, "YOUR_EMAIL");
console.log(res.status, (await res.text()).slice(0, 80));
} catch (err) {
if (err instanceof ValidationException) console.error(`not sent: ${err.message}`);
else if (err instanceof TimeoutException) console.error("gave up after recaptchaTimeout");
else if (err instanceof CapSkipError) console.error(`solve failed: ${err.name}: ${err.message}`);
else throw err;
process.exitCode = 1;
}Jika skrip selalu gagal dalam hitungan detik setiap kali dijalankan, periksa URL halaman sebelum hal lain, karena key yang dipakai di luar domain terdaftarnya gagal dengan cara yang sama setiap kali. Jika pemeriksaan sitekey melempar error, halaman membangun widget dari skrip hasil bundle, dan key-nya ada di tab Network seperti dijelaskan di Langkah 1. Endpoint mentah di balik metode ini didokumentasikan di bagian CaptchaFox pada referensi API.
Menjalankan banyak pendaftaran secara berdampingan
Setiap metode CapSkip di Node mengembalikan Promise, dan AsyncCapSkip hanyalah nama lain untuk class yang sama, jadi menjalankan beberapa pemecahan secara berdampingan cukup dengan JavaScript biasa. Yang Anda butuhkan adalah batas. CapSkip menjalankan 10 pemecahan CaptchaFox sekaligus secara default dan membuat sisanya menunggu thread yang kosong, jadi pool kecil yang menjaga sepuluh pemecahan tetap berjalan sudah sesuai dengan itu. Pasang kode ini sebagai pengganti blok try di akhir contoh lengkap:
// At most `limit` calls in flight; a failure becomes that item's Error.
async function mapLimited(items, limit, fn) {
const results = new Array(items.length);
let next = 0;
async function worker() {
while (next < items.length) {
const i = next++;
results[i] = await fn(items[i]).catch((err) => err);
}
}
await Promise.all(Array.from({ length: Math.min(limit, items.length) }, worker));
return results;
}
const emails = ["YOUR_EMAIL_1", "YOUR_EMAIL_2", "YOUR_EMAIL_3"];
const results = await mapLimited(emails, 10, (email) => signUp(PAGE_URL, email));
for (const r of results) console.log(r instanceof Error ? r.message : r.status);signUp adalah fungsi dari contoh lengkap. Fungsi ini membuat cookie jar sendiri di setiap pemanggilan, dan itulah yang membuatnya aman dijalankan secara paralel: satu jar yang dipakai bersama oleh sepuluh proses akan mencampuradukkan sesi dan token CSRF mereka. Fungsi ini juga menyimpan setiap token bersama user agent-nya sendiri sampai form dikirim. Naikkan Max. Threads di pengaturan CaptchaFox pada CapSkip untuk pool yang lebih besar. CaptchaFox juga menilai jaringan, bukan hanya browser, jadi banyak pemecahan dari satu alamat akan menaikkan frekuensi challenge dalam proses yang panjang. Siapkan proxy dengan tombol Configure Proxies di baris yang sama, atau berikan objek proxy di setiap pemanggilan.
Menjalankan solver di mesin lain
127.0.0.1 sudah benar selama skrip dan CapSkip berada di PC Windows yang sama. Begitu kode Node dipindahkan ke VPS, container, CI runner, atau serverless function, loopback menunjuk ke mesin yang salah dan pemecahan pertama melempar NetworkException dengan ECONNREFUSED. Alihkan CapSkip ke mode Server dan ia akan mendengarkan di alamat jaringan atau IP publik Anda, sehingga semua lingkungan itu dapat memanggilnya melalui API yang sama. Gunakan IP publik statis jika rutenya melewati internet, aktifkan validasi API key, dan batasi port hanya untuk alamat yang Anda harapkan dengan aturan Windows Firewall. Pemecah CAPTCHA tetap berupa mesin Windows milik Anda sendiri, dan pemecahannya tetap tanpa kuota.
Klien tidak membaca variabel lingkungan dengan sendirinya. Baca CAPSKIP_HOST, CAPSKIP_PORT dan CAPSKIP_API_KEY di kode Anda dan berikan ke konstruktor, seperti pada contoh lengkap, agar skrip yang sama bisa berjalan di komputer Anda maupun di server.
Kesalahan umum dan artinya
| Apa yang Anda lihat | Penyebab | Perbaiki |
|---|---|---|
| Situs menolak token yang dikembalikan CapSkip sebagai berhasil dipecahkan | Form dikirim dengan user-agent: node, bawaan fetch, bukan sebagai browser yang menerbitkan token | Kirim result.userAgent sebagai header User-Agent pada permintaan itu |
| Ditolak padahal user agent sudah cocok | Halaman memuat paket MAM tetapi pemecahan memakai widget default, atau sebaliknya | Baca tag script dan setel apiServer agar sesuai dengannya |
| Respons 403 saat form dikirim, padahal token dan user agent valid | Cookie sesi tidak dikirim, sehingga field CSRF tidak lagi cocok, atau kiriman tidak memiliki Referer | Bawa cookie dari pengambilan halaman dan kirim URL halaman sebagai Referer |
| result.userAgent bernilai undefined | Pemecahan tidak melaporkan user agent, sehingga fetch mengirim user agent-nya sendiri | Pertahankan pemeriksaan if; jika situs menolak node, kirim sendiri user agent browser desktop versi terbaru |
| ApiException dalam hitungan detik, setiap kali, untuk satu key | URL halaman berada di luar domain tempat key didaftarkan, atau key itu sendiri salah | Kirim halaman tempat widget berjalan, bukan redirect atau hasil pencarian, dan periksa ulang key-nya |
| ApiException sesekali yang berisi ERROR_CAPTCHA_UNSOLVABLE | CaptchaFox menampilkan challenge pilih gambar atau audio, atau puzzle geser yang tidak bisa dibaca CapSkip | Coba ulang di kode, atau naikkan Retries di pengaturan CaptchaFox pada CapSkip |
| Token yang berhasil sekali gagal pada kali kedua | Setiap token hanya bisa diverifikasi sekali dan cepat kedaluwarsa | Pecahkan token baru untuk setiap pengiriman, dan langsung kirim |
| ValidationException sebelum apa pun terkirim | Sitekey atau URL kosong, opsi yang tidak diterima metode ini, seperti pollingInterval per panggilan, atau tipe proxy yang tidak diterima CapSkip | Pastikan sitekey ditemukan, dan perbaiki atau buang opsi yang disebut dalam pesan |
| TimeoutException setelah lima menit | Waktu menunggu thread CaptchaFox yang kosong ditambah pemecahannya sendiri melewati 300 detik milik SDK, atau CapSkip berhenti di tengah pemecahan | Batasi ukuran pool sesuai Max. Threads, atau berikan timeout yang lebih panjang untuk pemanggilan itu |
| NetworkException dengan ECONNREFUSED atau ETIMEDOUT pada pemanggilan pertama | CapSkip tidak berjalan, host atau port-nya salah, atau firewall memblokir koneksi | Jalankan CapSkip, lalu periksa apakah ia harus berada di mode Local atau mode Server |
FAQ
Apakah axios atau got terhindar dari masalah user agent?
Tidak. Keduanya hanya mengganti namanya. axios mengirim axios diikuti nomor versinya, dan got mengirim got diikuti alamat repositori GitHub-nya. Tidak satu pun dari keduanya menyimpan cookie atau mengirim Referer kecuali Anda mengaturnya, jadi tiga header yang sama tetap berlaku. Apa pun kliennya, setel user agent dari result.userAgent pada permintaan yang membawa token.
Bisakah saya memakai token di Puppeteer atau Playwright sebagai gantinya?
Bisa, asalkan halaman yang mengirimnya berjalan dengan user agent yang dikembalikan CapSkip. Pecahkan dulu, lalu buka context Playwright dengan browser.newContext({ userAgent: ua }), atau panggil page.setUserAgent(ua) di Puppeteer sebelum halaman dimuat. Muat form, tulis token ke field cf-captcha-response, lalu kirim. Jika otomatisasi Anda tidak membutuhkan browser untuk hal lain, cara dengan fetch di atas lebih ringan.
Apa bedanya dengan versi Python?
Pemanggilan dan aturannya sama, begitu juga jebakan utamanya: klien HTTP mengirim namanya sendiri sebagai user agent. Di Python, nama itu adalah python-requests atau python-httpx, dan requests.Session menyimpan cookie untuk Anda. Di Node, namanya node, dan Anda membawa cookie sendiri. Sisi Python dibahas di panduan memecahkan CaptchaFox di Python.
Versi singkatnya
Untuk memecahkan CaptchaFox di Node.js, ambil halaman dan simpan cookie-nya, baca sitekey dari container captchafox, pemanggilan render, atau skrip MAM, lalu catat build mana yang dimuat halaman. Panggil solver.captchafox() dengan sitekey dan URL halaman yang sebenarnya, dan tambahkan apiServer hanya untuk halaman MAM. Kirim result.token di cf-captcha-response bersama cookie halaman, halaman itu sebagai Referer, dan result.userAgent sebagai header User-Agent, sekali saja dan secepatnya. Coba ulang challenge yang tidak bisa dipecahkan, jangan jalankan lebih banyak pemecahan sekaligus daripada Max. Threads, yaitu 10 secara default, dan beralihlah ke mode Server begitu skrip tidak lagi berada di mesin pemecah CAPTCHA.
- Cara kerja CaptchaFox dan apa saja yang dicakup pemecah CAPTCHA: halaman pemecah CaptchaFox.
- Setiap tipe CAPTCHA yang ditangani paket Node.js: halaman pemecah CAPTCHA Node.js.
Challenge yang ditampilkan ulang adalah satu-satunya bentuk percobaan ulang yang biasanya dibutuhkan tipe ini, dan dengan pemecah captcha tanpa batas di mesin Anda sendiri, setiap challenge baru hanya memakan beberapa detik, bukan satu pemecahan berbayar lagi.
