Cara Memecahkan reCAPTCHA di Deno: Izin dan Timeout

solve recaptcha in deno - How to Solve reCAPTCHA in Deno: Permissions and Timeouts

Untuk memecahkan reCAPTCHA di Deno, impor SDK Node.js CapSkip melalui npm specifier, lalu baca sendiri alamat pemecah CAPTCHA dari variabel lingkungan. Setelah itu jalankan skrip dengan flag izin yang hanya menyebut CapSkip dan situs Anda. CapSkip berjalan di PC Windows Anda sendiri, sehingga tidak ada tagihan per pemecahan. Kodenya pendek. Bagian yang sulit adalah model izin milik Deno. SDK melaporkan pemanggilan yang diblokir sebagai error jaringan. CapSkip yang diam saja membuat skrip menggantung tanpa error dan tanpa berhenti. Lalu cara yang biasa dipakai untuk menambahkan timeout membuat proses tetap hidup selama seluruh batas waktu. Panduan ini membahas masing-masingnya.

Apa yang Anda butuhkan

  • CapSkip yang berjalan di PC Windows, dengan pemecah reCAPTCHA diaktifkan. Lihat panduan penyiapan yang menjelaskan cara menjalankan CapSkip untuk pertama kali.
  • Deno 2. Semua yang ada di bawah dijalankan di Windows 11 dengan Deno 2.9.6, lalu diulang di 2.9.7, dengan capskip 1.3.0 dari npm.
  • Prompt PowerShell. Perintahnya memakai sintaks PowerShell.
  • Halaman dengan kotak centang reCAPTCHA v2 di dalam sebuah form. Contohnya login ke form bergaya Django yang membawa token CSRF. Ubah nama field agar sesuai dengan situs Anda.
  • 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.

Pengukuran di bawah berasal dari mock CapSkip (pengganti CapSkip yang dibuat khusus untuk pengujian) dan halaman login mock di PC yang sama, dipakai bersama Deno dan SDK yang asli. Error izin, jadwal polling, dan perilaku menggantung adalah bagian dari Deno dan SDK, jadi juga berlaku di situs Anda sendiri. Waktu pemecahan serta aturan menerima dan menolak pada halaman login adalah milik mock itu sendiri.

Langkah 1: instal Deno dan buat proyek

Instal Deno dengan penginstal resminya, atau dengan winget. Lihat halaman instalasi Deno untuk pilihan lain, seperti Scoop dan Chocolatey.

# PowerShell: the official installer (or: winget install DenoLand.Deno)
irm https://deno.land/install.ps1 | iex
deno --version

Lalu buat folder proyek dan letakkan deno.json di dalamnya sebelum Anda menjalankan apa pun. Import map mengunci versi SDK dan memungkinkan skrip menulis "capskip" alih-alih npm specifier yang panjang.

{
  "imports": {
    "capskip": "npm:[email protected]"
  }
}

Jangan jalankan deno add sebelum file itu ada. Jika sebuah package.json berada di folder di atas proyek Anda, yang umum terjadi di folder profil pengguna, Deno memperlakukan proyek itu sebagai proyek Node. Import npm:[email protected] lalu gagal dengan Could not find "capskip" in a node_modules folder. Import tanpa versi diam-diam memuat capskip mana pun yang terinstal di atas sana. Di PC uji, itu adalah versi lama 1.0.2. Menjalankan deno add tanpa deno.json bahkan menulis ulang package.json induk itu. deno.json di folder Anda sendiri membuat Deno menjadikan folder itu sebagai root proyek.

Langkah 2: impor SDK dan baca pengaturannya

Simpan kode dari Langkah 2 sampai 5 dalam satu file bernama solve.js, sesuai urutan yang ditampilkan. Seluruh file itu diulang menjelang akhir panduan ini. Deno menjalankannya sebagai modul ES, sehingga pemanggilan require dari README SDK gagal di sini dengan require is not defined. Gunakan named import. Default import juga gagal, karena ia memberi Anda seluruh objek exports: new CapSkip() melempar CapSkip is not a constructor.

