API Tutorials

Solve BLS CAPTCHA dengan Node.js dan CaptchaAI

Jawaban singkatnya: BLS CAPTCHA diselesaikan dengan mengirim kesembilan gambar grid dalam bentuk base64 plus kode instruksinya ke method bls milik CaptchaAI, lalu mengklik indeks sel yang dikembalikan API. Tidak ada sitekey, tidak ada token yang dimasukkan ke hidden field — hasilnya berupa daftar nomor sel, dan browser automation Anda yang mengeksekusi klik.

Perbedaan itulah yang biasanya membuat skrip pertama gagal. Developer yang sudah terbiasa dengan reCAPTCHA v2 refleks mencari g-recaptcha-response; di BLS pola tersebut sama sekali tidak berlaku. Artikel ini membedah alurnya dari Node.js dengan axios dan Puppeteer, mulai dari ekstraksi grid sampai submit form, lengkap dengan kesalahan yang paling sering muncul di produksi.


Pastikan dulu: BLS atau tipe lain?

Sebelum menulis satu baris kode, pastikan form yang Anda hadapi memang BLS. Tiga pertanyaan ini cukup:

  1. Apakah tantangannya berupa grid gambar 3×3, bukan checkbox atau widget slider?
  2. Apakah ada kode instruksi numerik (misalnya "664") di dekat grid?
  3. Apakah HTML halaman tidak memuat atribut sitekey?

Tiga jawaban "ya" berarti Anda berada di alur yang tepat. Kalau ada satu saja "tidak", baca dulu bagian perbandingan tipe di bagian akhir artikel — memakai method bls untuk widget berbasis sitekey hanya menghasilkan ERROR_BAD_PARAMETERS berulang kali.


Yang perlu disiapkan sebelum mulai

  • API key CaptchaAI — dari captchaai.com, simpan di environment variable.
  • Node.js 14+ — versi LTS mana pun sudah cukup.
  • axios — pasang dengan npm install axios.
  • Puppeteer atau Playwright — untuk mengambil gambar grid dan mengeksekusi klik.

Satu paket berlangganan sudah cukup untuk mulai: BASIC ($15/bulan, 5 thread) memberi lima solve yang berjalan bersamaan, dengan jumlah solve tanpa batas. Penagihan CaptchaAI berbasis thread, bukan per solve — untuk freelancer otomatisasi yang menagih klien dengan harga tetap per bulan, biaya yang tidak ikut naik seiring volume jauh lebih mudah dimasukkan ke proposal. Kalau antrean form Anda ramai, naik ke STANDARD ($30/bulan, 15 thread) atau ADVANCE ($90/bulan, 50 thread). Harga selalu dalam USD.


Anatomi tantangan BLS: grid 3×3 dan kode instruksi

Sel grid dinomori dari kiri ke kanan, atas ke bawah:

1 | 2 | 3
---------
4 | 5 | 6
---------
7 | 8 | 9

Kode instruksi numerik (misalnya "664") menentukan gambar mana yang harus dipilih. CaptchaAI membaca kode tersebut bersama sembilan gambar, lalu mengembalikan indeks sel yang cocok — biasanya lebih dari satu.

Konsekuensinya untuk kode Anda: urutan gambar adalah kontrak. Parameter image_base64_1 sampai image_base64_9 harus mengikuti urutan tampil di halaman. Kalau Anda mengumpulkan URL gambar lewat request paralel lalu menyusunnya berdasarkan urutan selesai, indeks yang kembali akan menunjuk sel yang salah dan submit ditolak tanpa pesan error yang jelas. Kumpulkan secara berurutan, seperti pada langkah berikut.


Langkah 1: Ambil gambar grid dan kode instruksi

const axios = require('axios');
const puppeteer = require('puppeteer');

const browser = await puppeteer.launch();
const page = await browser.newPage();
await page.goto('https://example.com/bls-form');

// Get instruction code
const instruction = await page.$eval('.bls-instruction', (el) => el.textContent.trim());

// Get all 9 cell image URLs and convert to base64
const cellImages = await page.$$eval('.bls-grid img', (imgs) =>
  imgs.map((img) => img.src)
);

