← Tất cả bài viết

Bên trong Browser Profile: `unblocker: true` thực sự làm những gì

Một cờ bật ba công tắc: các header trình duyệt thực, một chữ ký kết nối tương thích, và tự động giải nén cho gzip cùng brotli. Đây là cách nó hoạt động và lý do vì sao.

Hầu hết các trình thu thập dữ liệu (scraper) đều thất bại trước khi một header đơn lẻ kịp được đọc.

Máy chủ xem xét chữ ký ở cấp độ kết nối mà client của bạn gửi đi và quyết định xem bạn là một trình duyệt thực sự hay một thư viện client đang giả lập. Python requests, net/http của Go, curl thuần túy: tất cả đều để lộ một fingerprint đặc trưng ngay thời điểm bắt đầu bắt tay kết nối. Các trang web chú trọng bảo mật (Datadome, Akamai, Imperva, hay giải pháp quản lý của Cloudflare) sẽ ngắt kết nối hoặc trả về trang thử thách trước khi chuỗi User-Agent của bạn có bất kỳ tác dụng nào.

Đó chính là vấn đề mà unblocker: true giải quyết trên FourA. Trong tháng qua, chúng tôi đã hoàn thiện các thành phần cốt lõi để tính năng này hoạt động ổn định.

Điểm mới

unblocker: true là một cờ đơn giản trên bất kỳ lệnh gọi /api/single nào. Khi bật cờ này, chúng tôi thực hiện ba việc: chèn bộ header của trình duyệt, gửi request qua lớp transport khớp chính xác với những gì trình duyệt thực tế truyền đi, và giải nén bất kỳ định dạng nào máy chủ trả về (gzip, brotli, deflate). Hai tính năng đầu tiên đã có từ bản beta. Tính năng thứ ba (tự động giải nén brotli) đã được triển khai vào ngày 25 tháng 3, và cơ chế ghim phiên bản được áp dụng vào ngày hôm sau nhằm đảm bảo header và transport luôn đồng bộ tuyệt đối.

Cách hoạt động

Cấu trúc của một request sẽ như sau:

curl -X POST "https://api.foura.ai/api/single" \
  -H "Content-Type: application/json" \
  -H "x-api-key: YOUR_API_KEY" \
  -d '{
    "url": "https://example.com/products",
    "method": "GET",
    "unblocker": true
  }'

Có ba lớp hoạt động bên dưới.

Header injection. Chúng tôi thiết lập toàn bộ gói browser header: User-Agent, Sec-Ch-Ua, Sec-Ch-Ua-Platform, Sec-Fetch-Site, Sec-Fetch-Mode, Sec-Fetch-Dest, Accept, Accept-Language, và Accept-Encoding. Thứ tự rất quan trọng. Trình duyệt thực tế gửi các header này theo một trình tự cụ thể, và các thư viện phát hiện bot sẽ kiểm tra điều đó.

Connection signature. Tầng transport của chúng tôi khớp chính xác cấu trúc ở cấp độ byte của một phiên trình duyệt mới nhất: cùng thứ tự extension, cùng mức độ ưu tiên cipher, cùng các đặc điểm handshake riêng biệt. Thư viện cURL tiêu chuẩn, Python requests, và net/http của Go tạo ra các signature bị hệ thống tự động gắn cờ chỉ trong vài mili-giây trên hạ tầng được bảo vệ.

Auto-decompression. Khi bật unblocker, chúng tôi đặt Accept-Encoding thành gzip, deflate, br và transport sẽ tự động giải nén body. Bạn nhận lại một chuỗi đã giải mã (hoặc một Buffer nếu truyền returnBuffer: true). Không cần xử lý brotli thủ công, không bị lệch giữa header và body khi một trang web chọn deflate thay vì gzip.

Tại sao việc ghim phiên bản lại quan trọng

Connection signature bị khóa chặt theo phiên bản. Chi tiết cấp độ truyền dẫn (wire-level) của trình duyệt trong tháng này sẽ khác tháng trước, và một trang web thu thập fingerprint cẩn thận sẽ nhận ra sự sai lệch đó. Chúng tôi ghim các thành phần biến động lại với nhau để header, navigator object, và connection signature đều báo cáo cùng một phiên bản trình duyệt.