import { CapSkip } from "capskip";

// The SDK never reads the environment, so read it here and pass it in.
const host = Deno.env.get("CAPSKIP_HOST") ?? "127.0.0.1";
const port = Number(Deno.env.get("CAPSKIP_PORT") ?? 8080);
const apiKey = Deno.env.get("CAPSKIP_API_KEY") ?? "capskip";
const solver = new CapSkip({ host, port, apiKey });

// The login page to solve, passed on the command line.
const pageUrl = Deno.args[0] ?? "https://example.com/login";

SDK tidak membaca variabel lingkungan dengan sendirinya, jadi skrip membacanya lalu meneruskannya ke constructor. Nilai default membuat file ini berjalan tanpa penyiapan. CAPSKIP_API_KEY hanya berpengaruh jika Anda mengaktifkan validasi API key di CapSkip.

Langkah 3: ambil halaman dan simpan cookie-nya

Fungsi fetch milik Deno tidak punya cookie jar, jadi skrip membuatnya sendiri. Skrip membaca setiap baris Set-Cookie dengan getSetCookie. Jika memanggil headers.get pada set-cookie, baris-baris itu justru digabung menjadi satu string. Tanggal Expires pada cookie mengandung koma, sehingga pemisahan naif berdasarkan koma memotong cookie di tempat yang salah.

// Deno's fetch keeps no cookies, so collect every Set-Cookie line.
// (headers.get("set-cookie") would glue them into one string.)
const jar = new Map();

/** @param {Response} response */
function keepCookies(response) {
  for (const line of response.headers.getSetCookie()) {
    const [pair] = line.split(";");
    const eq = pair.indexOf("=");
    jar.set(pair.slice(0, eq).trim(), pair.slice(eq + 1).trim());
  }
}
const cookies = () => Array.from(jar, ([k, v]) => `${k}=${v}`).join("; ");

Berikutnya skrip memuat halaman login lalu membaca sitekey dan token CSRF dari halaman itu. Sesuaikan kedua pola dengan markup halaman Anda.

const page = await fetch(pageUrl);
keepCookies(page);
const html = await page.text();

// Adjust these two patterns to your page's markup.
const sitekey = html.match(/data-sitekey="([^"]+)"/)?.[1];
const csrf = html.match(/name="csrfmiddlewaretoken" value="([^"]+)"/)?.[1];
if (!sitekey || !csrf) throw new Error("sitekey or CSRF token not found");

Langkah 4: minta token ke CapSkip

Satu pemanggilan menyelesaikan pekerjaannya. Pemanggilan itu mengirim tugas, melakukan polling untuk jawabannya, lalu mengembalikan token. SDK melakukan polling segera, lalu menunggu seperempat detik dan menggandakan waktu tunggu setiap kali, hingga 5 detik. Pemecahan yang diselesaikan CapSkip dalam satu detik kembali dalam sekitar 1.8 detik pada pengujian, sama seperti di Node.

// code is typed "string or object" (Capy shares the field), so
// String() keeps deno check quiet.
const { code } = await solver.recaptcha(sitekey, pageUrl);
const token = String(code);

Hasilnya memiliki field code, dan itulah token-nya. File tipe milik SDK mendeklarasikannya sebagai string atau objek, karena sebagian tipe CAPTCHA mengembalikan objek di field yang sama. String() mengubahnya menjadi string biasa. Bagian berikutnya menambahkan timeout pada pemanggilan ini.

Langkah 5: kirim form dan periksa hasilnya

Skrip mengirim token di field g-recaptcha-response bersama field form lainnya. Ada dua detail yang penting. Fungsi fetch milik Deno tidak mengirim Referer, dan situs yang ketat seperti Django melalui HTTPS menolak form post tanpa header itu, jadi skrip menyetelnya. Lalu pemanggilan fetch memakai redirect manual, sehingga respons 302 dikembalikan dan cookie sesi barunya bisa dibaca. Dengan pengaturan default yang mengikuti redirect, cookie pada 302 itu hilang dan login kembali ke form dengan status 200.

