Skip to main content

Guides

Recipes for multi-account apps

How an app that posts, reads inboxes or collects data for many social accounts should use Browlix — one binding per account, identity first, holds per job, people for challenges, and the app's own state kept by the app.

View as Markdown

These recipes are for apps that work with many accounts on sites such as Facebook, Instagram, LinkedIn or X. They describe how to use Browlix, not how to automate a particular site. Every piece of code they rely on is in the sample app and Move from a local Chrome profile, both run on Browlix's lab machines.

Use them within each site's terms and the acceptable use policy. Browlix does not promise that a site will never restrict an account.

1. One binding per account

Bind each account once: bindings.create with your app_id and the account's external_account_id, pointing at its profile. Look it up with bindings.list before creating, and on CONFLICT use the binding that won (the sample app shows this). Keep metadata small and non-secret — credential-like keys are refused.

Group profiles by team or client with groups.* and label them with tags.*; both can be renamed or deleted from the API.

2. Identity before any action

A browser that opens is not proof of which account is signed in. After attaching, read the signed-in account from the site and compare it with the binding's external_account_id before doing anything:

SiteRead from the page after it loads
FacebookThe signed-in user's numeric ID
InstagramThe signed-in viewer's account
LinkedInThe signed-in member's identifier (URN)
XThe signed-in viewer, read again after every open

If it does not match, or nobody is signed in, stop: do not post, read or retry under that binding. Mark the account in your app and let a person look at it.

3. Hold the browser per job

  • acquireSession with a holderRef that names the worker process. The SDK renews the hold while the job runs.
  • Between jobs on the same account, detach({ keepWarmSeconds }) keeps the browser open so the next job starts at once.
  • At the end of the day, detach with keepWarmSeconds: 0 and stopSession: data is sealed and synced after the browser closes.
  • BUSY means a person or another app holds the browser. Wait and try later; never take it over.
  • FENCED means your hold was superseded. Stop acting on that page immediately — another worker owns it now.

See Hold a browser from your app for the full lease rules.

4. Challenges go to a person

When a site asks for a code, a confirmation, a captcha or an identity check, stop the job and hand the account to a person, who can finish it in the web app's live view while your app waits. Browlix has no captcha solving and your app should not add one.

5. The app keeps its own state

Your job queue, schedules, do-not-contact lists, per-account quotas and outgoing-message outbox belong to your app. A session closing is not a job completing: record the job's outcome in your app before you let go of the browser, and make sending idempotent on your side so a retried job never sends twice.

6. When something goes wrong

SignalWhat to do
RECOVERY_REQUIREDThe previous session ended uncertainly. Decide with sessions.recover, then open again — see Sessions
A session.failed event, or the session leaving readyStop the job; retry later
A machine goes offlineHolds lapse. The profile opens on another machine once its last session's data is synced; until then opening it answers SYNC_PENDING

Follow events with sessions.events or webhooks.

7. Moving accounts in

Move accounts from local Chrome directories one at a time, verify each identity, and keep the old directory until you are sure — Move from a local Chrome profile.

Tell us what is missing

If an operation you need is not in the API, an AI agent working on your integration can file it with feedback_submit, or you can — see Feedback from agents.