Nếu điều đó nghe có vẻ phức tạp, thì đúng là như vậy. Chúng tôi từng gặp sự cố không khớp trong đợt chuyển đổi monorepo hồi tháng 3, khi một thành phần tự động cập nhật và phần còn lại bị lệch pha. Cách khắc phục gồm hai commit: ghim thành phần biến động đó lại, và không bao giờ tin tưởng trình quản lý gói sẽ tự đồng bộ mọi thứ cho bạn.

Tác động thực tế

Trong các bài kiểm tra nội bộ đối với những trang web có kiểm tra danh tính người gửi request (tài chính, du lịch, thương mại điện tử lớn), sự khác biệt giữa unblocker: false và unblocker: true chính là sự khác biệt giữa một trang challenge và mã trạng thái 200. Một HTTP client thông thường thường nhận mã 403 ngay lần đầu tiên. Cùng một URL đó nhưng dùng unblocker: true sẽ lấy được nội dung trang, vì request trông giống hệt trình duyệt mà nó khai báo.

Tuy nhiên, với các trang web không thu thập fingerprint (hầu hết API công khai, template CMS cũ, bất kỳ hệ thống nào chỉ giới hạn theo IP rate limit), việc tắt unblocker là hoàn toàn bình thường và giúp tiết kiệm vài mili-giây đàm phán kết nối. Hãy sử dụng nó ở những nơi bạn thực sự cần.

Dành cho người dùng nâng cao

Một vài mô hình triển khai đáng lưu ý.

Kết hợp unblocker với một residential proxy khi mục tiêu kiểm tra cả uy tín IP. IP trung tâm dữ liệu đi kèm một connection signature hoàn hảo vẫn sẽ bị gắn cờ nếu nằm trong các ASN mà trang web đã đưa vào danh sách đen. Proxy endpoint của chúng tôi (/api/proxy) tự động xoay vòng theo tên miền mục tiêu, vì vậy việc thêm "proxy": "residential" vào request thường là đủ.

Bỏ qua unblocker khi gọi các JSON API không quan tâm đến trình duyệt. Các header bổ sung đôi khi lại trông đáng ngờ đối với một API vốn chỉ mong đợi một client dạng chương trình, ví dụ như một backend gọi đến microservice nội bộ của chính nó.

Nếu trang web kiểm tra khách truy cập bằng JavaScript trước khi hiển thị trang, riêng unblocker sẽ không đủ. Bạn cần endpoint trình duyệt, vốn chạy JavaScript của trang trong một trình duyệt đầy đủ. Đó là một sản phẩm khác với mức tính credit khác, và chúng tôi đã trình bày chi tiết trong Browser Tasks: How to Scrape JavaScript-Heavy Sites.

Và bạn có thể kết hợp unblocker với khối validate để từ chối các response về mặt kỹ thuật trả về mã 200 nhưng lại chứa trang thử thách:

{
  "url": "https://example.com/products",
  "method": "GET",
  "unblocker": true,
  "validate": {
    "data": { "fail": ["captcha", "Access Denied"] }
  }
}

Điều này giúp chuyển các lỗi âm thầm thành lỗi đã được phân loại, điều rất quan trọng cho việc theo dõi tỷ lệ thành công trong dashboard của bạn.

Kế hoạch tiếp theo

Các trình duyệt phát hành bản stable mới mỗi bốn tuần. Chúng tôi nâng cấp stack của mình để tương thích. Bạn không cần phải thay đổi bất kỳ điều gì ở phía mình: unblocker: true luôn trỏ đến phiên bản trình duyệt mà chúng tôi đã kiểm thử end-to-end.

Những thử thách phức tạp hơn vẫn đang ở phía trước. Các kiểm tra HTTP/3 đã bắt đầu xuất hiện trên các trang web lớn hơn, QUIC transport khó mô phỏng chính xác hơn transport cũ, và quá trình chuyển đổi từ các gói header tĩnh sang giả lập thực sự động đang bắt đầu. Các trang web được bảo vệ đã chuyển sang kiểm tra thứ tự frame HTTP/2, và khoảng cách giữa "thư viện trông giống trình duyệt" và "trình duyệt thực sự" sẽ thu hẹp dần từ cả hai phía. Chúng tôi sẽ viết bài chi tiết khi phát hành tính năng này.