Memecahkan PopularCaptcha di Playwright dan Puppeteer (Node.js)
Otomatisasi browser terhenti begitu PopularCaptcha muncul. Mengklik melewati kisi gambar dari skrip itu lambat dan rapuh. Mendapatkan token dari API pemecah dan memasukkannya ke halaman hanya membutuhkan satu request, dan sisa skrip Anda berjalan seperti biasa.
Panduan ini membahas Playwright dan Puppeteer dengan Node.js. Alurnya sama di keduanya, dan contohnya menggunakan solve proxyless, yang dijalankan Scarnox di jaringannya sendiri. PopularCaptcha adalah jenis yang dipecahkan Scarnox saat ini. Jenis captcha lain segera hadir, jadi kode di bawah hanya untuk PopularCaptcha.
Alurnya
- Baca sitekey dari halaman.
- Minta token ke Scarnox dengan satu POST request yang menunggu.
- Masukkan token ke field respons, atau berikan ke callback situs, lalu kirim form.
Siapkan kuncinya
Buat akun dan mulai dengan kredit uji coba gratis, tanpa kartu. Simpan kunci di environment variable, jangan pernah di kode pengujian:
export SCARNOX_KEY="scarnox_YOURAPIKEY"
Node 18 dan yang lebih baru sudah menyertakan fetch, jadi panggilan API tidak membutuhkan paket tambahan.
Playwright
import { chromium } from "playwright";
const API_KEY = process.env.SCARNOX_KEY;
async function solve(sitekey, url) {
const r = await fetch("https://api.scarnox.com/api/tasks/create", {
method: "POST",
headers: { Authorization: `Bearer ${API_KEY}`, "Content-Type": "application/json" },
body: JSON.stringify({ captcha_type: "PopularCaptchaTaskProxyless", site_key: sitekey, site_url: url }),
});
const data = await r.json();
if (data.errorId !== 0) throw new Error(`${data.errorCode}: ${data.errorDescription}`);
return data.solution.token;
}
const browser = await chromium.launch();
const page = await browser.newPage();
await page.goto("https://example.com/signup");
const sitekey = await page.getAttribute("[data-sitekey]", "data-sitekey");
const token = await solve(sitekey, page.url());
// Masukkan token ke kedua field respons yang mungkin dibaca situs.
await page.evaluate((t) => {
for (const name of ["h-captcha-response", "g-recaptcha-response"]) {
document.querySelectorAll(`[name="${name}"]`).forEach((el) => { el.value = t; });
}
}, token);
await page.fill("#email", "you@example.com");
await page.click("button[type=submit]");
Perhatikan bahwa site_url berasal dari page.url(). Itu adalah halaman tempat widget berada, yang dibutuhkan solver. Solve dilakukan setelah halaman dimuat, jadi sitekey sudah ada di DOM.
Puppeteer
Puppeteer hanya berbeda dalam API selector. Gunakan kembali fungsi solve di atas dan ganti panggilan halamannya:
const sitekey = await page.$eval("[data-sitekey]", (el) => el.dataset.sitekey);
const token = await solve(sitekey, page.url());
await page.evaluate((t) => {
document.querySelectorAll('[name="h-captcha-response"],[name="g-recaptcha-response"]')
.forEach((el) => { el.value = t; });
}, token);
Ketika situs menggunakan callback
Beberapa situs tidak membaca field tersembunyi. Mereka menunggu callback JavaScript dari widget. Temukan fungsi yang disebutkan di atribut data-callback widget, lalu panggil dengan token:
await page.evaluate((t) => {
const name = document.querySelector("[data-sitekey]")?.dataset.callback;
if (name && typeof window[name] === "function") window[name](t);
}, token);
Jika situs menggunakan keduanya, isi field dan panggil callback. Melakukan keduanya tidak masalah.
Widget tak terlihat
Widget tak terlihat tidak memiliki kotak centang. Situs memulainya dari kodenya sendiri, biasanya saat pengunjung menekan kirim. Kirim request yang sama dengan field opsional is_invisible yang diatur ke true:
body: JSON.stringify({
captcha_type: "PopularCaptchaTaskProxyless",
site_key: sitekey,
site_url: url,
is_invisible: true,
}),
Panduan captcha tak terlihat menjelaskan cara mengenali widget ini dan cara mengembalikan token.
Tips waktu
- Ambil token tepat sebelum Anda mengirim. Token kedaluwarsa dalam sekitar dua menit.
- Berikan request solve timeout yang panjang, sekitar 185 detik. Panggilan ini menunggu sampai token siap.
- Solve yang gagal gratis, jadi retry hanya memakan waktu. Retry error sementara dengan backoff, seperti dijelaskan di penanganan error dan backoff.
- Menjalankan banyak browser sekaligus? Batasi jumlah solve bersamaan agar satu batch yang lambat tidak menghambat sisa run.
- Tutup browser di blok
finally. Pengujian yang crash dan meninggalkan Chromium tetap berjalan akan memperlambat setiap solve berikutnya di mesin yang sama.
Menguji alur Anda sendiri
Jalankan contoh terhadap form milik Anda sendiri sebelum Anda mengarahkannya ke hal yang lebih besar. Periksa tiga hal: token diterima, form terkirim, dan halaman berikutnya muncul. Ketika alurnya berfungsi dari awal hingga akhir, jaga CI tetap hijau dengan satu solve sungguhan per run.
Coba gratis
Buat akun dan mulai dengan kredit uji coba gratis, tanpa kartu. Itu cukup untuk menyiapkan dan memeriksa seluruh alur. Untuk biaya solve dalam volume besar, lihat harga terkini.
Men-debug token yang ditolak
Ketika situs menolak token, reproduksi alurnya dengan satu request dan satu pemuatan halaman sebelum Anda mengubah hal lain. Periksa hal-hal ini secara berurutan:
- Sitekey yang Anda kirim cocok dengan widget pada halaman yang Anda muat.
site_urladalah halaman tempat widget berada, bukan target pengalihan.- Token masuk ke field yang dibaca halaman, atau callback sudah dipanggil.
- Pengiriman terjadi dalam waktu sekitar dua menit setelah solve.
Simpan HTML halaman pada saat kegagalan dengan await page.content(). Membandingkan HTML itu dengan run yang berhasil biasanya langsung menunjukkan perbedaannya: sitekey yang berbeda, field yang hilang, atau widget yang dirender dalam mode lain.