const images = [];
for (const src of cellImages) {
  if (src.startsWith('data:')) {
    images.push(src);
  } else {
    const { data } = await axios.get(src, { responseType: 'arraybuffer' });
    const b64 = Buffer.from(data).toString('base64');
    images.push(`data:image/png;base64,${b64}`);
  }
}

Perhatikan dua hal. Pertama, sebagian portal menyajikan gambar sebagai data: URI langsung di DOM, sebagian lagi sebagai URL biasa yang harus diambil lebih dulu — kode di atas menangani keduanya. Kedua, loop for...of sengaja tidak diganti Promise.all: urutannya harus terjaga.


Langkah 2: Kirim task ke method bls

const API_KEY = 'YOUR_API_KEY';
const sleep = (ms) => new Promise((r) => setTimeout(r, ms));

const params = new URLSearchParams({
  key: API_KEY,
  method: 'bls',
  instructions: instruction,
  json: '1',
});

// Add all 9 images
images.forEach((img, i) => {
  params.append(`image_base64_${i + 1}`, img);
});

const { data: submitData } = await axios.post(
  'https://ocr.captchaai.com/in.php',
  params.toString()
);

if (submitData.status !== 1) throw new Error(submitData.request);
const taskId = submitData.request;
console.log(`Task submitted: ${taskId}`);

Semua gambar dan instructions masuk dalam satu POST ke in.php. Respons JSON dengan status: 1 berarti task diterima, dan request berisi task ID yang Anda simpan untuk langkah polling. Simpan API key di environment variable, jangan hardcode — placeholder YOUR_API_KEY di sini hanya untuk contoh.


Langkah 3: Polling hasil dari res.php

await sleep(5000);

let selectedCells;
for (let i = 0; i < 30; i++) {
  const { data: pollData } = await axios.get('https://ocr.captchaai.com/res.php', {
    params: { key: API_KEY, action: 'get', id: taskId, json: 1 },
  });

  if (pollData.status === 1) {
    selectedCells = JSON.parse(pollData.request);
    console.log('Selected cells:', selectedCells);
    break;
  }
  if (pollData.request !== 'CAPCHA_NOT_READY') {
    throw new Error(pollData.request);
  }
  await sleep(5000);
}

Pola empat langkahnya konsisten dengan tipe CAPTCHA lain di CaptchaAI: kirim → simpan task ID → polling → pakai hasil. Jeda awal 5 detik menghindari CAPCHA_NOT_READY yang pasti muncul kalau Anda menembak res.php seketika. Untuk workload yang dideploy di AWS ap-southeast-1 (Singapura) atau ap-southeast-3 (Jakarta), latensi jaringan hanya menambah beberapa ratus milidetik — batas 30 iterasi masih menyisakan sekitar 2,5 menit sebelum menyerah, cukup lapang.


Langkah 4: Klik sel yang benar lalu submit

// Click each identified cell
const gridCells = await page.$$('.bls-grid img');
for (const cellNum of selectedCells) {
  await gridCells[cellNum - 1].click();
}

// Submit the form
await page.click('.bls-submit');
console.log(`Solved: clicked cells ${JSON.stringify(selectedCells)}`);
await browser.close();

Hasil yang diharapkan di konsol:

Selected cells: [1, 4, 7, 8]
Solved: clicked cells [1,4,7,8]

Konversi cellNum - 1 itu wajib: CaptchaAI menomori sel mulai dari 1, sedangkan array DOM mulai dari 0. Kesalahan off-by-one di sini adalah penyebab paling umum "hasil solve benar tapi form tetap ditolak".


Kode error yang sering muncul

Tiga kode ini menutupi hampir semua kegagalan yang muncul di produksi:

Kode Penyebab Yang harus dilakukan
ERROR_BAD_PARAMETERS Gambar atau kode instruksi tidak lengkap Kirim kesembilan gambar plus instructions dalam satu request
CAPCHA_NOT_READY Task masih diproses Lanjutkan polling setiap 5 detik, jangan anggap ini kegagalan
ERROR_ZERO_BALANCE Saldo akun habis Isi ulang akun CaptchaAI Anda