// fetch sends no Referer, and a strict site rejects the post without
// one. redirect "manual" keeps the 302 so we can read its new cookie.
const response = await fetch(pageUrl, {
  method: "POST",
  redirect: "manual",
  headers: { Cookie: cookies(), Referer: pageUrl },
  body: new URLSearchParams({
    csrfmiddlewaretoken: csrf,
    username: "YOUR_USERNAME",
    password: "YOUR_PASSWORD",
    "g-recaptcha-response": token,
  }),
});
keepCookies(response);

Login yang ditolak sering dijawab dengan 200 dan form yang sama lagi. Karena itu skrip menganggap apa pun selain 302 sebagai kegagalan, lalu mencari penanda yang hanya tampil di halaman setelah login. Ganti Welcome back dengan teks dari situs Anda sendiri. Skrip yang melaporkan berhasil untuk login yang ditolak lebih buruk daripada skrip yang gagal.

// A good login answers 302 and rotates the session cookie.
if (response.status !== 302) {
  const body = await response.text();
  throw new Error(`login rejected: ${response.status} ${body}`);
}
const next = new URL(response.headers.get("location") ?? "/", pageUrl);
const home = await fetch(next, { headers: { Cookie: cookies() } });

// Swap "Welcome back" for a marker your own site shows after login.
const ok = (await home.text()).includes("Welcome back");
console.log(ok ? "logged in" : "NOT logged in");
if (!ok) Deno.exit(2);

Langkah 6: jalankan dengan set izin sekecil mungkin

Deno menolak akses jaringan, variabel lingkungan, dan file sampai Anda mengizinkannya. Untuk memecahkan reCAPTCHA di Deno, skrip ini membutuhkan dua hal, dan perintah di bawah hanya memberikan izin untuk keduanya.

