Scarnox · Blog

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

  1. Baca sitekey dari halaman.
  2. Minta token ke Scarnox dengan satu POST request yang menunggu.
  3. 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

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:

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.

Langkah selanjutnya