← Quay lại blog

API JSON ẩn của trang web: cách tìm các điểm cuối nội bộ và tối ưu hóa lưu lượng truy cập của trình phân tích

Trang web tự trả dữ liệu cho chính nó dưới dạng JSON — và phản hồi này nhẹ hơn hàng chục lần so với trang HTML. Chúng ta sẽ phân tích từng bước, cách tìm endpoint nội bộ trong DevTools, tại sao cURL đã sao chép hoạt động, nhưng mã của bạn thì không, phải làm gì với các token và phân trang, và khi nào thì tốt hơn nên từ bỏ ý tưởng.

📅22 tháng 9, 2026
API JSON ẩn của trang web: cách tìm các điểm cuối nội bộ và tối ưu hóa lưu lượng truy cập của trình phân tích

Trình phân tích kéo 400 KB HTML cho tám trường mà trang web tự trả về trong phản hồi JSON 8 KB. Sự khác biệt năm mươi lần không phải là về "mã đẹp", mà là về hóa đơn cho các proxy cư trú, nơi bạn phải trả tiền cho mỗi gigabyte. Chúng ta sẽ phân tích cách tìm API nội bộ của trang web, điều gì cản trở việc lặp lại nó vào năm 2026, và khi nào nên từ bỏ ý tưởng này.

Tại sao cần tìm API ẩn nếu HTML đã được phân tích

Hầu hết các giao diện hiện đại — React, Vue, Angular, Next.js — đều tải khung của trang trước, sau đó kéo dữ liệu bằng các yêu cầu riêng biệt đến các điểm cuối của chính nó. Những điểm cuối này không được tài liệu hóa, nhưng chúng tồn tại, trả về JSON sạch và có thể truy cập mà không cần trình duyệt headless.

Bạn nhận được gì khi chuyển sang chúng:

  • Lưu lượng giảm đáng kể. Trong việc phân tích một trang sản phẩm điển hình, trang HTML nặng khoảng 400 KB cùng với đánh dấu, kiểu dáng và trình theo dõi, trong khi điểm cuối JSON tương ứng chỉ khoảng 8 KB, và có nhiều trường hơn: ID nội bộ, tồn kho, biến thể sản phẩm.
  • Không cần trình duyệt. Việc kết xuất JavaScript không còn, và cùng với nó — bộ nhớ, bộ xử lý và hàng chục yêu cầu bổ sung cho phông chữ và phân tích.
  • Dữ liệu đã được cấu trúc. Không có bộ chọn nào bị hỏng do thay đổi lớp CSS.
  • Ít yêu cầu hơn — ít lý do bị cấm hơn. Việc vẽ một trang danh mục trong trình duyệt là hàng chục lần truy cập vào trang web; cùng một lượng dữ liệu qua API — chỉ một lần.

Đối với dự án trên proxy cư trú, đây là sự tiết kiệm trực tiếp: giá được tính theo gigabyte, và việc chuyển từ kết xuất sang JSON thường làm giảm hóa đơn mạnh mẽ hơn bất kỳ thủ thuật nào với việc chặn hình ảnh. Chủ đề liên quan — cách giảm lưu lượng trình phân tích xuống 5 lần bằng các phương pháp khác.

Bước từng bước: cách tìm điểm cuối

  1. Đầu tiên hãy kiểm tra xem có API chính thức hay không. Hãy xem qua /developers, /api, /docs của trang web mục tiêu. API công khai được tài liệu hóa có phiên bản và cảnh báo về việc ngừng hỗ trợ — API riêng tư thay đổi một cách im lặng.
  2. Mở DevTools (F12) và chuyển đến tab Mạng, đảm bảo rằng ghi lại đã được bật.
  3. Bật bộ lọc Fetch/XHR. Nó sẽ loại bỏ hình ảnh, phông chữ và phân tích, chỉ để lại các yêu cầu dữ liệu.
  4. Xóa danh sách để loại bỏ tiếng ồn từ việc tải ban đầu.
  5. Kích hoạt dữ liệu cần thiết: cuộn qua kết quả, nhấn "trang tiếp theo", áp dụng bộ lọc, mở thẻ sản phẩm. Yêu cầu bạn quan tâm sẽ xuất hiện ngay khi hành động xảy ra.
  6. Tìm phản hồi với dữ liệu của bạn. Cách nhanh nhất — Ctrl+F trên bảng điều khiển Mạng: tìm giá trị duy nhất mà bạn thấy trên màn hình (mã sản phẩm, giá chính xác, một phần tên), và xem yêu cầu nào đã tạo ra nó.
  7. Sao chép yêu cầu hoàn toàn: nhấp chuột phải vào dòng → Sao chép → Sao chép dưới dạng cURL. Sau đó chuyển đổi thành mã qua curlconverter — như vậy bạn sẽ không mất bất kỳ tiêu đề nào.