deno run `
  --allow-env=CAPSKIP_HOST,CAPSKIP_PORT,CAPSKIP_API_KEY `
  --allow-net=127.0.0.1:8080,example.com `
  solve.js https://example.com/login

Daftar env menyebut ketiga variabel CAPSKIP. Daftar net menyebut alamat dan port CapSkip, serta situsnya. Ganti example.com dan alamat halaman dengan situs Anda sendiri. Jika salah satu entri dihapus, eksekusi gagal, dan error menyebut apa yang kurang.

IzinApa yang diizinkannyaYang Anda lihat tanpa izin itu
env, tiga namaMembaca variabel CAPSKIPNotCapable: Requires env access to "CAPSKIP_HOST", diikuti saran untuk menjalankan ulang dengan flag env. Variabel yang tidak disetel juga ditolak, jadi nilai default tidak membantu.
net, host dan port CapSkipPemanggilan SDK ke CapSkipNetworkException dengan pesan Requires net access to "127.0.0.1:8080", diikuti saran yang sama untuk flag net.
net, situsnyaPemanggilan fetch Anda ke halaman dan ke formError NotCapable yang menyebut nama situsnya.

Beberapa aturan tentang daftar net. Host tanpa port mengizinkan semua port, jadi example.com mencakup 80 maupun 443. Entri dengan port hanya mengizinkan port itu. 127.0.0.1 dan 127.0.0.2 adalah host yang berbeda. Lalu redirect ke nama host lain mengharuskan host itu ada di daftar juga. Halaman yang dialihkan dari example.com ke www.example.com gagal pada permintaan kedua sampai Anda menambahkannya. Tidak ada yang lain yang diperlukan: tanpa izin read, run, sys, maupun import.

Di terminal, Deno bertanya alih-alih langsung gagal. Deno menampilkan prompt sekali untuk setiap variabel dan setiap host, dan menjawab tidak menghasilkan error yang sama. Dalam job terjadwal tidak ada terminal, sehingga Deno langsung gagal. Flag allow-all (-A) menghapus semua pemeriksaan ini, jadi simpan hanya untuk eksperimen cepat.

Anda bisa menaruh perintah yang sama di deno.json sebagai task, supaya mengetik lebih sedikit. Blok pertama di bawah adalah deno.json dengan import map dan task solve, dan blok kedua menyetel variabel lingkungan di PowerShell lalu menjalankannya. Deno menambahkan alamat halaman yang Anda berikan setelah nama task.

{
  "imports": {
    "capskip": "npm:[email protected]"
  },
  "tasks": {
    "solve": "deno run --allow-env=CAPSKIP_HOST,CAPSKIP_PORT,CAPSKIP_API_KEY --allow-net=127.0.0.1:8080,example.com solve.js"
  }
}
$env:CAPSKIP_HOST = "127.0.0.1"
$env:CAPSKIP_PORT = "8080"
deno task solve https://example.com/login

Gunakan alamat IP untuk CAPSKIP_HOST. Jika Anda menyetel nama seperti localhost, nama itu sendiri harus ada di daftar net, atau SDK gagal dengan getaddrinfo EPERM localhost. Mencantumkannya pun menjadi jebakan. Saat CapSkip tidak berjalan, localhost membuat Deno mencoba alamat IPv6 [::1], yang tidak ada di daftar. Error tersebut dilempar dari sebuah timer, bukan dari pemanggilan SDK, sehingga bukan NetworkException dan tidak bisa ditangkap oleh try dan catch.

Membedakan pemanggilan yang diblokir dari CapSkip yang tidak berjalan

Keduanya datang sebagai NetworkException, sehingga handler yang selalu berkata "is CapSkip running?" mengarahkan Anda ke arah yang salah. Bedanya ada pada pesan dan penyebabnya. Pemanggilan yang diblokir memiliki pesan yang diawali Requires net access, dan penyebabnya adalah error NotCapable milik Deno. Jika CAPSKIP_HOST berupa nama, pesannya adalah getaddrinfo EPERM dan penyebabnya memiliki kode EPERM sebagai gantinya. CapSkip yang tidak berjalan memiliki pesan yang diawali connect ECONNREFUSED. Selain itu, Deno di Windows butuh sekitar dua detik untuk gagal, dibandingkan beberapa milidetik di Node. Skrip yang tampak berhenti sejenak sebelum melaporkannya tidak sedang menggantung. Fungsi di bawah memeriksa kedua jenis pemblokiran. Skrip lengkap di bagian akhir memanggilnya di blok catch yang membungkus seluruh alur.

import { ApiException, NetworkException, TimeoutException } from "capskip";

// Deno's permission errors arrive wrapped in NetworkException. The
// cause is NotCapable for an IP host, and has the code EPERM for a
// host name. Tell them apart from a CapSkip that is not running.
/** @param {any} err */
function explain(err) {
  const cause = err?.cause;
  if (err instanceof NetworkException) {
    const denied = cause instanceof Deno.errors.NotCapable ||
      cause?.code === "EPERM";
    return denied
      ? `Deno blocked the call, add a flag: ${err.message}`
      : `CapSkip is not reachable: ${err.message || cause?.code}`;
  }
  if (err instanceof ApiException) return `CapSkip replied: ${err.message}`;
  if (err instanceof TimeoutException) return `Too slow: ${err.message}`;
  return String(err?.stack ?? err);
}

Cegah CapSkip yang diam membuat skrip menggantung

SDK tidak menetapkan timeout pada koneksinya. Jika CapSkip menerima sebuah pemanggilan lalu tidak pernah menjawab, skrip menunggu selamanya. Deno tidak mencetak apa pun dan tidak keluar. Pengaturan recaptchaTimeout milik SDK tidak membantu. Pengaturan itu hanya diperiksa di antara polling, sehingga tidak bisa terpicu saat pemanggilan pengiriman atau sebuah polling sedang menunggu jawaban. Node berperilaku sama. Tanpa wrapper apa pun, satu-satunya jalan keluar adalah Ctrl+C.

Batasi sendiri waktu pemanggilannya. Alat yang biasa dipakai adalah AbortSignal.timeout, dan di Deno alat itu keliru untuk kasus ini. Sinyal timeout dengan abort listener menjaga proses tetap hidup sampai timer terpicu. Batas waktu 30 detik di sekitar pemecahan yang memakan 1.8 detik membuat skrip baru keluar setelah 30 detik. Dengan setTimeout biasa yang Anda hapus saat pemanggilan selesai, proses langsung keluar begitu berhasil.

// The SDK sets no socket timeout, so a CapSkip that accepts the call
// and never answers would hang the script. Race it against a timer,
// and clear the timer so the process can exit on success.
/**
 * @param {Promise<any>} promise
 * @param {number} ms
 */
function withTimeout(promise, ms) {
  const { promise: limit, reject } = Promise.withResolvers();
  const timer = setTimeout(
    () => reject(new Error(`no answer in ${ms} ms`)),
    ms,
  );
  return Promise.race([promise, limit]).finally(() => clearTimeout(timer));
}

Lalu ganti blok Langkah 4 dengan blok ini. Blok ini membungkus pemanggilan pemecahan yang sama. Tempel explain dan withTimeout di mana saja di atas baris yang memakainya. SDK menyerah sendiri setelah 300 detik, sehingga batas waktu 330 detik hanya terpicu ketika CapSkip diam.

// The SDK gives up after 300 s by itself, so a 330 s budget only
// fires when CapSkip goes silent. code is typed "string or object"
// (Capy shares the field), so String() hands the form a plain string.
const solving = solver.recaptcha(sitekey, pageUrl);
const { code } = await withTimeout(solving, 330_000);
const token = String(code);

Ketika timer menang, koneksi yang tertunda masih terbuka, jadi blok catch di contoh lengkap diakhiri dengan Deno.exit. Tanpa itu, proses akan terus menunggu di socket. Dalam pengujian, CapSkip yang tidak pernah menjawab pengiriman tugas dan CapSkip yang tidak pernah menjawab polling hasil sama-sama berakhir dengan error setelah batas waktu habis. Exit code-nya 1.

Type-check pada skrip

Deno dapat memeriksa JavaScript terhadap tipe bawaan SDK, tetapi tidak melakukan apa pun untuk file .js biasa kecuali Anda memintanya. Perintah deno check pada file .js biasa tidak melaporkan apa pun, bahkan ketika kodenya memiliki error tipe. Menyalakan checkJs di deno.json membuat pemeriksaan itu benar-benar berjalan.

{
  "imports": {
    "capskip": "npm:[email protected]"
  },
  "compilerOptions": {
    "checkJs": true
  }
}
deno check solve.js

Dengan pemeriksaan menyala, opsi constructor yang salah eja seperti hots untuk host menjadi error. Opsi yang salah eja di dalam pemanggilan pemecahan tidak menjadi error, karena tipe opsinya menerima key apa pun, sehingga salah ketik di sana lolos pemeriksaan dan tidak berpengaruh apa pun. Anggap pemeriksaan ini sebagai bantuan, bukan jaminan.

Kompilasi menjadi satu file exe

Karena izin menjadi bagian dari perintah, deno compile dapat menanamkannya ke dalam file hasil kompilasi. Skrip yang memecahkan reCAPTCHA di Deno lalu didistribusikan sebagai satu solve.exe yang berjalan di PC tanpa Deno terinstal. Itu cocok untuk mesin Windows yang menjalankan CapSkip dan skrip secara bersamaan.

deno compile `
  --allow-env=CAPSKIP_HOST,CAPSKIP_PORT,CAPSKIP_API_KEY `
  --allow-net=127.0.0.1:8080,example.com `
  --output solve.exe solve.js
