Gặp ERROR_CAPTCHA_UNSOLVABLE giữa lúc chạy batch, hay CAPCHA_NOT_READY lặp mãi không dứt? Phần lớn mã lỗi của API CaptchaAI rơi vào ba nhóm: sai tham số (sửa request rồi gửi lại), tài khoản/xác thực (kiểm tra key và số dư), hoặc lỗi tạm thời phía server (thử lại có backoff). Bài này liệt kê từng mã lỗi ở cả hai điểm cuối, kèm nguyên nhân thực tế và cách xử lý cụ thể — dành cho dev đang debug một tích hợp thật, không phải bài tổng quan lý thuyết.
API CaptchaAI có hai điểm cuối:
in.php— nơi bạn gửi task CAPTCHA (lỗi xảy ra ngay khi gửi)res.php— nơi bạn polling kết quả (lỗi xảy ra khi truy xuất)
Thêm json=1 vào request thì lỗi trả về dưới dạng JSON, dễ parse hơn nhiều so với text thuần:
{"status": 0, "request": "ERROR_CODE_HERE"}
Không có json=1, lỗi trả về dưới dạng văn bản thuần: ERROR_CODE_HERE
Mẹo: luôn bật
json=1kể cả khi debug thủ công — thói quen này giúp log lỗi tự động ngay từ đầu, không phải sửa lại pipeline khi lên production.
Ba quy tắc xử lý 90% mã lỗi captchaai
Chưa cần đọc hết danh sách bên dưới — ba dòng này đã đủ cho phần lớn trường hợp thực tế:
| Mẫu lỗi | Hành động |
|---|---|
CAPCHA_NOT_READY |
Bình thường — poll lại sau 5 giây, không phải lỗi |
ERROR_ liên quan tham số/format (sitekey, pageurl, key sai...) |
Sửa request rồi gửi lại — đừng gửi lại y nguyên request cũ |
Lỗi máy chủ (ERROR_SERVER_ERROR, ERROR_INTERNAL_SERVER_ERROR) |
Thử lại sau 10 giây, dùng backoff tăng dần |
Lỗi khi gửi task tới in.php
Nhóm lỗi này xuất hiện ngay tại bước gửi task CAPTCHA mới — trước khi CaptchaAI kịp bắt đầu giải. Sắp xếp theo mức độ gặp thực tế: lỗi tham số/định dạng (sửa request rồi gửi lại) chiếm phần lớn danh sách bên dưới, tiếp theo là lỗi tài khoản/xác thực, cuối cùng là lỗi tạm thời phía server.
ERROR_WRONG_USER_KEY
Nguyên nhân: Tham số key sai định dạng. API key của CaptchaAI luôn có đúng 32 ký tự.
Cách sửa:
- Đếm lại xem key có đúng 32 ký tự không.
- Kiểm tra không có khoảng trắng thừa hoặc ký tự xuống dòng dính vào.
- Copy key trực tiếp từcaptchaai.com/api.php, tránh gõ tay.
{
"key": "abc123... "
}
{
"key": "abc12345678901234567890123456789a"
}
ERROR_PAGEURL
Nguyên nhân: Tham số pageurl thiếu hoặc rỗng. Tham số này bắt buộc với mọi CAPTCHA dạng token (reCAPTCHA, Cloudflare Turnstile, GeeTest...).
Cách sửa: Điền đầy đủ URL của trang chứa CAPTCHA, kèm cả giao thức (https://):
{
"pageurl": ""
}
{
"pageurl": "https://staging.example.com/qa-login"
}
ERROR_WRONG_GOOGLEKEY / ERROR_GOOGLEKEY
Nguyên nhân: Tham số googlekey (sitekey) rỗng, sai định dạng hoặc bị thiếu.
Cách sửa:
- Trích lại sitekey từ thuộc tính
data-sitekeytrên trang đích, hoặc từ tham sốktrong URL anchor của reCAPTCHA. - Kiểm tra giá trị không bị rỗng hoặc cắt cụt khi copy.
{
"googlekey": ""
}
{
"googlekey": "6Le-wvkSAAAAAPBMRTvw0Q4Muexq9bi0DJwx_mJ-"
}
ERROR_BAD_TOKEN_OR_PAGEURL
Nguyên nhân: Cặp googlekey (sitekey) và pageurl không khớp — sitekey chưa được đăng ký cho URL trang đó.
Nguyên nhân thường gặp:
- reCAPTCHA nằm trong iframe ở subdomain khác, nhưng bạn đang truyền URL trang cha thay vì URL iframe.
- Sitekey thuộc về một trang hoặc domain khác.
- Sitekey được trích từ môi trường dev/staging chứ không phải production.
Cách sửa:
- Nếu reCAPTCHA nằm trong iframe, dùng URL
srccủa iframe đó làmpageurl. - Lấy lại sitekey trực tiếp từ trang production đang chạy thật.
- Kiểm tra cả hai giá trị bằng cách tải thủ công URL anchor của reCAPTCHA:
https://www.google.com/recaptcha/api2/anchor?k=YOUR_SITEKEY
ERROR_BAD_PARAMETERS
Nguyên nhân: Thiếu tham số bắt buộc, hoặc kiểu dữ liệu sai.
Cách sửa: Đối chiếu tài liệu API cho đúng loại CAPTCHA đang giải, đảm bảo đủ các tham số bắt buộc sau:
| Loại CAPTCHA | Thông số bắt buộc |
|---|---|
| reCAPTCHA v2/v3 | key, method=userrecaptcha, googlekey, pageurl |
| Cloudflare Turnstile | key, method=turnstile, sitekey, pageurl |
| Cloudflare Challenge | key, method=cloudflare_challenge, pageurl, proxy, proxytype |
| GeeTest v3 | key, method=geetest, gt, challenge, pageurl |
| BLS | key, method=bls, body, textinstructions |
| Bình thường/image | key, method=post, file hoặc body |
ERROR_WRONG_FILE_EXTENSION
Nguyên nhân: File có phần mở rộng không được hỗ trợ. Các định dạng hỗ trợ: jpg, jpeg, png, gif.
Cách sửa: Convert ảnh sang định dạng được hỗ trợ trước khi gửi.
Phòng lặp lại:
- Chuẩn hóa pipeline luôn xuất ảnh
.jpghoặc.pngtrước khi gửi. - Kiểm tra phần mở rộng bằng code, không chỉ dựa vào tên file gốc.
ERROR_IMAGE_TYPE_NOT_SUPPORTED
Nguyên nhân: Server không xác định được loại ảnh từ nội dung file.
Cách sửa: Convert sang định dạng chuẩn (PNG hoặc JPEG) và đảm bảo file không bị hỏng.
Phòng lặp lại:
- Mở lại file bằng thư viện ảnh để xác nhận file không bị hỏng trước khi gửi.
- Convert sang PNG chuẩn nếu ảnh lấy từ nguồn không rõ định dạng gốc.
ERROR_TOO_BIG_CAPTCHA_FILESIZE
Nguyên nhân: Ảnh tải lên vượt kích thước tối đa cho phép.
Cách sửa: Nén hoặc resize ảnh trước khi gửi. Dùng JPEG cho ảnh chụp thật, PNG cho screenshot.
Phòng lặp lại:
- Nén ảnh bằng Pillow (Python) hoặc
sharp(Node.js) trước khi gửi. - Đặt giới hạn kích thước upload ngay trong pipeline scraping, đừng đợi CaptchaAI trả lỗi mới xử lý.
ERROR_ZERO_CAPTCHA_FILESIZE
Nguyên nhân: File ảnh quá nhỏ (dưới 100 byte) — dấu hiệu của upload rỗng hoặc file hỏng.
Cách sửa: Kiểm tra bạn đang gửi dữ liệu ảnh thật, không phải file rỗng hoặc chuỗi base64 bị cắt cụt.
Phòng lặp lại:
- Log kích thước file ngay trước khi gửi để phát hiện sớm file rỗng.
- Validate ảnh lớn hơn 100 byte trong code, trước khi gọi
in.php.
ERROR_UPLOAD
Nguyên nhân: Server không đọc được file tải lên hoặc payload base64.
Cách sửa:
- Với file upload: kiểm tra lại encoding của multipart form data.
- Với base64: kiểm tra chuỗi base64 đầy đủ, không bị cắt và encode đúng.
- Test thử với một ảnh đã biết chắc chắn hợp lệ để loại trừ khả năng file hỏng.
ERROR_BAD_PROXY
Nguyên nhân: Proxy bạn khai báo không truy cập được, hoặc bị hệ thống đánh dấu là hỏng.
Cách sửa:
- Test proxy độc lập — nó có kết nối được tới trang đích không?
- Đổi sang proxy khác.
- Kiểm tra đúng định dạng:
login:password@IP:PORThoặcIP:PORTcho proxy xác thực theo IP.
Tính năng dùng proxy phải được bật trên tài khoản của bạn trước. Liên hệ hỗ trợ CaptchaAI nếu chưa bật.
ERROR_KEY_DOES_NOT_EXIST
Nguyên nhân: Key API không khớp với tài khoản nào trong hệ thống.
Cách sửa:
- Đăng nhập vàocaptchaai.comvà copy key từ dashboard.
- Kiểm tra bạn đang dùng đúng key của đúng tài khoản (dễ nhầm khi có nhiều account test/production).
- Nếu tài khoản vừa tạo, đợi vài phút cho key kích hoạt.
ERROR_ZERO_BALANCE
Nguyên nhân: Tài khoản không còn thread trống để nhận task mới.
Cách sửa:
- Đợi các task đang chạy hoàn tất — thread sẽ tự giải phóng.
- Nâng cấp gói để có thêm thread đồng thời.
- Kiểm tra số dư tạicaptchaai.com/api.php.
Lỗi này không phải lúc nào cũng do hết tiền. Nó thường xảy ra khi toàn bộ thread đang bận. Một đội scraping ở TP.HCM theo dõi giá trên Shopee/Lazada từng gặp lỗi này mỗi khi chạy batch buổi tối — nguyên nhân không phải hết số dư mà do gói BASIC ($15/tháng, 5 thread) không đủ cho khối lượng đồng thời, và task cũ chưa kịp trả kết quả đã bị chèn task mới. Nâng lên STANDARD ($30/tháng, 15 thread) giải quyết dứt điểm.
IP_BANNED
Nguyên nhân: IP của bạn bị chặn tạm thời sau nhiều lần xác thực sai liên tiếp.
Cách sửa: Đợi khoảng 5 phút rồi thử lại với thông tin xác thực đúng. Đừng cố gửi tiếp request với key sai — càng gửi càng kéo dài thời gian bị chặn.
Phòng lặp lại:
- Kiểm tra log xem có tiến trình nào đang gửi lặp lại request bằng key sai không.
- Dừng toàn bộ traffic từ IP đó ít nhất 5 phút trước khi thử lại.
ERROR_SERVER_ERROR / ERROR_INTERNAL_SERVER_ERROR
Nguyên nhân: Lỗi tạm thời phía server.
Cách sửa: Đợi 10 giây rồi thử lại. Dùng backoff tăng dần cho các lần lỗi liên tiếp:
import time
retry_delay = 10
for attempt in range(5):
response = submit_captcha()
if response.get("status") == 1:
break
time.sleep(retry_delay)
retry_delay *= 2 # 10s, 20s, 40s, 80s, 160s
Lỗi khi polling res.php
Nhóm này xuất hiện khi bạn kiểm tra trạng thái của một task đã gửi trước đó. CAPCHA_NOT_READY đứng đầu vì đây là trạng thái bình thường bạn sẽ gặp nhiều nhất; phần còn lại đi từ lỗi định dạng dễ sửa tới lỗi cần điều tra sâu hơn như proxy hay CAPTCHA không giải được.
CAPCHA_NOT_READY
Đây không phải lỗi. Nó chỉ có nghĩa là CaptchaAI vẫn đang giải, chưa xong.
Hành động: Đợi 5 giây rồi poll lại.
if result.get("request") == "CAPCHA_NOT_READY":
time.sleep(5)
continue # poll again
Thời điểm polling theo từng loại CAPTCHA: | Loại CAPTCHA | Poll lần đầu sau | Khoảng cách giữa các lần poll | |---|---|---| | reCAPTCHA v2/v3/Enterprise | 15 giây | 5 giây | | Cloudflare Turnstile | 15 giây | 5 giây | | Cloudflare Challenge | 20 giây | 5 giây | | GeeTest v3 | 15 giây | 5 giây | | Bình thường/image CAPTCHA | 5 giây | 5 giây |
ERROR_WRONG_CAPTCHA_ID
Nguyên nhân: ID task không tồn tại hoặc đã hết hạn.
Cách sửa:
- Kiểm tra bạn đang poll bằng đúng ID nhận được lúc gửi task.
- ID task có thể hết hạn nếu để quá lâu — gửi lại task mới nếu task đã cũ.
ERROR_WRONG_ID_FORMAT
Nguyên nhân: ID task chỉ được chứa chữ số.
Cách sửa: Kiểm tra bạn đang gửi đúng ID mà in.php trả về (chỉ số, không lẫn ký tự khác).
Phòng lặp lại:
- In log giá trị
idngay trước khi gửi để phát hiện ký tự lạ. - Lấy
idtừ fieldrequesttrong response JSON củain.php, đừng parse nhầm field khác.
ERROR_EMPTY_ACTION
Nguyên nhân: Tham số action thiếu hoặc rỗng trong request polling.
Cách sửa: Thêm action=get vào request res.php:
params = {
"key": api_key,
"action": "get", # Required
"id": captcha_id,
"json": 1,
}
ERROR_PROXY_CONNECTION_FAILED
Nguyên nhân: Solver không kết nối được tới trang đích qua proxy bạn cung cấp.
Cách sửa:
- Proxy có thể tạm thời chết — đổi sang proxy khác.
- Trang đích có thể đang chặn chính IP proxy đó.
- Kiểm tra proxy thực sự reach được trang đích trước khi dùng.
Phòng lặp lại:
- Theo dõi tỷ lệ lỗi proxy theo thời gian để phát hiện proxy pool đang xuống cấp.
- Chuẩn bị sẵn danh sách proxy dự phòng để fallback tự động.
ERROR_CAPTCHA_UNSOLVABLE
Nguyên nhân: CaptchaAI thử nhiều lần nhưng không giải được CAPTCHA này.
Các nguyên nhân thường gặp:
- Loại CAPTCHA không được hỗ trợ, hoặc tham số sai.
- Challenge bị hỏng hoặc đã hết hạn.
- Với các solve dùng proxy: proxy quá chậm hoặc không truy cập được trang đích.
- Site đã đổi cách triển khai CAPTCHA.
Cách sửa:
- Kiểm tra lại tham số (sitekey, pageurl, method) đúng chưa.
- Gửi một task mới hoàn toàn.
- Nếu đang dùng proxy, đổi sang proxy khác.
- Nếu vẫn lỗi lặp lại, khả năng cao site đã thay đổi — trích lại sitekey và pageurl từ đầu.
Đừng poll lại cùng một task ID đã báo lỗi này. Gửi task mới với tham số mới.
ERROR_WRONG_USER_KEY / ERROR_KEY_DOES_NOT_EXIST
Hai lỗi này cũng có thể xuất hiện ở res.php, không chỉ ở in.php — nguyên nhân và cách sửa giống hệt phần lỗi gửi task ở trên.
Phòng lặp lại:
- Dùng chung một biến
API_KEYcho cảin.phpvàres.php, tránh lệch key giữa hai bước. - Nếu lỗi chỉ xảy ra ở
res.php, kiểm tra request polling có đang hardcode key cũ không.
Template xử lý lỗi dùng ngay
Copy mẫu này để xử lý lỗi đầy đủ, dùng được với bất kỳ ngôn ngữ nào:
Python
import time
import requests
API_KEY = "YOUR_API_KEY"
SUBMIT_URL = "https://ocr.captchaai.com/in.php"
RESULT_URL = "https://ocr.captchaai.com/res.php"
# Errors that should not be retried (fix the request first)
NO_RETRY_ERRORS = {
"ERROR_WRONG_USER_KEY",
"ERROR_KEY_DOES_NOT_EXIST",
"ERROR_PAGEURL",
"ERROR_WRONG_GOOGLEKEY",
"ERROR_GOOGLEKEY",
"ERROR_BAD_TOKEN_OR_PAGEURL",
"ERROR_BAD_PARAMETERS",
"ERROR_WRONG_FILE_EXTENSION",
"ERROR_IMAGE_TYPE_NOT_SUPPORTED",
"IP_BANNED",
}
# Errors that can be retried
RETRY_ERRORS = {
"ERROR_ZERO_BALANCE",
"ERROR_SERVER_ERROR",
"ERROR_INTERNAL_SERVER_ERROR",
"ERROR_UPLOAD",
}
def solve_captcha(submit_data, max_retries=3, max_polls=60):
"""Submit and solve a CAPTCHA with full error handling."""
# Submit with retry logic
for attempt in range(max_retries):
resp = requests.post(SUBMIT_URL, data={**submit_data, "json": 1}, timeout=30)
resp.raise_for_status()
data = resp.json()
if data.get("status") == 1:
captcha_id = data["request"]
break
error = data.get("request", "UNKNOWN")
if error in NO_RETRY_ERRORS:
raise ValueError(f"Fatal error (fix request): {error}")
if error in RETRY_ERRORS and attempt < max_retries - 1:
time.sleep(10 * (2 ** attempt))
continue
raise RuntimeError(f"Submit failed: {error}")
else:
raise RuntimeError("Submit failed after max retries")
# Poll for result
time.sleep(15)
for _ in range(max_polls):
resp = requests.get(
RESULT_URL,
params={"key": API_KEY, "action": "get", "id": captcha_id, "json": 1},
timeout=30,
)
data = resp.json()
if data.get("request") == "CAPCHA_NOT_READY":
time.sleep(5)
continue
if data.get("status") == 1:
return data["request"]
error = data.get("request", "UNKNOWN")
if error == "ERROR_CAPTCHA_UNSOLVABLE":
raise RuntimeError("CAPTCHA unsolvable — resubmit with fresh parameters")
raise RuntimeError(f"Poll error: {error}")
raise TimeoutError("Solve timed out")
Node.js
const NO_RETRY_ERRORS = new Set([
"ERROR_WRONG_USER_KEY",
"ERROR_KEY_DOES_NOT_EXIST",
"ERROR_PAGEURL",
"ERROR_WRONG_GOOGLEKEY",
"ERROR_BAD_TOKEN_OR_PAGEURL",
"ERROR_BAD_PARAMETERS",
"IP_BANNED",
]);
async function solveCaptcha(submitData, maxRetries = 3, maxPolls = 60) {
const sleep = (ms) => new Promise((r) => setTimeout(r, ms));
// Submit with retry
let captchaId;
for (let attempt = 0; attempt < maxRetries; attempt++) {
const resp = await fetch("https://ocr.captchaai.com/in.php", {
method: "POST",
headers: { "Content-Type": "application/x-www-form-urlencoded" },
body: new URLSearchParams({ ...submitData, json: "1" }),
});
const data = await resp.json();
if (data.status === 1) {
captchaId = data.request;
break;
}
if (NO_RETRY_ERRORS.has(data.request)) {
throw new Error(`Fatal error: ${data.request}`);
}
if (attempt < maxRetries - 1) {
await sleep(10_000 * 2 ** attempt);
continue;
}
throw new Error(`Submit failed: ${data.request}`);
}
// Poll for result
await sleep(15_000);
for (let i = 0; i < maxPolls; i++) {
const resp = await fetch(
`https://ocr.captchaai.com/res.php?${new URLSearchParams({
key: submitData.key,
action: "get",
id: captchaId,
json: "1",
})}`
);
const data = await resp.json();
if (data.request === "CAPCHA_NOT_READY") {
await sleep(5_000);
continue;
}
if (data.status === 1) return data.request;
throw new Error(`Poll error: ${data.request}`);
}
throw new Error("Solve timed out");
}
Câu hỏi thường gặp
CAPCHA_NOT_READY có phải lỗi cần xử lý không?
Không. Nó chỉ báo rằng CaptchaAI vẫn đang giải, chưa xong — poll lại sau 5 giây là đủ. Trạng thái này bình thường với mọi loại CAPTCHA, kể cả reCAPTCHA và Turnstile.
Vì sao nên luôn bật json=1 khi debug lỗi?
Không có json=1, lỗi trả về dạng text thuần (ERROR_CODE_HERE), khó tách khỏi response thành công bằng code. Với json=1, bạn luôn nhận được cặp status/request có cấu trúc, parse và log lỗi tự động dễ hơn nhiều — nhất là khi chạy hàng nghìn request mỗi ngày.
ERROR_ZERO_BALANCE báo dù tài khoản vẫn còn tiền, tại sao?
Vì lỗi này không chỉ nói về số dư — nó còn nghĩa là toàn bộ thread hiện đang bận. CaptchaAI tính phí theo thread (gói BASIC $15/tháng có 5 thread, STANDARD $30/tháng có 15 thread...), không phải theo số dư solve. Nếu bạn gửi task vượt số thread đang có, các request mới sẽ bị từ chối cho tới khi có thread trống.
Gặp ERROR_CAPTCHA_UNSOLVABLE liên tục thì nên xử lý theo thứ tự nào?
Trước tiên xác minh sitekey và pageurl đúng trang production. Sau đó gửi lại bằng task ID mới — không bao giờ poll lại task ID cũ đã báo lỗi này. Nếu lỗi vẫn lặp lại trên cùng một site, khả năng cao site đã đổi cách triển khai CAPTCHA và bạn cần trích lại tham số từ đầu.
ERROR_WRONG_USER_KEY và ERROR_KEY_DOES_NOT_EXIST khác nhau ở đâu?
ERROR_WRONG_USER_KEY là lỗi format — key không đủ 32 ký tự hoặc dính khoảng trắng/ký tự thừa. ERROR_KEY_DOES_NOT_EXIST là key đúng định dạng nhưng không khớp tài khoản nào — thường do copy nhầm key của account khác hoặc key thuộc account vừa tạo chưa kích hoạt xong. Cách chắc chắn nhất để loại trừ cả hai: đăng nhập vàocaptchaai.comvà lấy lại key trực tiếp từcaptchaai.com/api.php.
Hướng dẫn liên quan
- Quickstart CaptchaAI — giải CAPTCHA đầu tiên của bạn trong 5 phút
- Cách giải reCAPTCHA v2 bằng API — hướng dẫn tích hợp đầy đủ, từ sitekey tới token
- Cách giải Cloudflare Challenge bằng API — lưu ý bắt buộc phải có proxy hoạt động
- Các lỗi thường gặp khi giải reCAPTCHA v2 — troubleshooting chuyên sâu riêng cho reCAPTCHA v2