Kết nối Puppeteer Node.js với AdsPower qua Local API
Puppeteer là lựa chọn quen thuộc với người viết automation bằng Node.js, đặc biệt khi công việc đã sẵn có trong hệ sinh thái JavaScript. Bài này hướng dẫn cách gắn Puppeteer vào một hồ sơ AdsPower đang chạy thay vì để Puppeteer tự mở trình duyệt riêng.
Vì sao không gọi puppeteer.launch() như thông thường?
Cách dùng Puppeteer phổ biến nhất là puppeteer.launch() — Puppeteer tự tải và khởi động một bản Chromium do chính nó quản lý. Nếu làm vậy, bạn có một trình duyệt hoàn toàn tách biệt với AdsPower: không dấu vân tay riêng, không proxy đã cấu hình, không cookie của hồ sơ. Toàn bộ giá trị của AdsPower (cách ly hồ sơ, dấu vân tay riêng biệt) sẽ bị bỏ qua.
Thay vào đó, cần dùng puppeteer.connect() — hàm này cho phép Puppeteer gắn vào một trình duyệt Chromium đã đang chạy sẵn ở nơi khác, đúng với tình huống AdsPower đã khởi động SunBrowser cho hồ sơ đó trước rồi.
Điều kiện cần trước khi bắt đầu
- Tài khoản AdsPower ở bậc Professional trở lên.
- Ứng dụng AdsPower đang mở và đăng nhập trên máy chạy script.
- Đã cài
puppeteercho Node.js (npm install puppeteer). - Hồ sơ dùng nhân SunBrowser (Chromium) — Puppeteer không điều khiển được FlowerBrowser (Firefox).
Luồng kết nối tổng quát
Bước 1: Gọi Local API để mở hồ sơ
Gọi endpoint mở hồ sơ theo tài liệu Postman chính hãng (documenter.getpostman.com/view/45822952/2sB34hEzQH). Phản hồi trả về thông tin kết nối của trình duyệt vừa mở. Ví dụ dưới đây dùng tên biến giữ chỗ, không phải tên trường thật của AdsPower:
const fetch = require("node-fetch"); // hoặc dùng fetch có sẵn ở Node.js mới
// Thay URL bên dưới bằng đúng endpoint mở hồ sơ trong tài liệu chính hãng.
const res = await fetch(
"http://<local-api-host>:<port>/<endpoint-mo-ho-so-theo-tai-lieu>?profile_id=ID_HO_SO_CAN_MO"
);
const data = await res.json();
// Tên trường thật lấy theo tài liệu Postman — đây là biến giữ chỗ minh hoạ.
const browserURL = data.giu_cho_dia_chi_ket_noi; // ví dụ dạng "http://127.0.0.1:9222"
Bước 2: Gắn Puppeteer vào trình duyệt đang chạy
const puppeteer = require("puppeteer");
const browser = await puppeteer.connect({
browserURL, // lấy từ bước 1, đây là cơ chế chuẩn của Puppeteer
defaultViewport: null,
});
const pages = await browser.pages();
const page = pages[0] ?? (await browser.newPage());
await page.goto("https://example.com");
console.log(await page.title());
Nếu Local API trả về địa chỉ WebSocket thay vì địa chỉ HTTP, dùng tuỳ chọn tương ứng của Puppeteer:
const browser = await puppeteer.connect({
browserWSEndpoint: browserWSEndpointTuLocalAPI,
});
Cả browserURL và browserWSEndpoint đều là tham số hợp lệ của Puppeteer — chọn tham số nào phụ thuộc vào việc Local API của AdsPower trả về dạng địa chỉ HTTP hay WebSocket trong phản hồi thật, xem chi tiết trong tài liệu Postman.
Bước 3: Thao tác bình thường trên page
Sau khi gắn thành công, mọi API quen thuộc của Puppeteer (page.click(), page.type(), page.waitForSelector(), page.evaluate()…) dùng bình thường như khi Puppeteer tự mở trình duyệt.
Bước 4: Ngắt kết nối đúng cách khi xong việc
Dùng browser.disconnect() thay vì browser.close() khi xong việc, vì close() sẽ đóng hẳn tiến trình trình duyệt còn disconnect() chỉ ngắt liên kết của script với trình duyệt, để AdsPower tiếp tục quản lý vòng đời của hồ sơ đó. Sau đó gọi Local API để đóng hồ sơ đúng cách theo endpoint tương ứng trong tài liệu, để AdsPower cập nhật đúng trạng thái hồ sơ.
Những lỗi thường gặp
- Gọi nhầm
browser.close(): khiến hồ sơ đóng đột ngột không qua Local API, có thể để lại trạng thái hồ sơ không đồng bộ trên giao diện AdsPower. - Puppeteer tự tải Chromium riêng dù đã dùng
connect(): kiểm tra lại đã import đúng cáchconnect()thay vì vô tình gọilaunch()ở đâu đó trong code. - Chạy nhiều script song song mở nhiều hồ sơ cùng lúc: mỗi lệnh gọi Local API để mở hồ sơ đều tính vào hạn mức tốc độ gọi theo bậc giá. Xem cách xử lý tại bài xử lý khi chạm trần giới hạn tốc độ gọi API.
So với Selenium và Playwright
Nguyên lý gắn vào địa chỉ gỡ lỗi từ Local API là chung, chỉ khác cú pháp gọi của từng framework. Nếu bạn cần chạy nhiều ngữ cảnh trình duyệt song song với API hiện đại hơn, xem thêm bài kết nối Playwright với AdsPower; nếu quen Python hơn Node.js, xem bài kết nối Selenium Python với AdsPower.
Tài liệu tham khảo chính xác
Tên endpoint, tham số truyền vào và cấu trúc JSON phản hồi thật của Local API nằm trong tài liệu Postman chính hãng tại documenter.getpostman.com/view/45822952/2sB34hEzQH. Luôn đối chiếu tên trường thật trước khi đưa vào code chạy thật. Tìm hiểu khái niệm nền tảng tại bài API cục bộ AdsPower là gì, và bậc giá cần có tại trang AdsPower.
Câu hỏi thường gặp
Vì sao dùng puppeteer.connect() thay vì puppeteer.launch()?
puppeteer.launch() luôn khởi động một trình duyệt Chromium hoàn toàn mới do Puppeteer tự quản lý, không liên quan gì đến hồ sơ AdsPower. puppeteer.connect() cho phép gắn vào một trình duyệt đã đang chạy sẵn — đúng với tình huống AdsPower đã mở hồ sơ trước đó qua Local API.
Nên dùng browserURL hay browserWSEndpoint?
Cả hai đều là tuỳ chọn hợp lệ của Puppeteer để kết nối vào trình duyệt đang chạy. browserURL dùng địa chỉ HTTP của giao thức gỡ lỗi, browserWSEndpoint dùng thẳng địa chỉ WebSocket. Tuỳ Local API của AdsPower trả về dạng nào trong phản hồi mà chọn tham số tương ứng — xem cấu trúc phản hồi thật trong tài liệu Postman chính hãng.
Cần gói AdsPower nào để dùng được cách này?
Tối thiểu bậc Professional vì Local API không có ở gói Free. Xem bảng bậc giá và giới hạn tốc độ gọi tại bài API cục bộ AdsPower là gì.
Có cần cài Chromium riêng cho Puppeteer không?
Không cần. Khi dùng puppeteer.connect() để gắn vào trình duyệt đã chạy sẵn, Puppeteer không tự tải hay khởi động bản Chromium đi kèm của nó — trình duyệt thực tế đang chạy là SunBrowser do AdsPower khởi động.
Chạy song song nhiều hồ sơ bằng Puppeteer có giới hạn gì không?
Mỗi lần gọi Local API để mở một hồ sơ mới đều tính vào giới hạn tốc độ gọi theo bậc giá (120/300/600 lần mỗi phút). Mở song song nhiều hồ sơ cùng lúc cần rải đều các lệnh gọi API, xem cách xử lý tại bài xử lý khi chạm trần giới hạn tốc độ gọi API AdsPower.