Cara Memecahkan Cloudflare Turnstile di Node.js dan TypeScript

solve cloudflare turnstile in node.js - How to Solve Cloudflare Turnstile in Node.js and TypeScript

Cloudflare Turnstile muncul dalam dua bentuk dan keduanya memerlukan kode yang berbeda. Widget di dalam formulir adalah panggilan dua argumen. Tantangan interstisial satu halaman penuh memerlukan dua nilai tambahan yang diambil dari halaman, dan tokennya hanya akan diterima jika Anda mengirimkan kembali user agent yang digunakan pemecah. Persyaratan terakhir itulah yang menghasilkan token yang terlihat sempurna tetapi selalu gagal.

Cara membedakannya

WidgetHalaman challenge
TampilanCheckbox di dalam formulir yang dapat digunakanInterstisial satu halaman penuh, halaman terblokir
Membutuhkan cData dan chlPageDataTidakYa
Membutuhkan user agent yang dikembalikanTidakYa

Kami demo Turnstile langsung menjalankan varian widget, yang menjadi referensi berguna saat Anda mencoba menentukan varian mana yang sedang Anda hadapi.

Penyiapan

npm install capskip
const { CapSkip } = require('capskip');

const solver = new CapSkip({
  host: '127.0.0.1',
  port: 8080,
  recaptchaTimeout: 300,   // seconds, also covers Turnstile
});

CapSkip memecahkan secara lokal, jadi aplikasi desktop harus berjalan sebelum panggilan apa pun berhasil.

Mode widget

const result = await solver.turnstile(
  '0x4AAAAAAA...',                  // the data-sitekey attribute
  'https://example.com/login',
);

console.log(result.code);           // cf-turnstile-response token

Letakkan result.code ke dalam cf-turnstile-response dan kirim. Tidak ada lagi yang diperlukan.

Halaman challenge membutuhkan dua nilai tambahan

Interstitial membawa state per permintaan yang mengikat token tersebut. Dua bagian darinya harus ikut dikirim bersama pemecahan:

  • cData, diteruskan sebagai data
  • chlPageData, diteruskan sebagai pagedata

Keduanya berada di halaman tantangan itu sendiri, bukan di atribut formulir, sehingga halamannya harus diambil sebelum dapat dipecahkan. Pada interstisial Cloudflare standar, keduanya berada pada objek opsi tantangan milik halaman itu sendiri, di samping sitekey. Keduanya sekali pakai dan terikat pada pemuatan halaman tersebut, jadi ambil dan pecahkan sekaligus alih-alih menyimpannya di cache.

const result = await solver.turnstile(sitekey, pageUrl, {
  data: cData,             // the cData value
  pagedata: chlPageData,   // the chlPageData value
  action: 'managed',       // optional, when the page declares one
});

console.log(result.code);
console.log(result.userAgent);   // required for the next step

User agent bukan opsional

Turnstile mengikat token ke fingerprint browser yang menghasilkannya, dan user agent adalah bagian dari fingerprint itu. CapSkip mengembalikan nilai yang dipakainya di result.userAgent. Kirim token dengan user agent bawaan fetch Node dan Cloudflare akan menolak token yang sebenarnya sepenuhnya valid.

userAgent hanya terisi untuk Turnstile. Nilainya undefined untuk setiap tipe CAPTCHA lain, itulah tepatnya mengapa hal ini menjebak orang yang memakai ulang helper reCAPTCHA yang sudah bekerja.

const response = await fetch(pageUrl, {
  method: 'POST',
  headers: {
    // Send back the exact user agent the solve was performed with.
    'User-Agent': result.userAgent,
    'Content-Type': 'application/x-www-form-urlencoded',
  },
  body: new URLSearchParams({
    'cf-turnstile-response': result.code,
  }),
});

Jika sebuah token ditolak dan cData-nya masih baru, ini hampir selalu alasannya.

TypeScript

import { CapSkip, SolveResult } from 'capskip';

const solver = new CapSkip({ host: '127.0.0.1', port: 8080 });
const result: SolveResult = await solver.turnstile(sitekey, pageUrl);

// userAgent is optional on the type, because only Turnstile populates it.
if (result.userAgent) {
  // safe to forward
}

Definisi disertakan bersama paket, sehingga tidak ada @types install. Anotasi tipe opsional pada userAgent adalah dorongan yang berguna: kompiler tidak akan membiarkan Anda lupa bahwa jenis CAPTCHA lain membiarkannya kosong.

Proxy dan konkurensi

// Solve through the same egress you will submit from.
await solver.turnstile(sitekey, pageUrl, {
  data: cData,
  pagedata: chlPageData,
  proxy: { type: 'HTTPS', uri: 'user:[email protected]:3128' },
});

// Several at once.
const results = await Promise.all(targets.map((t) =>
  solver.turnstile(t.sitekey, t.url)));

Proxy berfungsi untuk Turnstile, reCAPTCHA, dan GeeTest, tetapi tidak untuk CAPTCHA gambar, yang tidak pernah menyentuh situs target. Untuk halaman tantangan, setiap pemecahan memerlukan cData miliknya sendiri yang baru diambil, jadi ambillah di dalam fungsi yang dipetakan alih-alih dalam satu batch di awal.

Pertanyaan yang sering diajukan

Apakah widget pernah membutuhkan cData?

Tidak, dan mengirim nilai kosong akan membuat pemecahan gagal alih-alih membantu. Hanya tantangan interstitial satu halaman penuh yang menggunakannya.

Token terlihat baik-baik saja tetapi situs menolaknya.

Hampir selalu user agent. Kirim menggunakan result.userAgent alih-alih apa pun yang dikirim client HTTP Anda secara bawaan. Penyebab paling mungkin kedua adalah cData yang basi, yang terikat pada satu kali muat halaman.

Bisakah saya menggunakan ini dengan Puppeteer?

Ya, dan keduanya cocok dipadukan: baca cData dari halaman yang sudah dimuat dengan page.evaluate, pecahkan dengan SDK ini, lalu setel user agent yang sama pada halaman sebelum melanjutkan. Lihat pemecah CAPTCHA Node.js halaman membahas sisi otomatisasi.

Ringkasan

Widget memerlukan sitekey dan URL. Halaman challenge membutuhkan data dan pagedata dibaca segar dari halaman, dan token harus dikirimkan bersama result.userAgent. Selebihnya adalah penanganan Promise biasa.

Bahasa lain ada di Pemecah Cloudflare Turnstile halaman, detail parameter di dokumentasi API, dan cakupan Node yang lebih luas ada di halaman pemecah CAPTCHA Node.js halaman. CapSkip adalah pemecah captcha tanpa batas yang berjalan di perangkat keras Anda sendiri.