So Sánh

Phiên cố định và phiên luân phiên: Chiến lược proxy tốt nhất cho CAPTCHA

Câu trả lời ngắn: luồng nhiều bước trên cùng một trạng thái đăng nhập thì dùng phiên cố định; luồng chỉ đọc từng trang độc lập thì dùng luân phiên. Chọn sai không hỏng request ngay — nó âm thầm đẩy tỷ lệ CAPTCHA lên và khiến token bị từ chối ở bước cuối.

Thứ tự bên dưới đúng như lúc ra quyết định:

  • chọn chế độ theo loại luồng;
  • hiểu vì sao token gắn với IP;
  • ráp code Python, Node.js;
  • chỉnh TTL, xử lý sự cố.

Ma trận quyết định: chọn chế độ trong 30 giây

Luồng xử lý Nên dùng Lý do
Đăng nhập / đăng ký Cố định Token gắn với IP đã giải
Kiểm thử checkout Cố định Cookie cần cùng IP
Gửi biểu mẫu có CAPTCHA Cố định Ràng buộc token – IP
Thu thập danh mục sản phẩm Luân phiên Phân tán tải request
Đọc kết quả tìm kiếm Luân phiên Tránh giới hạn tần suất

Dấu hiệu chọn sai:

  • token giải xong vẫn bị từ chối ở bước submit;
  • cookie đăng nhập mất giữa hai bước;
  • job chỉ đọc trang công khai mà tỷ lệ CAPTCHA vẫn leo thang.

Pipeline thật thường cần cả hai — xem chiến lược lai.


Hai chế độ khác nhau ở chỗ nào

Phiên cố định giữ một IP trong cửa sổ TTL bạn đặt (thường 1–30 phút); luân phiên cấp IP mới mỗi request.

STICKY SESSION:
  Request 1 ──▶ IP: 192.168.1.50 ──▶ site.com/login
  Request 2 ──▶ IP: 192.168.1.50 ──▶ site.com/dashboard
  Request 3 ──▶ IP: 192.168.1.50 ──▶ site.com/account
  (Same IP for all requests in the session window)

ROTATING SESSION:
  Request 1 ──▶ IP: 192.168.1.50 ──▶ site.com/page1
  Request 2 ──▶ IP: 10.0.0.77   ──▶ site.com/page2
  Request 3 ──▶ IP: 172.16.5.22 ──▶ site.com/page3
  (Different IP per request)

Khác biệt nhỏ, nhưng quyết định token còn hợp lệ hay không:

Yếu tố Phiên cố định Phiên luân phiên
IP mỗi request Giữ nguyên 1–30 phút Mới mỗi lần
Nhất quán phiên Cao Không có
Tỷ lệ CAPTCHA (nhiều bước) Thấp (5–10%) Cao (30–50%)
Tỷ lệ CAPTCHA (trang đơn) Trung bình (10–20%) Thấp (5–10%)
Độ tin cậy token Cao hơn — cùng IP Nguy cơ lệch IP
Tốc độ Nhanh (tái dùng kết nối) Chậm hơn
Rủi ro bị chặn Cao hơn nếu IP bị gắn cờ Thấp
Phù hợp với Đăng nhập, checkout Thu thập dữ liệu

Khi nào phiên cố định thắng

Luồng nhiều bước: token gắn với IP

Token CAPTCHA gắn với ngữ cảnh phiên. IP đổi giữa lúc giải và lúc submit thì server có thể từ chối token — mất cả thời gian lẫn thread.

import requests
import time

CAPTCHAAI_KEY = "YOUR_API_KEY"
CAPTCHAAI_URL = "https://ocr.captchaai.com"

# Sticky session: same IP for the entire login flow
STICKY_PROXY = {
    "http": "http://user-session-abc123:[email protected]:5000",
    "https": "http://user-session-abc123:[email protected]:5000",
}

session = requests.Session()
session.proxies = STICKY_PROXY
session.headers.update({
    "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) "
    "AppleWebKit/537.36 Chrome/126.0.0.0 Safari/537.36",
})

def login_with_captcha(url, sitekey, username, password):
    """Full login flow — MUST use same IP throughout."""
    # Step 1: Load login page (IP: 192.168.1.50)
    session.get(url)

    # Step 2: Solve CAPTCHA (solved against IP: 192.168.1.50)
    token = solve_recaptcha(sitekey, url)

    # Step 3: Submit login (MUST be IP: 192.168.1.50)
    resp = session.post(url, data={
        "username": username,
        "password": password,
        "g-recaptcha-response": token,
    })

    return resp.status_code == 200

def solve_recaptcha(sitekey, pageurl):
    resp = requests.post(f"{CAPTCHAAI_URL}/in.php", data={
        "key": CAPTCHAAI_KEY,
        "method": "userrecaptcha",
        "googlekey": sitekey,
        "pageurl": pageurl,
        "json": 1,
    })
    task_id = resp.json()["request"]

    for _ in range(60):
        time.sleep(5)
        result = requests.get(f"{CAPTCHAAI_URL}/res.php", params={
            "key": CAPTCHAAI_KEY, "action": "get",
            "id": task_id, "json": 1,
        })
        data = result.json()
        if data["request"] != "CAPCHA_NOT_READY":
            return data["request"]

    raise TimeoutError("CAPTCHA solve timeout")

