Hướng Dẫn API

Cách giải Cloudflare Turnstile bằng API

Turnstile không hiện ô "Tôi không phải robot" — nó chấm điểm trình duyệt trong im lặng rồi tự phát token. Giải bằng script chỉ cần 4 việc: lấy sitekey, gửi task tới in.php, polling res.php, chèn token vào form. Bài này đi thẳng vào 4 bước đó bằng API CaptchaAI, kèm code Python và Node.js.

Ví dụ: đội QA ở một công ty outsourcing TP.HCM test luồng đăng nhập trên staging site được Turnstile bảo vệ trước mỗi lần release — quy trình dưới đây là thứ họ tự động hoá trong pipeline CI. Chưa quen CaptchaAI thì xem Quickstart trước.


Chuẩn bị trước khi giải Turnstile qua API

Trước khi viết dòng code đầu tiên, gom đủ 4 thứ dưới đây — thiếu một trong số này là request đầu tiên đã trả lỗi ngay tại bước gửi task.

Mục Giá trị
API key CaptchaAI Từ bảng điều khiển tại captchaai.com
Sitekey Turnstile Trích từ trang đích (bắt đầu bằng 0x)
URL trang URL đầy đủ nơi widget render
Ngôn ngữ Python 3.7+ hoặc Node.js 14+

Bước 1: Lấy sitekey Turnstile từ trang đích

Sitekey nằm sẵn trong HTML của trang, thường trong thẻ div hoặc script:

<div class="cf-turnstile" data-sitekey="0x4AAAAAAAC3DHQFLr1GavNl"></div>

Hoặc được render bằng JavaScript:

turnstile.render('#widget', {
  sitekey: '0x4AAAAAAAC3DHQFLr1GavNl',
  callback: function(token) { /* ... */ }
});

Ba cách trích xuất:

  1. DevTools trình duyệt — tab Elements, tìm data-sitekey hoặc cf-turnstile.
  2. Xem mã nguồnCtrl+U, tìm chuỗi bắt đầu bằng 0x.
  3. Tab Network — lọc theo challenges.cloudflare.com; sitekey nằm trong tham số request.

Sitekey Turnstile luôn bắt đầu bằng 0x — cách phân biệt nhanh với khoá reCAPTCHA (bắt đầu bằng 6L).

Lưu ý nhỏ: một số trang render widget Turnstile trong iframe lồng nhau, DevTools mặc định không nhảy thẳng vào được — bấm chuột phải trên widget rồi chọn "Inspect" thay vì tìm thủ công trong tab Elements sẽ nhanh hơn nhiều.


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

POST tới https://ocr.captchaai.com/in.php với method=turnstile:

import requests

API_KEY = "YOUR_CAPTCHAAI_KEY"
SITEKEY = "0x4AAAAAAAC3DHQFLr1GavNl"
PAGEURL = "https://staging.example.com/qa-login"

r = requests.post("https://ocr.captchaai.com/in.php", data={
    "key": API_KEY,
    "method": "turnstile",
    "sitekey": SITEKEY,
    "pageurl": PAGEURL,
    "json": 1,
})
data = r.json()
if data["status"] != 1:
    raise RuntimeError(f"submit failed: {data}")
task_id = data["request"]
print("task id:", task_id)

Tương đương Node.js:

const axios = require("axios");

const { data } = await axios.post("https://ocr.captchaai.com/in.php", null, {
  params: {
    key: process.env.CAPTCHAAI_KEY,
    method: "turnstile",
    sitekey: "0x4AAAAAAAC3DHQFLr1GavNl",
    pageurl: "https://staging.example.com/qa-login",
    json: 1,
  },
});
if (data.status !== 1) throw new Error(`submit failed: ${JSON.stringify(data)}`);
const taskId = data.request;

Gửi thành công trả về {"status": 1, "request": "<task_id>"}. Giữ lại task_id này để polling ở bước sau.


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

CaptchaAI thường giải xong trong chưa đầy 10 giây. Đợi 10 giây trước lần poll đầu, rồi lặp mỗi 5 giây, tối đa 40 vòng để chừa dư địa cho các trang khó:

import time

time.sleep(10)
for _ in range(40):
    r = requests.get("https://ocr.captchaai.com/res.php", params={
        "key": API_KEY,
        "action": "get",
        "id": task_id,
        "json": 1,
    })
    res = r.json()
    if res["status"] == 1:
        token = res["request"]
        break
    if res["request"] != "CAPCHA_NOT_READY":
        raise RuntimeError(f"solver error: {res}")
    time.sleep(5)
else:
    raise TimeoutError("turnstile solving timed out")

print("token (60 ký tự đầu):", token[:60])

Token trả về là một chuỗi Base64, thường bắt đầu bằng 0. và dài 400–600 ký tự.


Bước 4: Đưa token vào form và submit

Gán token vào trường ẩn cf-turnstile-response của form rồi submit như bình thường.

Selenium:

driver.execute_script(
    "document.querySelector('[name=cf-turnstile-response]').value = arguments[0];",
    token,
)
driver.find_element("css selector", "form").submit()

Playwright:

page.evaluate(
    "(t) => document.querySelector('[name=cf-turnstile-response]').value = t",
    token,
)
page.click("button[type=submit]")

HTTP thuần: thêm cf-turnstile-response=<token> vào body application/x-www-form-urlencoded.

Token chỉ sống khoảng 120–300 giây. Chậm tay là backend trả timeout-or-duplicate, phải giải lại từ đầu.


