Hướng Dẫn API

Giải BLS CAPTCHA bằng Node.js và CaptchaAI

BLS CAPTCHA là lưới ảnh 3×3 kèm mã lệnh bằng số cho biết phải chọn ô nào — và bạn giải nó từ Node.js bằng bốn bước: đọc mã lệnh cùng 9 ảnh ô, encode sang base64, gửi task tới in.php của CaptchaAI, rồi polling res.php để lấy danh sách ô cần click. Bài này dành cho dev đang viết script Puppeteer hoặc Playwright, không phải bài tổng quan lý thuyết.

Điểm khiến BLS khác hẳn reCAPTCHA hay Turnstile: kết quả trả về không phải token, mà là mảng chỉ số ô.

Loại CAPTCHA API trả về Việc bạn phải làm sau đó
reCAPTCHA v2 token g-recaptcha-response đặt token vào form rồi submit
Cloudflare Turnstile token cf-turnstile-response đặt token vào form rồi submit
BLS CAPTCHA mảng chỉ số ô, ví dụ [1, 4, 7, 8] click từng ô trong trình duyệt rồi submit

Nói cách khác, script BLS luôn cần một trình duyệt điều khiển được — không có đường tắt kiểu gọi API rồi POST thẳng form.


Bạn cần chuẩn bị gì

Mục Giá trị
Khóa API CaptchaAI Từ captchaai.com
Node.js 14+
Thư viện axios (npm install axios)

BLS thuộc nhóm CAPTCHA dạng ảnh/lưới được CaptchaAI hỗ trợ chính thức, cùng reCAPTCHA v2/v3, Cloudflare Turnstile, Cloudflare Challenge và GeeTest v3.

CaptchaAI tính tiền theo thread (luồng giải đồng thời), không theo từng lần giải:

  • BASIC ($15/tháng, 5 thread) — đủ cho script chạy tuần tự.
  • STANDARD ($30/tháng, 15 thread) — khi chạy vài worker song song.
  • ADVANCE ($90/tháng, 50 thread) — cho pipeline QA quy mô lớn.

Cấu trúc lưới BLS: đọc trước khi code

Lưới 3×3 được đánh số từ trái sang phải, từ trên xuống dưới:

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

Mã lệnh dạng số (ví dụ "664") cho biết cần chọn nội dung nào. CaptchaAI trả về chỉ mục các ô khớp. Chỉ số bắt đầu từ 1, nên khi map sang mảng DOM bạn phải trừ đi 1 — đây là lỗi off-by-one phổ biến nhất trong script BLS.


Bước 1: lấy mã lệnh và 9 ảnh ô

Mở trang bằng Puppeteer, đọc text của phần tử chứa mã lệnh, rồi thu thập src của 9 ảnh. Ảnh có thể sẵn là data URI hoặc URL thường — trường hợp sau cần tải về và encode base64:

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}`);
  }
}

Lưu ý: nếu ảnh ô chỉ phục vụ sau khi đăng nhập, axios.get đứng riêng sẽ nhận 403 vì thiếu cookie phiên. Khi đó hãy đọc ảnh trong context trang bằng page.evaluate và canvas.


Bước 2: gửi task tới in.php

Cả 9 ảnh đi trong cùng một request POST, kèm method: 'bls' và mã lệnh ở instructions. Ảnh đánh số image_base64_1 đến image_base64_9:

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}`);

Nếu status khác 1, giá trị request chính là mã lỗi — đọc nó thay vì retry mù. Khi thành công bạn nhận về ID task.


Bước 3: polling res.php để lấy kết quả

Polling là chủ động hỏi kết quả định kỳ. Chờ 5 giây rồi gọi res.php mỗi 5 giây, tối đa 30 vòng:

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);
}

Theo đo đạc nội bộ, BLS giải trong <1 giây ở tầng xử lý, nên vòng lặp hiếm khi chạy quá vài lượt; 30 vòng chỉ là lưới an toàn khi mạng chậm. Kết quả trả về là chuỗi JSON, phải JSON.parse trước khi dùng.


Bước 4: click đúng ô rồi submit form

