Skip to main content

Get started

Quickstart

Create an API key, open a profile on one of your machines, control it with Playwright and stop it again.

View as Markdown

This walk-through uses the HTTP API directly so every step is visible. The same steps exist in the SDK, the CLI and as MCP tools.

You need a Browlix workspace with at least one paired machine that is online (Workspace → Machines → Pair a machine). Step 6 must run on that machine — see Where your code runs.

Before you start

Install the client for the language you use (Node 20 or later, or Python 3.9 or later). The Playwright package is only the client; it does not need its own browsers, because Browlix opens the browser:

npm i https://browlix.com/api/public/sdk/v1/download/latest playwright

The TypeScript snippets form one ES module with top-level await: save them as quickstart.mts and run node quickstart.mts (Node 22.18 or later runs TypeScript directly; on older Node use npx tsx quickstart.mts). The curl snippets are bash. On Ubuntu and Debian the system Python refuses a global pip install: create a virtual environment first with python3 -m venv .venv && . .venv/bin/activate (package python3-venv).

1. Create an API key

In the web app open Settings → API keys, create a key with the scopes you need and copy it — the secret is shown once. Keep it in an environment variable, never in code:

bash
export BROWLIX_API_KEY="bxk_…"

2. Check the key

curl https://browlix.com/api/public/v1/workspace \
  -H "Authorization: Bearer $BROWLIX_API_KEY"

Every response carries a correlation_id; quote it when you report a problem.

3. Pick a machine

curl https://browlix.com/api/public/v1/devices \
  -H "Authorization: Bearer $BROWLIX_API_KEY"
# export DEVICE_ID=<data[0].id>

Use a machine whose state is online; the list also shows its operating system and free session capacity.

4. Create a profile

Writes are commands: you send your own command_id (a UUID) so a retry can never create a second profile. See Commands and receipts.

curl -X POST https://browlix.com/api/public/v1/profiles \
  -H "Authorization: Bearer $BROWLIX_API_KEY" \
  -H "Content-Type: application/json" \
  -d "{\"command_id\":\"$(uuidgen)\",\"profile\":{\"name\":\"Quickstart\",\"config\":{\"os\":\"linux\"}}}"
# export PROFILE_ID=<data.profile_id>

Set os to the operating system of the machine you picked (windows or linux): a profile is kept consistent with the machine it runs on.

5. Open the profile

curl -X POST https://browlix.com/api/public/v1/sessions \
  -H "Authorization: Bearer $BROWLIX_API_KEY" \
  -H "Content-Type: application/json" \
  -d "{\"command_id\":\"$(uuidgen)\",\"profile_id\":\"$PROFILE_ID\",\"device_id\":\"$DEVICE_ID\"}"

# export SESSION_ID=<data.id>, then poll until data.lifecycle is "ready"
curl https://browlix.com/api/public/v1/sessions/$SESSION_ID \
  -H "Authorization: Bearer $BROWLIX_API_KEY"

A profile has at most one live session. Opening it again answers BUSY with the open session's id.

6. Attach Playwright (on that machine)

sessions.attach returns a short-lived ticket and the address of the machine's local broker, ws://127.0.0.1:<port>/cdp. Run this on the machine that holds the session:

import { chromium } from "playwright";

const a = await bx.attach(sessionId, { ttlSeconds: 300 });
const browser = await chromium.connectOverCDP(a.endpoint, { headers: a.headers });
const page = browser.contexts()[0]!.pages()[0] ?? (await browser.contexts()[0]!.newPage());
await page.goto("https://example.com");
console.log(await page.title());
await browser.close(); // disconnects Playwright; the session keeps running

The ticket is valid for one session, for ttl_seconds (30–900, default 300). Ask for a new one when it expires.

7. Stop the session

curl -X POST https://browlix.com/api/public/v1/sessions/$SESSION_ID/stop \
  -H "Authorization: Bearer $BROWLIX_API_KEY" \
  -H "Content-Type: application/json" \
  -d "{\"command_id\":\"$(uuidgen)\"}"

The session is reported closed only after the machine proves no browser process is left.

Next steps

  • Sessions — every lifecycle state and what to do in each.
  • Webhooks — get session.ready pushed instead of polling.
  • Errors — the typed codes and which ones are safe to retry.