Hướng Dẫn API

Cách tự động giải quyết CAPTCHA hình ảnh lưới

Để tự động giải một grid image CAPTCHA, bạn đi qua bốn bước, chạy được với vài chục dòng Python hoặc Node.js:

  1. Chụp toàn bộ lưới thành một ảnh.
  2. Gửi ảnh tới endpoint in.php của CaptchaAI với method=postrecaptcha=1.
  3. Polling res.php cho đến khi có kết quả.
  4. Click các ô theo chỉ số hoặc tọa độ mà API trả về.

Grid image CAPTCHA là gì và khác gì reCAPTCHA

Grid image CAPTCHA là loại thử thách hiển thị một ảnh lớn chia thành lưới (thường 3×3 hoặc 4×4) và yêu cầu người dùng chọn các ô khớp với mô tả. reCAPTCHA cũng dùng định dạng này, nhưng rất nhiều trang lại dựng lưới tùy chỉnh riêng, không thuộc hệ thống của Google. Bài này tập trung vào các grid không phải reCAPTCHA đó — với reCAPTCHA thật, bạn nên dùng token method (method=userrecaptcha) vì đơn giản và ổn định hơn.

Khi nào nên tự động giải grid image CAPTCHA

Một tình huống quen thuộc: team QA tại một công ty outsourcing ở TP.HCM cần chạy regression test hằng đêm cho luồng đăng nhập trên môi trường staging, mà form đó lại chèn một grid captcha tùy chỉnh. Thay vì click thủ công hàng trăm lượt, họ để CaptchaAI giải bước này và cho pipeline tự chạy tiếp. Cách giải trong bài phù hợp khi:

  • Lưới là ảnh tĩnh, không phải reCAPTCHA động.
  • Bạn có quyền kiểm thử trên hệ thống hoặc môi trường staging đó.
  • Bạn muốn đưa bước giải captcha vào một pipeline tự động hóa chạy lặp lại.

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

Thành phần Giá trị
API key CaptchaAI Lấy tại captchaai.com
Ảnh lưới Ảnh chụp màn hình hoặc base64 của toàn bộ lưới
Ngôn ngữ Python 3.7+ hoặc Node.js 14+

Bước 1: chụp toàn bộ lưới thành ảnh

Bạn cần đưa cả lưới về dạng ảnh trước khi gửi. Có hai cách tùy vào việc lưới được render thế nào.

Cách A: chụp màn hình phần tử captcha

from selenium import webdriver
from selenium.webdriver.common.by import By

driver = webdriver.Chrome()
driver.get("https://example.com/protected-form")

# Screenshot just the captcha container
captcha_element = driver.find_element(By.CSS_SELECTOR, "#captcha-container")
captcha_element.screenshot("captcha_grid.png")

Cách B: lấy ảnh từ thuộc tính src

Nếu lưới nằm trong một thẻ img, đọc thẳng thuộc tính src sẽ gọn hơn chụp màn hình — xử lý được cả trường hợp ảnh nhúng dạng data:image lẫn ảnh phải tải qua HTTP.

import base64
import requests

captcha_img = driver.find_element(By.CSS_SELECTOR, ".grid-captcha img")
src = captcha_img.get_attribute("src")

if src.startswith("data:image"):
    image_b64 = src.split(",")[1]
else:
    image_data = requests.get(src).content
    image_b64 = base64.b64encode(image_data).decode()

Bước 2: gửi ảnh lưới tới CaptchaAI

Gửi task về endpoint in.php. Điểm mấu chốt cho grid là hai tham số method=postrecaptcha=1 — chúng báo cho CaptchaAI biết đây là thử thách chọn ô, không phải OCR văn bản thường. API trả về một ID task để bạn tra kết quả ở bước sau.

Gửi bằng file upload (Python)

import requests
import time

API_KEY = "YOUR_API_KEY"

with open("captcha_grid.png", "rb") as f:
    response = requests.post("https://ocr.captchaai.com/in.php",
        data={
            "key": API_KEY,
            "method": "post",
            "recaptcha": 1,
            "json": 1
        },
        files={"file": f}
    )

data = response.json()
task_id = data["request"]
print(f"Task: {task_id}")

Gửi bằng base64 (Python)

Nếu bạn đã có ảnh dưới dạng base64 (ví dụ từ Cách B ở trên), gửi thẳng qua tham số body, khỏi ghi file ra đĩa.

response = requests.post("https://ocr.captchaai.com/in.php", data={
    "key": API_KEY,
    "method": "post",
    "body": image_b64,
    "recaptcha": 1,
    "json": 1
})

task_id = response.json()["request"]

Node.js

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

async function submitGridCaptcha(imagePath) {
  const imageB64 = fs.readFileSync(imagePath).toString('base64');

  const { data } = await axios.post('https://ocr.captchaai.com/in.php', null, {
    params: {
      key: 'YOUR_API_KEY',
      method: 'post',
      body: imageB64,
      recaptcha: 1,
      json: 1
    }
  });

  return data.request;
}

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

