Hướng dẫn
App giữ trình duyệt
Gắn tài khoản trong app của bạn với hồ sơ, giữ trình duyệt của hồ sơ trong lúc code làm việc, gia hạn, nhả mà không đóng trình duyệt và theo dõi sự kiện phiên.
Một app làm việc với nhiều tài khoản — đăng bài, kiểm tra hộp thư, thu thập dữ liệu — cần ba điều từ Browlix: hồ sơ nào thuộc tài khoản nào, một trình duyệt dùng được mà không ai giành mất giữa chừng, và cách nhả ra mà không bỏ phí trình duyệt đang mở cho việc kế tiếp. Liên kết (binding) và lượt giữ (hold) làm đúng việc đó, qua cùng API, công cụ MCP, SDK và quyền như mọi thứ khác.
Một chương trình hoàn chỉnh làm tất cả việc này — và phục hồi sau mất kết nối, khởi động lại — là app mẫu.
Gắn tài khoản với hồ sơ
Một liên kết nói rằng "tài khoản acc-42 của app fb-poster dùng hồ sơ này". Liên kết không bao giờ chứa mật khẩu, cookie hay token — trạng thái đăng nhập đã nằm trong hồ sơ.
const b = await bx.call("bindings.create", {
body: { app_id: "fb-poster", external_account_id: "acc-42", profile_id: profileId, label: "Shop page" },
});- Mỗi cặp (
app_id,external_account_id) chỉ có một liên kết. Tạo lần hai trảCONFLICTkèmbinding_idđang có; muốn đổi hồ sơ thì dùngbindings.update. bindings.updatevàbindings.deletecầnrevisionbạn đọc gần nhất, để hai công cụ không ghi đè nhau.metadatatối đa 4 KiB dữ liệu của riêng bạn. Khoá trông giống thông tin đăng nhập (password,token,cookie,secret,otp,auth,api_key) bị từ chối.bindings.listtrả từng liên kết kèm phiên đang chạy của hồ sơ và ai đang giữ.
Tạo, sửa, xoá liên kết cần quyền profile.edit; đọc cần profile.read. Phạm vi nhóm vẫn áp dụng: khoá của thành viên chỉ thấy vài nhóm thì chỉ thấy liên kết của các nhóm đó.
Giữ trình duyệt
sessions.acquire mở hồ sơ trên một máy phù hợp — hoặc dùng lại trình duyệt nếu nó còn mở và rảnh — rồi trao cho app của bạn một lượt giữ.
const hold = await bx.acquireSession({
appId: "fb-poster",
externalAccountId: "acc-42",
holderRef: "poster-worker-3", // tên cố định của worker này
ttlSeconds: 120, // phải gia hạn trong khoảng này
keepWarmSeconds: 300, // giữ mở chừng này sau khi nhả
wait: true, // trả về khi trình duyệt sẵn sàng
onLost: () => abortCurrentJob(), // đã có lượt giữ mới hơn, hoặc phiên đã kết thúc
});
const a = await bx.attach(hold.sessionId);
// … điều khiển trang bằng Playwright (xem Gắn Playwright)
await hold.detach();Gửi profile_id thay cho app_id + external_account_id nếu bạn không dùng liên kết. Thêm device_id để chọn máy; nếu không, Browlix chọn máy online ít việc nhất có cùng hệ điều hành với hồ sơ.
Kết quả là phiên kèm lease (generation, holder_ref, expires_at, …) và acquired:
acquired | HTTP | Ý nghĩa |
|---|---|---|
opened | 201 | Đã mở trình duyệt mới cho bạn |
reused | 200 | Trình duyệt còn mở từ lượt giữ trước; bạn nhận nó với số thế hệ mới |
renewed | 200 | Bạn đang giữ rồi (cùng khoá và holder_ref); lượt giữ được gia hạn |
Khi người khác đang giữ
Mỗi hồ sơ có một trình duyệt và một người giữ tại một thời điểm. Nếu đang bận, acquire trả BUSY kèm details.holder_kind:
holder_kind | Ai | retryable |
|---|---|---|
person | Người đang dùng trên web (xem từ xa có quyền điều khiển) hoặc phiên mở không qua lượt giữ | không — hỏi họ |
automation | Một luồng tự động hoá đang chạy | có, khi lượt chạy xong |
app | Lượt giữ hiện tại của app khác | có, khi họ nhả hoặc hết hạn |
stopping | Trình duyệt đang đóng | có, chờ chút |
other_machine | Đang mở trên máy khác với device_id bạn yêu cầu | không |
Browlix không bao giờ cho biết người giữ kia là ai. RECOVERY_REQUIRED nghĩa là phiên trước kết thúc không chắc chắn — phục hồi trước.
Chặn bản cũ
Mỗi lượt giữ có một generation (số thế hệ). Mỗi lần người giữ khác nhận trình duyệt, số này tăng lên, nên một worker bị treo, mất mạng hay chạy quá giờ không thể thao tác thay cho trình duyệt nữa:
sessions.renewvàsessions.detachphải gửi đúnggenerationvàholder_refmà acquire trả về, bằng cùng khoá API.- Số thế hệ cũ, lượt giữ đã hết hạn, đã nhả hoặc phiên đã kết thúc đều trả
FENCEDkèmdetails.reason(superseded,expired,detachedhoặcsession_ended). - Khi nhận
FENCED, ngừng đụng vào trình duyệt đó và acquire lại. HàmacquireSessioncủa SDK tự ngừng gia hạn và gọionLost.
Gia hạn trước khi hết ttl_seconds (30–600, mặc định 120) — SDK gia hạn sau mỗi một phần ba khoảng đó. Lượt giữ không được gia hạn sẽ hết hạn: trình duyệt vẫn mở thêm keep_warm_seconds, sau đó tắt nếu không ai giữ lại.
Nhả mà không đóng
sessions.detach kết thúc lượt giữ nhưng không bao giờ tự tắt trình duyệt. Nó vẫn mở thêm keep_warm_seconds (0–1800, mặc định 120, hoặc giá trị gửi kèm detach) để việc kế tiếp của cùng tài khoản chạy ngay. Hết khoảng đó trình duyệt tắt — trừ khi trong lúc đó có người giành quyền điều khiển hoặc một lượt tự động hoá nhận nó; khi đó trình duyệt tiếp tục chạy cho họ. Muốn đóng ngay, gửi keep_warm_seconds: 0 hoặc gọi sessions.stop.
Browlix kiểm các lượt giữ hết hạn mỗi phút một lần, nên trình duyệt có thể mở quá thời gian giữ ấm tối đa khoảng một phút.
Theo dõi sự kiện phiên
Webhook có thể bị lỡ khi máy nhận của bạn tắt. sessions.events là nhật ký đứng sau chúng: mọi thay đổi trạng thái phiên và mọi lượt giữ được nhận, nhả, hết hạn hay kết thúc, theo thứ tự id.
let after = loadCursor(); // id cuối cùng bạn đã xử lý, lần đầu là 0
const r = await bx.call("sessions.events", { query: { after, limit: 200 } });
for (const e of r.data as { id: number; kind: string; session_id: string }[]) {
handle(e); // id chỉ tăng; bỏ qua id đã gặp
after = e.id;
}
saveCursor(after);- Sự kiện được giữ 7 ngày.
gap: truenghĩa là các sự kiện sau con trỏ của bạn đã bị xoá — đồng bộ lại bằngsessions.listvàbindings.list. - Lọc theo
session_idhoặcprofile_id. Đọc cần quyềnsession.read.
Mỗi máy hỗ trợ gì
devices.capabilities liệt kê việc mỗi máy làm được lúc này — gắn CDP (luôn trên cùng máy), chạy ẩn, đồng bộ hồ sơ, khoá lưu trữ, xem từ xa, tự động hoá, điều khiển đồng loạt, AI agent và API tương thích AdsPower — kèm phiên bản worker cần có, sức chứa và số trình duyệt đang chạy. Hãy đọc nó thay vì đoán từ số phiên bản.
Quyền
| Lệnh | Quyền |
|---|---|
bindings.list | profile.read |
bindings.create, bindings.update, bindings.delete | profile.edit |
sessions.acquire, sessions.renew, sessions.detach | session.start |
sessions.events | session.read |
devices.capabilities | device.read |
Mọi lệnh ghi đều có nhật ký và nhận command_id, nên gửi lại sau khi mất phản hồi sẽ nhận đúng kết quả lần đầu (lệnh và biên nhận). Qua MCP, các lệnh này là công cụ bindings_create, sessions_acquire, sessions_renew, sessions_detach, sessions_events, v.v.