.\solve.exe https://example.com/login

Ada empat hal yang perlu diketahui. Kompilasi pertama mengunduh runtime sekitar 33 MB dari dl.deno.land, dan file exe-nya sekitar 80 MB. Variabel lingkungan tetap berfungsi, jadi CAPSKIP_PORT tetap dipakai. Izin ditetapkan saat kompilasi, dan file exe tidak punya flag untuk memperluasnya: jika Anda memberikan flag allow-all, flag itu menjadi argumen program yang pertama. Lalu di dalam file exe, pemanggilan yang ditolak akan meminta Anda menentukan izin itu saat kompilasi.

Sebuah peluncuran yang menyerupai peluncuran oleh Task Scheduler menjalankan file exe dan keluar dengan kode 0 dalam pengujian. Peluncuran itu memakai System32 sebagai folder kerja, tanpa konsol, dan dengan PATH tanpa Deno. Task terjadwal yang sungguhan tidak didaftarkan, jadi baca panduan memecahkan CAPTCHA di job Windows Task Scheduler untuk pengaturan batas waktu dan restart yang penting di sana.

Menjalankan CapSkip di mesin lain

Skrip dan pemecah CAPTCHA tidak harus berada di PC yang sama. Alihkan CapSkip ke mode Server di pengaturan koneksi, dan ia akan mendengarkan di alamat jaringan atau IP publik Anda. Lalu ubah dua hal: CAPSKIP_HOST dan daftar net. Jika Anda lupa memasukkan alamat yang baru ke daftar net, error menyebut alamat tersebut.