Kết quả không trả về ngay. Bạn gọi res.php mỗi 5 giây cho đến khi trạng thái là 1; trong lúc đó API trả CAPCHA_NOT_READY là bình thường. Với grid, kết quả thường có trong khoảng 15–30 giây tùy chất lượng ảnh.

def get_grid_solution(task_id):
    for _ in range(30):
        time.sleep(5)
        result = requests.get("https://ocr.captchaai.com/res.php", params={
            "key": API_KEY,
            "action": "get",
            "id": task_id,
            "json": 1
        }).json()

        if result.get("status") == 1:
            return result["request"]
        if result.get("request") != "CAPCHA_NOT_READY":
            raise Exception(f"Error: {result['request']}")

    raise Exception("Timeout")

solution = get_grid_solution(task_id)
print(f"Solution: {solution}")
# Returns click coordinates or cell indices

Bước 4: click các ô theo kết quả

CaptchaAI trả về một trong hai định dạng: danh sách chỉ số ô (2,5,6) hoặc danh sách tọa độ (x=120,y=80;x=250,y=200). Chọn nhánh xử lý đúng với định dạng bạn nhận được.

Click theo chỉ số ô

# If solution returns cell indices (e.g., "2,5,6")
selected = [int(i) for i in solution.split(",")]
cells = driver.find_elements(By.CSS_SELECTOR, ".grid-cell")

for idx in selected:
    cells[idx - 1].click()
    time.sleep(0.2)

driver.find_element(By.CSS_SELECTOR, ".verify-button").click()

Click theo tọa độ

from selenium.webdriver.common.action_chains import ActionChains

# If solution returns coordinates (e.g., "x=120,y=80;x=250,y=200")
captcha_element = driver.find_element(By.CSS_SELECTOR, "#captcha-container")
actions = ActionChains(driver)

for coord in solution.split(";"):
    parts = dict(p.split("=") for p in coord.split(","))
    x, y = int(parts["x"]), int(parts["y"])
    actions.move_to_element_with_offset(captcha_element, x, y).click()

actions.perform()

Xử lý lỗi thường gặp

Lỗi Nguyên nhân Cách xử lý
ERROR_WRONG_FILE_EXTENSION Định dạng ảnh không hợp lệ Dùng PNG hoặc JPEG; kiểm tra chuỗi base64 có hợp lệ không
ERROR_CAPTCHA_UNSOLVABLE Ảnh quá nhỏ hoặc mờ Chụp ở độ phân giải đầy đủ
Click sai ô Nhầm định dạng kết quả Kiểm tra kết quả là chỉ số ô hay tọa độ
ERROR_TOO_BIG_CAPTCHA_FILESIZE Ảnh vượt quá giới hạn dung lượng Giảm kích thước xuống dưới 600KB

Ví dụ hoàn chỉnh có thể chạy ngay

Cần một dự án chạy được đầy đủ, có sẵn thiết lập môi trường, polling, thử lại và xử lý lỗi?

Xem ví dụ hoàn chỉnh trên GitHub →


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

Giải grid image CAPTCHA tốn bao nhiêu tiền?

CaptchaAI tính giá theo thread (số luồng giải đồng thời), không tính theo từng lượt giải. Gói thấp nhất là BASIC ($15/tháng, 5 thread), giải không giới hạn trong tháng với 5 luồng chạy song song. Grid không bị tính phụ phí riêng so với các loại CAPTCHA khác.

Nên gửi ảnh lưới bằng file upload hay base64?

Cả hai đều tới cùng endpoint in.php và cho kết quả như nhau. Dùng base64 khi bạn đã có ảnh trong bộ nhớ (ví dụ đọc từ thuộc tính src) để khỏi ghi file ra đĩa; dùng file upload khi bạn đã chụp màn hình và lưu thành file .png.

Grid image CAPTCHA khác gì so với OCR/normal captcha?

Normal captcha (OCR) yêu cầu đọc chuỗi ký tự trong ảnh và trả về text. Grid image yêu cầu chọn các ô khớp mô tả, nên kết quả là chỉ số ô hoặc tọa độ để bạn click, chứ không phải một chuỗi ký tự. Vì vậy grid cần thêm tham số recaptcha=1.

Khi nào nên dùng grid solving, khi nào dùng token solving?

Dùng token solving (method=userrecaptcha) cho reCAPTCHA chuẩn — đơn giản và ổn định hơn. Dùng grid solving (method=post với recaptcha=1) cho các lưới tùy chỉnh không phải reCAPTCHA hoặc lưới hình ảnh độc lập. Với lưới động của reCAPTCHA (ô được thay khi click), hãy dùng token method vì grid method chỉ giải một ảnh tĩnh.


Hướng dẫn liên quan

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