Cả ba bước — mở trang, giải, submit — phải qua một IP.

Vì sao tính nhất quán IP lại quan trọng

Sticky session:

  1. Browser loads page    → IP: 5.5.5.5
  2. CAPTCHA solved        → Token bound to session
  3. Form submitted        → IP: 5.5.5.5 ✅ Token accepted

Rotating session:

  1. Browser loads page    → IP: 5.5.5.5
  2. CAPTCHA solved        → Token bound to session
  3. Form submitted        → IP: 9.9.9.9 ❌ Token may be rejected

Khi nào phiên luân phiên thắng

Thu thập dữ liệu số lượng lớn

Mỗi trang là request độc lập, không có trạng thái cần giữ; trải qua nhiều IP giúp giảm mật độ truy cập mỗi IP.

Ví dụ quen ở Việt Nam: một team product tại TP.HCM theo dõi giá niêm yết công khai cho chính danh mục hàng của họ trên Shopee, Lazada và Tiki. Vài trăm URL, mỗi URL đọc một lần mỗi giờ, không cần đăng nhập — đúng việc mà luân phiên xử lý gọn nhất. Ghi log tối thiểu, không giữ dữ liệu cá nhân thừa; Nghị định 13/2023/NĐ-CP là lý do thực tế.

import concurrent.futures

ROTATING_PROXY = {
    "http": "http://user:[email protected]:5000",
    "https": "http://user:[email protected]:5000",
}

def scrape_page(url):
    """Each request gets a fresh IP automatically."""
    resp = requests.get(
        url,
        proxies=ROTATING_PROXY,
        headers={"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64)"},
        timeout=30,
    )
    if resp.status_code == 200:
        return url, resp.text
    return url, None

urls = [f"https://example.com/products?page={i}" for i in range(1, 501)]

with concurrent.futures.ThreadPoolExecutor(max_workers=10) as pool:
    results = list(pool.map(scrape_page, urls))
    success = sum(1 for _, html in results if html)
    print(f"Scraped: {success}/{len(urls)}")

Đọc kết quả tìm kiếm cũng vậy: công cụ tìm kiếm đếm truy vấn theo IP, luân phiên tránh trần giới hạn tần suất.

def scrape_search(query, pages=10):
    results = []
    for page in range(pages):
        # Each request → new IP
        resp = requests.get(
            "https://search-engine.example.com/search",
            params={"q": query, "start": page * 10},
            proxies=ROTATING_PROXY,
            timeout=20,
        )
        results.append(resp.text)
        time.sleep(2)
    return results

Chiến lược lai: dùng cả hai trong một pipeline

Để lớp quản lý proxy tự chọn: có đăng nhập thì cấp phiên cố định kèm session ID, còn lại luân phiên.

class HybridProxyManager:
    """Sticky for multi-step flows, rotating for single requests."""

    def __init__(self, provider_host, username, password, port=5000):
        self.host = provider_host
        self.username = username
        self.password = password
        self.port = port

    def get_rotating_proxy(self):
        return {
            "http": f"http://{self.username}:{self.password}@{self.host}:{self.port}",
            "https": f"http://{self.username}:{self.password}@{self.host}:{self.port}",
        }

    def get_sticky_proxy(self, session_id, duration_min=10):
        sticky_user = f"{self.username}-session-{session_id}-ttl-{duration_min}"
        return {
            "http": f"http://{sticky_user}:{self.password}@{self.host}:{self.port}",
            "https": f"http://{sticky_user}:{self.password}@{self.host}:{self.port}",
        }

proxy_mgr = HybridProxyManager("proxy.example.com", "user", "pass")

def scrape_with_auto_strategy(url, needs_login=False):
    if needs_login:
        # Multi-step → sticky
        import uuid
        session_id = uuid.uuid4().hex[:8]
        proxy = proxy_mgr.get_sticky_proxy(session_id)
    else:
        # Single page → rotating
        proxy = proxy_mgr.get_rotating_proxy()

    return requests.get(url, proxies=proxy, timeout=30)

Mọi quyết định nằm một chỗ, không rải rẽ nhánh khắp code.


Triển khai bằng Node.js

Cùng logic bằng Node.js: chọn chế độ, giữ IP xuyên suốt luồng đăng nhập, gửi task tới in.php rồi polling res.php.

const axios = require("axios");

const CAPTCHAAI_KEY = "YOUR_API_KEY";
const PROXY_HOST = "proxy.example.com";
const PROXY_PORT = 5000;

function getProxy(mode, sessionId = null) {
  const user =
    mode === "sticky" ? `user-session-${sessionId}` : "user";

  return {
    proxy: {
      host: PROXY_HOST,
      port: PROXY_PORT,
      auth: { username: user, password: "pass" },
    },
  };
}

// Rotating: bulk scrape
async function scrapePages(urls) {
  const results = [];
  for (const url of urls) {
    const config = getProxy("rotating");
    const resp = await axios.get(url, { ...config, timeout: 30000 });
    results.push({ url, data: resp.data });
  }
  return results;
}