$env:CAPSKIP_HOST = "192.168.1.50"
$env:CAPSKIP_PORT = "8080"
$env:CAPSKIP_API_KEY = "YOUR_API_KEY"
deno run `
  --allow-env=CAPSKIP_HOST,CAPSKIP_PORT,CAPSKIP_API_KEY `
  --allow-net=192.168.1.50:8080,example.com `
  solve.js https://example.com/login

Gunakan IP publik statis jika rutenya melewati internet. Aktifkan validasi API key, dengan key yang sama di CAPSKIP_API_KEY seperti yang disetel blok di atas. CapSkip membuka port-nya untuk semua alamat saat mode Server dimulai. Untuk membatasi akses hanya pada mesin yang Anda harapkan, tambahkan aturan blokir Windows Firewall untuk alamat lainnya. Pemecah CAPTCHA tetap berupa mesin Windows milik Anda sendiri, dan pemecahannya tetap tanpa kuota.

Skrip lengkap

Berikut solve.js dalam satu bagian utuh, lengkap dengan wrapper timeout dan error handler. Simpan di samping deno.json dan jalankan dengan perintah dari Langkah 6.

import {
  ApiException,
  CapSkip,
  NetworkException,
  TimeoutException,
} from "capskip";

// The SDK never reads the environment, so read it here and pass it in.
const host = Deno.env.get("CAPSKIP_HOST") ?? "127.0.0.1";
const port = Number(Deno.env.get("CAPSKIP_PORT") ?? 8080);
const apiKey = Deno.env.get("CAPSKIP_API_KEY") ?? "capskip";
const solver = new CapSkip({ host, port, apiKey });

// The login page to solve, passed on the command line.
const pageUrl = Deno.args[0] ?? "https://example.com/login";

// Deno's fetch keeps no cookies, so collect every Set-Cookie line.
// (headers.get("set-cookie") would glue them into one string.)
const jar = new Map();

/** @param {Response} response */
function keepCookies(response) {
  for (const line of response.headers.getSetCookie()) {
    const [pair] = line.split(";");
    const eq = pair.indexOf("=");
    jar.set(pair.slice(0, eq).trim(), pair.slice(eq + 1).trim());
  }
}
const cookies = () => Array.from(jar, ([k, v]) => `${k}=${v}`).join("; ");

// Deno's permission errors arrive wrapped in NetworkException. The
// cause is NotCapable for an IP host, and has the code EPERM for a
// host name. Tell them apart from a CapSkip that is not running.
/** @param {any} err */
function explain(err) {
  const cause = err?.cause;
  if (err instanceof NetworkException) {
    const denied = cause instanceof Deno.errors.NotCapable ||
      cause?.code === "EPERM";
    return denied
      ? `Deno blocked the call, add a flag: ${err.message}`
      : `CapSkip is not reachable: ${err.message || cause?.code}`;
  }
  if (err instanceof ApiException) return `CapSkip replied: ${err.message}`;
  if (err instanceof TimeoutException) return `Too slow: ${err.message}`;
  return String(err?.stack ?? err);
}

// The SDK sets no socket timeout, so a CapSkip that accepts the call
// and never answers would hang the script. Race it against a timer,
// and clear the timer so the process can exit on success.
/**
 * @param {Promise<any>} promise
 * @param {number} ms
 */
function withTimeout(promise, ms) {
  const { promise: limit, reject } = Promise.withResolvers();
  const timer = setTimeout(
    () => reject(new Error(`no answer in ${ms} ms`)),
    ms,
  );
  return Promise.race([promise, limit]).finally(() => clearTimeout(timer));
}

try {
  const page = await fetch(pageUrl);
  keepCookies(page);
  const html = await page.text();

  // Adjust these two patterns to your page's markup.
  const sitekey = html.match(/data-sitekey="([^"]+)"/)?.[1];
  const csrf = html.match(/name="csrfmiddlewaretoken" value="([^"]+)"/)?.[1];
  if (!sitekey || !csrf) throw new Error("sitekey or CSRF token not found");

  // The SDK gives up after 300 s by itself, so a 330 s budget only
  // fires when CapSkip goes silent. code is typed "string or object"
  // (Capy shares the field), so String() hands the form a plain string.
  const solving = solver.recaptcha(sitekey, pageUrl);
  const { code } = await withTimeout(solving, 330_000);
  const token = String(code);

  // fetch sends no Referer, and a strict site rejects the post without
  // one. redirect "manual" keeps the 302 so we can read its new cookie.
  const response = await fetch(pageUrl, {
    method: "POST",
    redirect: "manual",
    headers: { Cookie: cookies(), Referer: pageUrl },
    body: new URLSearchParams({
      csrfmiddlewaretoken: csrf,
      username: "YOUR_USERNAME",
      password: "YOUR_PASSWORD",
      "g-recaptcha-response": token,
    }),
  });
  keepCookies(response);

  // A good login answers 302 and rotates the session cookie.
  if (response.status !== 302) {
    const body = await response.text();
    throw new Error(`login rejected: ${response.status} ${body}`);
  }
  const next = new URL(response.headers.get("location") ?? "/", pageUrl);
  const home = await fetch(next, { headers: { Cookie: cookies() } });

  // Swap "Welcome back" for a marker your own site shows after login.
  const ok = (await home.text()).includes("Welcome back");
  console.log(ok ? "logged in" : "NOT logged in");
  if (!ok) Deno.exit(2);
} catch (err) {
  console.error(explain(err));
  Deno.exit(1);
}

Kesalahan umum saat memecahkan reCAPTCHA di Deno

Tanpa blok try, Deno mencetak nama class lebih dulu, seperti pada kolom pertama. Skrip lengkap mencetak pesan yang sama setelah prefix-nya sendiri.

Apa yang Anda lihatPenyebabPerbaiki
Requires env access to "CAPSKIP_HOST"Izin env kekurangan satu namaCantumkan ketiga nama CAPSKIP
NetworkException: Requires net access to "127.0.0.1:8080"Host dan port CapSkip tidak ada di daftar netTambahkan keduanya, dan tambahkan situsnya juga
NetworkException: connect ECONNREFUSED, setelah sekitar 2 detikCapSkip tidak berjalan, atau port-nya salahJalankan CapSkip dan periksa port di pengaturan koneksi
NetworkException: getaddrinfo EPERM localhostNama host dipakai, tetapi hanya IP yang ada di daftar netGunakan 127.0.0.1 di CAPSKIP_HOST
ReferenceError: require is not definedPemanggilan CommonJS di dalam modul ESGunakan named import
TypeError: CapSkip is not a constructorDefault import memberikan seluruh objek exportsImport { CapSkip } berdasarkan nama
Could not find "capskip" in a node_modules folderpackage.json di atas proyek mengambil alih resolusi importTaruh deno.json di folder proyek
Tidak ada output, tidak keluarCapSkip menerima pemanggilan lalu tidak pernah menjawabBungkus pemanggilan dengan withTimeout dan panggil Deno.exit
ApiException: ERROR_CAPTCHA_UNSOLVABLECapSkip sudah mencoba dan gagalKirim tugas baru, lihat catatan tentang ERROR_CAPTCHA_UNSOLVABLE

FAQ

Bisakah saya tidak memakai flag dan langsung memakai allow-all?

Bisa berjalan, tetapi itu menghilangkan alasan menjalankan skrip di Deno. Skrip lalu memiliki akses jaringan, file, dan variabel lingkungan ke semuanya, termasuk paket yang diimpornya. Satu daftar berisi tiga nama dan satu daftar berisi dua host cukup pendek untuk tetap dipakai.

Apakah ini berfungsi di Deno Deploy atau runtime hosted lainnya?

Deno Deploy dan runtime hosted lainnya tidak diuji di sini. Server di pusat data milik pihak lain tidak bisa menjangkau 127.0.0.1 di PC Anda. Jadi jalankan CapSkip dalam mode Server di mesin Windows yang Anda kendalikan, dengan IP publik statis, lalu arahkan CAPSKIP_HOST ke sana. Platform itu juga harus mengizinkan koneksi keluar ke alamat dan port tersebut, jadi periksa aturan jaringannya. Lihat panduan memecahkan CAPTCHA di Netlify Functions untuk penyiapan mode Server yang sama dari fungsi yang di-host.

Mengapa memakai SDK dan bukan memanggil CapSkip dengan fetch?

CapSkip kompatibel dengan API 2captcha, jadi fetch ke in.php dan res.php bisa dipakai. Namun Anda harus menulis sendiri loop polling, back-off, dan pemetaan error. SDK sudah melakukan polling dengan jadwal yang dimulai dari seperempat detik, mengembalikan token, dan melempar ApiException, NetworkException, dan TimeoutException. Harganya ada dua detail: error izin datang dalam keadaan terbungkus, dan SDK tidak menetapkan timeout socket.

Apakah tipe CAPTCHA lain bekerja dengan cara yang sama di Deno?

Hanya reCAPTCHA v2 yang dijalankan di Deno untuk panduan ini. Tipe berbasis token, seperti Turnstile dan GeeTest, memanggil endpoint yang sama, sehingga kedua flag yang sama seharusnya berlaku, tetapi itu tidak diuji. CAPTCHA gambar yang diberikan sebagai path file juga membutuhkan izin read, dan yang diberikan sebagai URL membutuhkan situs itu ada di daftar net. Baca opsi untuk setiap tipe di halaman pemecah CAPTCHA Node.js sebelum menyalin pemanggilan.

Versi singkatnya

Untuk memecahkan reCAPTCHA di Deno, taruh deno.json berisi import SDK di folder Anda sendiri dan impor named export. Baca sendiri pengaturan CapSkip. Jalankan dengan daftar env dan daftar net yang berisi alamat CapSkip dan situs Anda, tidak lebih. Bedakan pemanggilan yang ditolak dari CapSkip yang tidak berjalan lewat penyebabnya. Batasi pemecahan dengan timer biasa, karena AbortSignal.timeout menahan proses tetap terbuka, sedangkan tanpa timer CapSkip yang diam membuat skrip menggantung selamanya.

Skrip yang Anda kompilasi sekali lalu dijadwalkan bisa menghasilkan ribuan pemecahan per bulan. Jika semuanya dijalankan melalui sebuah pemecah captcha tanpa batas di mesin Windows Anda sendiri, angka itu tidak pernah berubah menjadi tagihan.