Perlakukan ketiganya secara berbeda di kode Anda:

  • CAPCHA_NOT_READY bukan error — jangan masukkan ke penghitung kegagalan.
  • ERROR_BAD_PARAMETERS adalah bug di sisi Anda; mengulang request yang sama tidak akan menolong.
  • ERROR_ZERO_BALANCE sebaiknya memicu alert, bukan retry.

Di luar tabel ini, periksa juga kualitas ekstraksi gambar. Kalau sebuah sel ternyata kosong atau ter-render sebagai placeholder karena halaman belum selesai memuat, akurasi turun tanpa memunculkan error apa pun. Tambahkan await page.waitForSelector('.bls-grid img') sebelum ekstraksi pada koneksi yang lambat — kondisi jaringan mobile-first di Indonesia membuat langkah ini makin relevan, bukan makin sepele.


Kapan BLS, kapan tipe lain

BLS adalah tipe grid dengan instruksi numerik. Kalau target Anda sebenarnya memakai widget berbasis sitekey, alurnya berbeda total dan hasilnya berupa token string, bukan daftar sel:

  • reCAPTCHA v2 mengembalikan token g-recaptcha-response yang Anda tulis ke hidden field sebelum submit.
  • Cloudflare Turnstile memakai pola serupa dengan token cf-turnstile-response.
  • GeeTest v3 mengembalikan tiga nilai hasil untuk widget slider-nya.

Perlu dicatat, CaptchaAI belum mendukung hCaptcha maupun FunCaptcha (Arkose Labs), dan GeeTest v4 masih berstatus segera hadir. Kalau form yang Anda otomatisasi memakai salah satu tipe tersebut, alur di artikel ini tidak berlaku.


Checklist sebelum menjalankan ke produksi

  1. API key dibaca dari environment variable, bukan ditulis di file sumber.
  2. Ekstraksi gambar berjalan berurutan dan menunggu .bls-grid img selesai dimuat.
  3. Konversi indeks cellNum - 1 sudah diterapkan di loop klik.
  4. Polling berhenti setelah batas iterasi, lalu task dikirim ulang, bukan menunggu selamanya.
  5. Jumlah proses paralel tidak melebihi jumlah thread paket Anda.

Pertanyaan umum

Kenapa API mengembalikan array, bukan token seperti reCAPTCHA?

Karena BLS bukan widget berbasis token. Yang dinilai adalah pilihan sel, jadi CaptchaAI mengembalikan indeks sel ([1, 4, 7, 8]) dan skrip Anda yang menerjemahkannya menjadi klik nyata di browser.

Apakah urutan pengiriman kesembilan gambar berpengaruh?

Sangat berpengaruh. Indeks yang dikembalikan mengacu pada urutan yang Anda kirim. Kirim image_base64_1 sampai image_base64_9 persis sesuai urutan tampil di grid, dan hindari pengambilan paralel yang mengacak urutan.

Berapa lama waktu penyelesaian satu BLS CAPTCHA?

Biasanya 5–15 detik, sehingga interval polling 5 detik sudah pas. Kalau sebuah task melewati sekitar 90 detik, perlakukan sebagai gagal lalu kirim ulang, jangan menunggu tanpa batas.

Bisakah saya memakai Playwright, bukan Puppeteer?

Bisa. Interaksi HTTP ke in.php dan res.php identik; yang berubah hanya pemanggilan browser automation-nya, misalnya page.$$eval diganti padanannya di Playwright.

Berapa thread yang saya butuhkan untuk memproses ratusan form?

Hitung dari waktu penyelesaian: satu thread menuntaskan sekitar 4–6 BLS CAPTCHA per menit. Lima thread pada paket BASIC ($15/bulan) berarti sekitar 20–30 solve per menit — cukup untuk sebagian besar pekerjaan batch. Naikkan paket ketika antrean Anda benar-benar mulai menumpuk, bukan sebelum itu.


Bacaan lanjutan


Ambil API key CaptchaAI dan jalankan solve BLS pertama Anda dari Node.js →

Komentar dinonaktifkan untuk artikel ini.