Hướng Dẫn API

Cách giải quyết reCAPTCHA v2 Enterprise bằng Node.js

Khác biệt giữa reCAPTCHA v2 thường và v2 Enterprise nằm ở đúng một tham số: enterprise=1. Luồng vẫn bốn bước — lấy sitekey, gửi task tới in.php, polling res.php, đặt token vào form. Đã có script Node.js giải v2 thường thì bạn chỉ cần thêm ba thứ: nhận diện widget Enterprise, tham số action, và user_agent CaptchaAI trả về.

Enterprise v2 khác gì bản v2 tiêu chuẩn?

Widget vẫn là ô "I'm not a robot", nhưng token được xác minh qua backend Enterprise của Google kèm chấm điểm rủi ro. Ba hệ quả:

  • Sitekey Enterprise và sitekey v2 thường không dùng lẫn nhau được — gửi nhầm sẽ nhận ERROR_BAD_TOKEN_OR_PAGEURL.
  • Trang có thể gắn action (ví dụ LOGIN) và kiểm tra giá trị đó khi verify.
  • Token gắn với User-Agent của phía giải.

Khi nào đội QA ở Việt Nam cần luồng này

Team outsourcing ở TP.HCM hay Hà Nội thường phải chạy regression vài trăm lần mỗi đêm trên cổng đăng nhập Enterprise của khách hàng. Cách ghép vào CI:

  1. Đặt API key trong biến môi trường của runner, không commit vào repo.
  2. Mỗi test case gọi hàm giải một lần rồi truyền token cho request đăng nhập.
  3. Ghi log ID task, thời gian giải và mã lỗi để truy vết khi build đỏ.
  4. Chạy song song đúng bằng số thread trong gói.

CaptchaAI tính giá theo thread (luồng giải đồng thời), không theo lượt giải; giá niêm yết bằng USD. Log thời gian giải cũng phục vụ yêu cầu ghi nhận xử lý dữ liệu theo Nghị định 13/2023/NĐ-CP.

Chuẩn bị trước khi viết code

  • API key CaptchaAI tại captchaai.com
  • Node.js 14+fetch có sẵn hoặc node-fetch
  • sitekey — tham số k= trong anchor URL
  • pageurl — URL đầy đủ của trang
  • action (tùy chọn) — tham số sa=

Bước 1: nhận diện reCAPTCHA v2 Enterprise trong DevTools

Mở DevTools, tab Network, tìm request anchor:

https://www.google.com/recaptcha/enterprise/anchor?ar=1&k=6LdxxXXxAAAAAAcX...&sa=LOGIN&...
  • Script nạp từ /recaptcha/enterprise.js hoặc /enterprise/anchor
  • Tham số k=sitekey gửi cho CaptchaAI
  • Tham số sa= (nếu có) là action

URL /recaptcha/api2/anchor là v2 tiêu chuẩn — đừng thêm enterprise=1.

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

Gửi GET tới in.php với method=userrecaptcha cộng enterprise=1, json=1:

const API_KEY = "YOUR_API_KEY";

async function submitTask(sitekey, pageurl, action) {
  const params = new URLSearchParams({
    key: API_KEY,
    method: "userrecaptcha",
    googlekey: sitekey,
    pageurl: pageurl,
    enterprise: "1",
    json: "1",
  });

  if (action) {
    params.set("action", action);
  }

  const response = await fetch(
    `https://ocr.captchaai.com/in.php?${params}`
  );
  const data = await response.json();

  if (data.status !== 1) {
    throw new Error(`Submit failed: ${data.request}`);
  }

  console.log(`Task submitted. ID: ${data.request}`);
  return data.request;
}

data.request là ID task — giữ lại để tra kết quả.

Bước 3: polling res.php để lấy token

Polling là chủ động hỏi kết quả định kỳ: đợi 20 giây rồi hỏi lần đầu, sau đó mỗi 5 giây:

function delay(ms) {
  return new Promise((resolve) => setTimeout(resolve, ms));
}

async function pollResult(taskId) {
  await delay(20000);

  for (let attempt = 0; attempt < 30; attempt++) {
    const params = new URLSearchParams({
      key: API_KEY,
      action: "get",
      id: taskId,
      json: "1",
    });

    const response = await fetch(
      `https://ocr.captchaai.com/res.php?${params}`
    );
    const data = await response.json();

    if (data.status === 1) {
      console.log(`Solved. Token: ${data.request.substring(0, 60)}...`);
      return {
        token: data.request,
        userAgent: data.user_agent || "",
      };
    }

    if (data.request !== "CAPCHA_NOT_READY") {
      throw new Error(`Solve failed: ${data.request}`);
    }

    console.log(`Attempt ${attempt + 1}: not ready, waiting 5s...`);
    await delay(5000);
  }

  throw new Error("Solve timed out");
}

CAPCHA_NOT_READY là bình thường; giá trị khác là lỗi thật, nên ném ra ngay.

Bước 4: đặt token vào form kèm đúng User-Agent

Token đi kèm request dưới tên trường g-recaptcha-response. Nếu phản hồi có user_agent, đặt giá trị đó vào header:

async function submitForm(token, userAgent) {
  const headers = { "Content-Type": "application/x-www-form-urlencoded" };

  if (userAgent) {
    headers["User-Agent"] = userAgent;
  }

  const response = await fetch("https://example.com/api/login", {
    method: "POST",
    headers,
    body: new URLSearchParams({
      username: "user",
      password: "pass",
      "g-recaptcha-response": token,
    }),
  });

  console.log(`Response status: ${response.status}`);
  return response;
}

Script Node.js hoàn chỉnh

Ghép bốn bước thành một file chạy bằng node solve.js, thay SITE_KEYPAGE_URL bằng giá trị staging:

const API_KEY = "YOUR_API_KEY";
const SITE_KEY = "6LdxxXXxAAAAAAcXxxXxxX91xxxxxxxx8xxOx7A";
const PAGE_URL = "https://staging.example.com/qa-login";
const ACTION = "LOGIN"; // optional — omit if not in anchor URL

function delay(ms) {
  return new Promise((resolve) => setTimeout(resolve, ms));
}

async function solveRecaptchaV2Enterprise() {
  // Submit task
  const submitParams = new URLSearchParams({
    key: API_KEY,
    method: "userrecaptcha",
    googlekey: SITE_KEY,
    pageurl: PAGE_URL,
    enterprise: "1",
    action: ACTION,
    json: "1",
  });

  const submitRes = await fetch(
    `https://ocr.captchaai.com/in.php?${submitParams}`
  );
  const submitData = await submitRes.json();

  if (submitData.status !== 1) {
    throw new Error(`Submit error: ${submitData.request}`);
  }

  const taskId = submitData.request;
  console.log(`Task ID: ${taskId}`);

  // Poll for result
  await delay(20000);

  for (let i = 0; i < 30; i++) {
    const pollParams = new URLSearchParams({
      key: API_KEY,
      action: "get",
      id: taskId,
      json: "1",
    });

    const pollRes = await fetch(
      `https://ocr.captchaai.com/res.php?${pollParams}`
    );
    const pollData = await pollRes.json();

    if (pollData.status === 1) {
      return {
        token: pollData.request,
        userAgent: pollData.user_agent || "",
      };
    }

    if (pollData.request !== "CAPCHA_NOT_READY") {
      throw new Error(`Solve error: ${pollData.request}`);
    }

    await delay(5000);
  }

  throw new Error("Solve timed out");
}

(async () => {
  const { token, userAgent } = await solveRecaptchaV2Enterprise();
  console.log(`Token: ${token.substring(0, 60)}...`);
  if (userAgent) console.log(`User-Agent: ${userAgent}`);
})();

Kết quả in ra khi chạy thành công:

Task ID: 73849562810
Token: 03AGdBq24PBCqLmOx2V4pGHJjkR2xZ1r...
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64)...

Bảng lỗi thường gặp và cách xử lý

Lỗi Nguyên nhân Cách xử lý
ERROR_WRONG_USER_KEY Key sai định dạng Key phải đủ 32 ký tự
ERROR_KEY_DOES_NOT_EXIST Không tìm thấy key Đối chiếu tại captchaai.com
ERROR_ZERO_BALANCE Số dư không đủ Nạp thêm tài khoản
ERROR_BAD_TOKEN_OR_PAGEURL Sai sitekey hoặc pageurl Lấy k= từ anchor URL
ERROR_CAPTCHA_UNSOLVABLE Task không giải được Xác nhận sitekey Enterprise v2, gửi lại
Site từ chối token User-Agent không khớp Dùng user_agent trả về
Timeout sau 30 lần polling Task còn trong hàng đợi Xem số thread đang bận

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

Dùng enterprise=1 cho reCAPTCHA v3 Enterprise được không?

Không. v3 Enterprise vẫn dùng method=userrecaptcha nhưng cần thêm version=v3 (thường cả min_score), v2 Enterprise thì không. Nhận diện sai phiên bản là lý do phổ biến khiến site vẫn chặn dù task trả token.

Chạy 5.000 lượt giải mỗi đêm thì cần gói nào?

Tính theo thread, không theo lượt: mỗi gói không giới hạn số lượt giải. Với trần thời gian giải <60 s của v2 Enterprise, BASIC ($15/tháng, 5 thread) đủ nếu tải rải đều cả đêm; STANDARD ($30/tháng, 15 thread) hợp hơn khi dồn 2–3 tiếng.

Token đúng nhưng form vẫn báo CAPTCHA sai?

Kiểm tra theo thứ tự:

  • User-Agent gửi form có trùng user_agent trả về không
  • pageurl có đúng URL thật không, kể cả subdomain và query
  • Token đã quá hai phút chưa

Nên polling bao lâu một lần?

Chờ 20 giây rồi hỏi mỗi 5 giây như trong code. Khi chạy hàng trăm task song song, thêm jitter 0–2 giây để các worker không cùng gọi res.php.

Bắt đầu ngay

Lấy API key tại captchaai.com, thêm enterprise=1 vào request v2 và chạy script ở trên với sitekey staging.

Đọc thêm

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