// Sticky: login flow
async function loginFlow(loginUrl, sitekey, credentials) {
  const sessionId = Date.now().toString(36);
  const config = getProxy("sticky", sessionId);

  // Step 1: Load page
  await axios.get(loginUrl, config);

  // Step 2: Solve CAPTCHA
  const submitResp = await axios.post(
    "https://ocr.captchaai.com/in.php",
    null,
    {
      params: {
        key: CAPTCHAAI_KEY,
        method: "userrecaptcha",
        googlekey: sitekey,
        pageurl: loginUrl,
        json: 1,
      },
    }
  );
  const taskId = submitResp.data.request;

  let token;
  for (let i = 0; i < 60; i++) {
    await new Promise((r) => setTimeout(r, 5000));
    const res = await axios.get("https://ocr.captchaai.com/res.php", {
      params: { key: CAPTCHAAI_KEY, action: "get", id: taskId, json: 1 },
    });
    if (res.data.request !== "CAPCHA_NOT_READY") {
      token = res.data.request;
      break;
    }
  }

  // Step 3: Submit with same IP
  return axios.post(
    loginUrl,
    {
      ...credentials,
      "g-recaptcha-response": token,
    },
    config
  );
}

Đặt TTL cho phiên cố định

TTL ngắn quá thì phiên hết hạn giữa chừng; dài quá thì request dồn vào một IP.

Thời lượng Phù hợp với Đánh đổi
1 phút Gửi một biểu mẫu Dễ hết hạn giữa luồng
5 phút Đăng nhập + vài thao tác Cân bằng tốt nhất
10 phút Luồng nhiều trang Rủi ro chặn mức vừa
30–60 phút Phiên kéo dài Rủi ro chặn cao nhất

Cách chọn:

  1. Đo thời gian thật của luồng, tính cả lúc giải CAPTCHA.
  2. Nhân đôi, làm tròn lên mức TTL proxy hỗ trợ.
  3. Luồng đăng nhập 40 giây thì TTL 5 phút là dư.

Chi phí thật sự nằm ở tỷ lệ CAPTCHA

Proxy tính theo GB hoặc số request, nên hai chế độ gần như cùng giá. Chênh lệch nằm chỗ khác: sai chế độ làm tỷ lệ CAPTCHA tăng, kéo theo nhu cầu thread.

CaptchaAI tính phí theo thread (luồng giải đồng thời), không theo lần giải; số lần giải trong tháng không giới hạn. Giá bằng USD:

  • BASIC ($15/tháng, 5 thread) — vài luồng đăng nhập QA;
  • STANDARD ($30/tháng, 15 thread) — khoảng 15 worker song song;
  • ADVANCE ($90/tháng, 50 thread) — quy mô agency.

CaptchaAI giải reCAPTCHA v2/v3 (kể cả Enterprise), Cloudflare Turnstile và Challenge, GeeTest v3, CAPTCHA ảnh/OCR, grid image, BLS. hCaptcha và FunCaptcha (Arkose Labs) chưa được hỗ trợ; GeeTest v4 sắp ra mắt; CaptchaFox, Friendly Captcha, Lemin ở giai đoạn beta.


Khắc phục sự cố thường gặp

Bốn triệu chứng hay gặp khi đặt sai chế độ:

Triệu chứng Nguyên nhân Cách xử lý
Token bị từ chối dù đã giải xong IP đổi giữa lúc giải và submit Chuyển luồng sang phiên cố định
Tỷ lệ CAPTCHA cao ở trang đơn Một IP gánh quá nhiều trang Chuyển sang phiên luân phiên
Mất cookie phiên giữa chừng TTL hết hạn sớm Tăng TTL hoặc rút ngắn luồng
IP cố định bị chặn Request dồn vào một IP bị gắn cờ Giảm TTL, giãn thời gian request

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

Nên bắt đầu bằng chế độ nào khi chưa đo được gì?

Phiên luân phiên, trừ khi luồng có đăng nhập. Chuyển sang cố định khi thấy một trong hai dấu hiệu:

  • token bị từ chối ở bước submit;
  • cookie phiên không sống qua bước thứ hai.

TTL bao nhiêu là hợp lý cho luồng đăng nhập có CAPTCHA?

5 phút, rồi đo luồng thật và chỉnh lại.

CaptchaAI tính tiền theo số CAPTCHA đã giải hay theo thread?

Theo thread, số lần giải không giới hạn. Đổi chế độ proxy chỉ ảnh hưởng số thread bạn cần, không phải sửa code tích hợp: phần gửi task tới in.php và polling res.php giữ nguyên.

Cấu hình phiên cố định với nhà cung cấp proxy như thế nào?

Phần lớn nhúng session ID vào username, dạng user-session-abc123. Định dạng chính xác xem tài liệu từng bên:


Đọc tiếp

Ba bài bổ trợ cho quyết định ở trên:


Chọn chế độ phiên theo luồng, còn phần giải CAPTCHA để API lo — lấy API key CaptchaAI và chạy thử ví dụ Python ở trên.

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