Các đường dẫn đặc trưng mà bạn nên xem xét trước tiên: /api/, /v1/, /v2/, /search, /products, /listings, /graphql.

Trường hợp đặc biệt: các trang trên Next.js

Tại đây, dữ liệu thường không yêu cầu yêu cầu riêng biệt — chúng nằm ngay trong HTML. Trên Pages Router cũ, đó là khối __NEXT_DATA__. Trên App Router (Next.js 13 và mới hơn), dữ liệu cho việc hydrat hóa được phân bổ qua các cuộc gọi self.__next_f.push() trong một số nút script — đây là payload đã được tuần tự hóa của React Server Components. Việc phân tích nó bằng tay không dễ chịu: các khối liên kết với nhau thông qua các tiền tố $ và có thể bị cắt giữa dòng. Đối với Python, có thư viện nextflight, phân tích cả Flight-payload từ HTML và phản hồi RSC thô (yêu cầu với tiêu đề RSC: 1), và đề xuất tìm kiếm trong đó theo tên khóa, thay vì theo chỉ số mảng — như vậy trình phân tích có thể sống sót sau khi triển khai lại trang web.

Đảo ngược tham số: phân trang và bộ lọc

Điểm cuối đã tìm thấy hầu như luôn có tham số. Có ba sơ đồ:

  • Theo trang: ?page=3&per_page=20
  • Độ lệch và giới hạn: ?offset=40&limit=20
  • Con trỏ: ?after=<token>&limit=20 — mã thông báo của trang tiếp theo đến trong thân của phản hồi trước đó

Ba quy tắc giúp tiết kiệm hàng giờ gỡ lỗi:

  • Ngừng lại ở gói trống, thay vì số trang đã được tính trước: bộ đếm total trong các API riêng tư thường sai hơn mức mong muốn.
  • Kiểm tra kích thước thực tế của gói. Yêu cầu 100, nhận được 20 — có nghĩa là điểm cuối có giới hạn riêng của nó, và phép toán của bạn về các trang đã không còn chính xác.
  • Không truy cập vào trang 500. Phân trang sâu thường bị cắt bởi máy chủ; thay vào đó, hãy cắt lựa chọn bằng các bộ lọc — theo danh mục, theo khoảng giá, theo ngày.

Tại sao cURL từ trình duyệt hoạt động, nhưng mã của bạn thì không

Đây là điểm thất bại phổ biến nhất, và lý do gần như luôn là một: mất tiêu đề. cURL đã sao chép mang theo toàn bộ ngữ cảnh của yêu cầu, trong khi khách hàng tự viết thì không.

Những gì thường là bắt buộc:

  • Các tiêu đề tùy chỉnh với tiền tố X- — X-CSRF-Token, X-Requested-With: XMLHttpRequest và mọi loại X-*-Token mà frontend tự thêm vào. Nếu không có chúng, bạn sẽ nhận được phản hồi trong khoảng 400–500.
  • Referer — tiêu đề ngữ cảnh, được tạo ra bởi hành động của người dùng. Nhiều điểm cuối kiểm tra rằng yêu cầu "đến từ trang của chính nó".
  • Authorization: Bearer <JWT> — mã thông báo ngắn hạn, thường từ 15–60 phút. Việc mã hóa nó là vô nghĩa: cần phải biết cách nhận mã mới.
  • Cookie phiên — giữ chúng trong đối tượng phiên, chứ không sao chép bằng tay.
  • Content-Type Content-Type chính xác cho POST: application/json và application/x-www-form-urlencoded mã hóa thân theo cách khác nhau, và sự không khớp với loại đã công bố sẽ làm hỏng yêu cầu một cách im lặng.

Nơi tìm kiếm các mã thông báo nếu chúng không có trong cookie: trong mã nguồn HTML bên trong <script> (tìm kiếm theo giá trị đã biết qua Ctrl+F), trong các gói JavaScript, trong localStorage hoặc IndexedDB — tab Ứng dụng trong DevTools.

Các cạm bẫy mà bạn sẽ biết muộn

API riêng tư thay đổi mà không có cảnh báo. Nó không có phiên bản, không có cam kết tương thích và hỗ trợ: đội ngũ frontend đổi tên trường vào tối thứ Năm, và trình phân tích của bạn thu thập khoảng trống. Bảo vệ không phải là "bộ chọn đáng tin cậy", mà là kiểm soát cấu trúc: hãy kiểm tra rằng các trường bắt buộc có mặt và đúng loại; theo dõi tỷ lệ giá trị trống và số lượng bản ghi trong quá trình; bỏ qua các bản ghi bị hỏng, nhưng hãy nâng cao cảnh báo nếu tỷ lệ lỗi vượt quá 10%; lưu trữ các phản hồi thô để sau này có thể so sánh.