Ví dụ Python đầy đủ

Gộp cả 4 bước trên vào một hàm duy nhất để copy-paste thẳng vào script automation của bạn:

import os, time, requests

API = "https://ocr.captchaai.com"
KEY = os.environ["CAPTCHAAI_KEY"]

def solve_turnstile(sitekey: str, pageurl: str) -> str:
    r = requests.post(f"{API}/in.php", data={
        "key": KEY, "method": "turnstile",
        "sitekey": sitekey, "pageurl": pageurl, "json": 1,
    }, timeout=30)
    j = r.json()
    if j["status"] != 1:
        raise RuntimeError(f"submit: {j}")
    tid = j["request"]

    time.sleep(10)
    for _ in range(40):
        r = requests.get(f"{API}/res.php", params={
            "key": KEY, "action": "get", "id": tid, "json": 1,
        }, timeout=30)
        j = r.json()
        if j["status"] == 1:
            return j["request"]
        if j["request"] != "CAPCHA_NOT_READY":
            raise RuntimeError(f"poll: {j}")
        time.sleep(5)
    raise TimeoutError("timeout")

if __name__ == "__main__":
    print(solve_turnstile("0x4AAAAAAAC3DHQFLr1GavNl", "https://staging.example.com/qa-login"))

Turnstile vẫn không giải được? Kiểm tra 4 điều này

Trước khi mở ticket hỗ trợ, tự rà qua danh sách này — phần lớn ca "giải mãi không được" nằm ở một trong bốn nguyên nhân sau, không phải lỗi từ phía CaptchaAI:

  1. Sitekey đổi theo mỗi lượt truy cập. Scrape lại trang ngay trước khi gửi task, đừng cache sitekey cũ.
  2. pageurl không khớp. Backend Turnstile so URL rất nghiêm; gửi đúng path, bỏ query string thừa.
  3. Token đã hết hạn. Dùng trong 2 phút, quá giờ thì giải lại từ Bước 2.
  4. Chất lượng nguồn IP. IP datacenter dùng chung, giá rẻ dễ khiến Turnstile bật thêm thử thách. Nếu Cloudflare vẫn chặn ở tầng TLS, dùng curl_cffi hoặc Playwright thay vì requests trần.

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

Nếu bốn điều trên không phải nguyên nhân, tra tiếp mã lỗi trả về từ in.php/res.php trong bảng sau:

Ý nghĩa Hành động
ERROR_WRONG_USER_KEY Định dạng API key sai Kiểm tra lại biến CAPTCHAAI_KEY, dán đủ ký tự
ERROR_KEY_DOES_NOT_EXIST Không tìm thấy key Sao chép lại key từ bảng điều khiển
ERROR_ZERO_BALANCE Số dư bằng 0 Nạp tiền rồi gửi lại task
ERROR_PAGEURL Thiếu pageurl Gửi URL đầy đủ, có https://
ERROR_CAPTCHA_UNSOLVABLE Giải thất bại Kiểm tra sitekey và pageurl có khớp trang thật không; thử gửi lại một lần

Mã lỗi đầy đủ hơn: hướng dẫn giải reCAPTCHA v2 — dùng chung cho mọi loại CAPTCHA trên CaptchaAI.


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

Tổng hợp nhanh những câu đội automation/QA hay hỏi nhất khi mới tích hợp Turnstile qua API CaptchaAI:

Giải Cloudflare Turnstile qua API mất bao lâu?

Dưới 10 giây trên phần lớn trang. Vòng lặp 40×5 giây trong code chỉ là dư địa an toàn.

Nếu task thường xuyên chạm mốc 40 vòng poll mà vẫn chưa có token, khả năng cao sitekey hoặc pageurl bạn gửi không khớp trang thật — xem mục kiểm tra 4 điều phía trên.

Sitekey Turnstile đổi liên tục, có phải bug không?

Không — một số trang cố tình phát sitekey mới mỗi lượt truy cập. Scrape lại trang trước mỗi lần gửi task, đừng lưu sitekey cố định.

Giải vài chục nghìn Turnstile mỗi ngày thì nên dùng plan nào?

CaptchaAI tính phí theo thread song song, không theo lượt giải — mỗi thread giải không giới hạn trong tháng. Khối lượng lớn thường bắt đầu ở ADVANCE ($90/tháng, 50 thread), nâng lên PREMIUM ($170/tháng, 100 thread) khi cần thêm concurrency.

Có thể gắn quy trình giải Turnstile này vào pipeline CI/CD không?

Được — code ở trên chỉ là các hàm Python/Node.js thuần, không phụ thuộc trình duyệt thật nên chạy tốt trong runner headless của các nền tảng CI phổ biến:

  • GitHub Actions
  • GitLab CI
  • Jenkins

Chỉ cần đưa CAPTCHAAI_KEY vào biến môi trường/secret của pipeline thay vì hard-code trong script.

API CaptchaAI có SDK cho ngôn ngữ nào ngoài Python và Node.js?

Có. Gói ví dụ đầy đủ của CaptchaAI cho luồng 4 bước này còn có:

  • Bản PHP
  • Bản Bash (dùng curl)

Phù hợp nếu backend của bạn không chạy trên Node hay Python.


Bước tiếp theo

Nắm chắc 4 bước ở trên là đủ để chạy production. Muốn hiểu sâu hơn cơ chế chấm điểm phía sau Turnstile để debug các ca khó, đọc thêm bài dưới đây:

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