API Tutorials

使用 Node.js 和 CaptchaAI 解决 BLS CAPTCHA

BLS 验证码是 3×3 九宫格加一串数字指令码,指令码决定该点哪几格。Node.js 里只有一条路径:九张格子图连同指令码交给识别接口,拿回单元格索引,再让浏览器按索引点击。下面拆成四步,用 CaptchaAIbls 方法,提交走 in.php,取结果走 res.php


动手前需要准备什么

项目 要求
CaptchaAI API Key 注册后在控制台获取
Node.js 14+
依赖库 axiospuppeteer

Puppeteer 首次安装要下载 Chromium,走 npm 镜像能省掉大半等待。

CaptchaAI 按线程计费而非按次:BASIC $15/月 5 线程,STANDARD $30/月 15 线程,ADVANCE $90/月 50 线程,套餐内识别次数不限,价格按美元计价。


九宫格加指令码:BLS 的判定逻辑

格子从左到右、从上到下编号:

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

页面同时给出一串数字指令(例如 “664”),决定哪几格是答案。脚本把指令码九张图一起发出去,接口返回索引数组,比如 [1, 4, 7, 8]

BLS 的识别结果是坐标而不是 token,没有隐藏字段可填,最后一步必须由浏览器真实点击完成。


步骤 1:抓取指令码与九张格子图

用 Puppeteer 打开表单页,读出指令码,收集九个 img 的地址。格子图可能内联,也可能是普通 URL,下面的循环对后者用 axios 拉回二进制转 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}`);
  }
}

如果 cellImages 长度不是 9,说明页面还没渲染完,goto 后补一句 waitForSelector 再取。


步骤 2:带指令码提交到 CaptchaAI

POSTin.phpmethod 固定为 bls,九张图放进 image_base64_19,指令码放进 instructions,加 json=1 让返回体是 JSON。

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

返回的 request 字段是任务 ID。YOUR_API_KEY 请改成从环境变量读取,别把密钥写死在仓库里。


步骤 3:轮询识别结果

先等 5 秒再开始查,之后每 5 秒查一次 res.php,最多 30 轮。

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

CAPCHA_NOT_READY 是正常状态;其他字符串都是真实错误,要抛出而不是继续循环,否则会静默空转两分半。


步骤 4:按索引点击并提交表单

selectedCells 映射回页面上的九个 img。编号从 1 开始,DOM 下标从 0 开始,故要 cellNum - 1

// 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();

正常运行时你会看到:

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

建议把这四步封装成 solveBls(page) 并允许重试一次——图片拉取被网络抖动打断,比识别本身失败更常见。


实战场景:预约表单的回归测试

BLS 九宫格常见于签证预约一类的表单。合规的典型用法是:机构自己运营预约系统,上线前要验证“填表 → 过验证码 → 提交”在高并发下是否稳定,脚本在 staging 环境反复跑,验证码环节交给上面四步。用 STANDARD 套餐(15 线程),最多 15 个用例可同时停在这一步互不排队。

请只在你自有或已获授权的系统上运行脚本,并留意《网络安全法》《数据安全法》的采集范围要求。


错误码排查

错误 原因 处理方式
ERROR_BAD_PARAMETERS 图片不足 9 张或缺指令码 确认九张图齐全,instructions 非空
CAPCHA_NOT_READY 任务仍在处理 正常状态,继续轮询
ERROR_ZERO_BALANCE 余额不足 到控制台充值

两类问题不体现为错误码:base64 里混进懒加载占位图,以及指令码带空格。前者靠 waitForSelector,后者用 .trim()


常见问题

BLS 返回的是 token 还是坐标?

是坐标。返回索引数组(如 [1, 4, 7, 8]),要在浏览器里逐个点击,而不是填进隐藏字段——这和 reCAPTCHA v2 返回 g-recaptcha-response 的流程不同。

九张图必须全部提交吗?只发指令命中的那几张行不行?

必须全部提交。要看到完整九宫格才能判断哪几格匹配指令,缺图直接返回 ERROR_BAD_PARAMETERS

能用 Playwright 替代 Puppeteer 吗?

可以。axios 提交与轮询一行都不用改,只需把 page.click 换成 Playwright 的 locator().click() 写法。

一个 BLS 任务大概多久出结果?

通常 5–15 秒。这只是参考区间,实际耗时随图片体积与排队情况变化,请实测后再定超时阈值。

CaptchaAI 还支持哪些九宫格类的验证码?

还支持 Grid Image(网格图片)与图片 / OCR 验证码。BLS 固定 3×3,4×4 等变体请改用 Grid Image 方法。


相关阅读


立即注册 CaptchaAI,开始识别 BLS 验证码 →

该文章已禁用评论。