API đôi khi được bảo vệ chặt chẽ hơn cả trang. Điều này thường xảy ra: HTML được trả về một cách bình thường, trong khi /api/ có một anti-bot kiểm tra cả dấu vân tay TLS và sự kết hợp của các tiêu đề. Khi đó, việc tiết kiệm lưu lượng trở thành tăng tỷ lệ yêu cầu không thành công, và lợi ích bị tiêu tốn.

Các yêu cầu đã ký. Nếu trong các tham số có gì đó như sign, hash hoặc _s, frontend tính toán chữ ký trong JavaScript. Tái tạo nó là một dự án riêng biệt, và thường rẻ hơn để ở lại với HTML.

Giới hạn về tần suất. Các điểm cuối riêng tư không được thiết kế cho dòng chảy: giữ 1–2 yêu cầu mỗi giây, đặt thời gian chờ riêng cho kết nối và đọc (ví dụ: 5 và 30 giây), chỉ lặp lại các lỗi tạm thời — 429, 500, 502, 503, 504 — và không chạm vào 401 và 404. Độ trễ theo cấp số nhân với jitter là bắt buộc, nếu không tất cả các worker sẽ đi vào vòng thứ hai cùng một lúc. Chi tiết hơn — trong phân tích thời gian chờ và logic retry cho proxy.

Khung pháp lý. Các điểm cuối công khai không xác thực — một tình huống, truy cập vào tài khoản — hoàn toàn khác: việc đăng ký có nghĩa là chấp nhận thỏa thuận người dùng. Dữ liệu cá nhân thuộc về GDPR bất kể chúng dễ dàng như thế nào. Các sự kiện — giá cả, đặc điểm, sự hiện diện — không được bảo vệ bởi bản quyền, khác với văn bản và hình ảnh.

Khi nào nên ở lại với HTML

API ẩn không phải lúc nào cũng có lợi. Hãy ở lại với việc phân tích trang nếu:

  • trang web là máy chủ và không có API nội bộ nào cả;
  • điểm cuối yêu cầu chữ ký hoặc quay vòng mã thông báo — duy trì nó đắt hơn so với trang;
  • API có bảo vệ nghiêm ngặt hơn so với các trang công khai;
  • bạn cần kết quả cuối cùng mà frontend thu thập từ nhiều nguồn;
  • bạn quản lý hàng chục trang web: một dây chuyền HTML duy nhất mở rộng tốt hơn so với một sở thú API riêng tư với những kỳ quặc riêng.

Loại proxy nào nên chọn cho việc phân tích API

Chuyển sang JSON thay đổi cách tính toán, vì điểm nghẽn chuyển sang: lưu lượng trở nên ít, trong khi yêu cầu về chất lượng IP và độ ổn định của phiên tăng lên.

  • Điểm cuối công khai không cần xác thực và không có anti-bot. Ở đây đủ proxy trung tâm dữ liệu: khối lượng dữ liệu nhỏ, không cần phải trả tiền cho proxy cư trú.
  • Điểm cuối sau anti-bot hoặc gắn với phiên. Cần proxy cư trú với phiên dính: mã thông báo, cookie và IP phải khớp trong toàn bộ chuỗi, nếu không máy chủ sẽ xóa phiên ở yêu cầu thứ hai. Trong khi đó, hóa đơn sẽ vẫn khiêm tốn — gigabyte trong chế độ JSON được tiêu thụ chậm.
  • Dữ liệu từ ứng dụng di động. Nếu phiên bản web bị đóng, và ứng dụng trả về cùng một cách dễ dàng hơn, các điểm cuối được tìm kiếm thông qua việc chặn lưu lượng — đây là một quy trình riêng biệt, được phân tích trong bài viết về tìm kiếm API ẩn của ứng dụng di động qua mitmproxy.

Tóm tắt

Hai mươi phút trong DevTools thường thay thế cho nhiều ngày vật lộn với trình duyệt headless: bộ lọc Fetch/XHR, tìm kiếm theo giá trị hiển thị, Sao chép dưới dạng cURL — và bạn đã có yêu cầu làm việc trong tay. Tiếp theo là giải quyết các chi tiết: chuyển tất cả các tiêu đề, phân tích sơ đồ phân trang, đặt xác thực phản hồi và đánh giá một cách tỉnh táo xem điểm cuối có được bảo vệ nghiêm ngặt hơn so với chính trang hay không. Ở nơi mà API riêng tư hoạt động, nó giảm cả khối lượng lưu lượng và số lượng yêu cầu — tức là ngay lập tức giảm chi phí proxy và khả năng bị cấm.