Lấy lại danh sách phần tử ảnh, click từng ô theo chỉ số (nhớ - 1), rồi 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();

Sản lượng dự kiến:

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

Nếu form vẫn báo sai, chụp screenshot ngay trước lúc submit: phần lớn trường hợp là lưới đã được làm mới trong lúc bạn gọi API, khiến ảnh cũ không còn khớp DOM.


Ví dụ: script đặt lịch hẹn của một team ở TP.HCM

Tình huống quen thuộc với dev Việt Nam: script hỗ trợ chính hồ sơ của bạn trên cổng đặt lịch hẹn có BLS CAPTCHA. Luồng chạy:

  1. Đăng nhập bằng tài khoản của bạn, giữ phiên trong một browserContext duy nhất.
  2. Vào trang chọn khung giờ, chờ lưới render xong (page.waitForSelector('.bls-grid img')).
  3. Chạy Bước 1–4 ở trên, ghi log ID task và mảng ô đã click.
  4. Nếu form từ chối, giãn thời gian thử lại (backoff) 30–60 giây rồi lấy lưới mới.

Hai nguyên tắc nên giữ: chỉ thao tác trên hồ sơ bạn có quyền xử lý; và nếu lưu ảnh ô hay dữ liệu cá nhân trong log để debug thì tối giản dữ liệu và đặt thời hạn xóa — Nghị định 13/2023/NĐ-CP về bảo vệ dữ liệu cá nhân khiến việc giữ log tùy tiện thành rủi ro không đáng có (ghi chú vận hành, không phải tư vấn pháp lý).

Đội QA tại các công ty outsourcing ở Hà Nội và TP.HCM dùng đúng khung này cho staging của khách hàng, chỉ khác URL trỏ về staging.example.com/qa-form.


Bảng lỗi và cách xử lý

Lỗi Nguyên nhân Cách xử lý
ERROR_BAD_PARAMETERS Thiếu ảnh hoặc thiếu mã lệnh Gửi đủ 9 ảnh và tham số instructions
CAPCHA_NOT_READY Task vẫn đang xử lý Tiếp tục polling mỗi 5 giây
ERROR_ZERO_BALANCE Tài khoản hết số dư Nạp tiền vào tài khoản CaptchaAI

Ngoài ba mã trên, hai lỗi hay gặp nhất lại không đến từ API:

  • selectedCells rỗng vì JSON.parse chạy trên một chuỗi lỗi.
  • Click trượt vì lưới đã re-render giữa chừng.

Log cả pollData.request thô lẫn số phần tử .bls-grid img lúc click sẽ khoanh vùng được cả hai trong một lần chạy.


Câu hỏi thường gặp

Kết quả BLS có phải token để dán vào form không?

Không. API trả về mảng chỉ số ô (ví dụ [1, 4, 7, 8]), bạn phải tự click các ô đó rồi submit. Khác với reCAPTCHA v2, nơi chỉ cần đặt g-recaptcha-response vào form.

Chạy 5 phiên song song thì cần gói nào?

Mỗi phiên đang chờ kết quả chiếm một thread. BASIC ($15/tháng, 5 thread) đủ cho 5 phiên đồng thời; nhiều worker hơn thì lên STANDARD ($30/tháng, 15 thread). Số lần giải không bị tính phí thêm.

Vì sao ảnh ô tải về bị lỗi 403?

axios gọi ngoài trình duyệt nên không mang theo cookie phiên. Đọc ảnh trong context trang bằng page.evaluate, hoặc chuyển cookie từ Puppeteer sang axios.

Dùng Playwright thay Puppeteer được không?

Được. Phần gọi API giữ nguyên — chỉ đổi lệnh điều khiển trình duyệt (page.$$eval sang page.locator(...).all()). Code Bước 2 và Bước 3 không cần sửa.

CaptchaAI có giải lưới 4×4 không?

BLS luôn là lưới 3×3 (9 ô). Với lưới 4×4 bạn dùng phương thức Grid Image, cũng thuộc nhóm CAPTCHA ảnh được hỗ trợ chính thức.


Đọc thêm


Lấy API key và giải ô BLS đầu tiên với CaptchaAI →

Os comentários estão desativados para este artigo.