Developer docs

VPBrowser API

Start, stop and automate browser profiles from your own code. Connect Puppeteer or Playwright to any profile, on any of your computers, from anywhere. Paths and parameters are AdsPower-compatible.

Overview

There are two APIs with the same endpoints and the same AdsPower-compatible response envelope. Pick the one that matches where your script runs.

1. Remote API

https://vpbrowser.com/api/v1/…
  • Works from anywhere: your server, a VPS, a laptop.
  • Auth: header X-Api-Key: vb_live_… (or Authorization: Bearer vb_live_…).
  • Create keys in the dashboard: Settings → Remote API → Create key. The key is shown once.
  • A key acts as the user who created it: it sees that user's profiles and launches on that user's computers.

2. Local API

http://127.0.0.1:50325/api/v1/…
  • Uses the next free port if 50325 is taken (e.g. when AdsPower is running).
  • Runs inside the VPBrowser desktop app (Mac/Windows) from version 0.3.30. Only reachable from the same computer.
  • Key: dashboard Settings → Local API (in the app), or tray menu → Local API → Copy API key. Header X-Api-Key: <key>.
  • Scripts written for the AdsPower Local API work after changing the key (same paths & params).
Remote API auth
# Either header works
curl -H "X-Api-Key: vb_live_..." https://vpbrowser.com/api/v1/user/list
curl -H "Authorization: Bearer vb_live_..." https://vpbrowser.com/api/v1/user/list
Local API auth
curl -H "X-Api-Key: <key>" http://127.0.0.1:50325/api/v1/user/list

Response envelope

Every response uses the same envelope. code is 0 on success and -1 on error, with msg explaining what went wrong.

Success
{
  "code": 0,
  "msg": "success",
  "data": { ... }
}
Error
{
  "code": -1,
  "msg": "Profile not found",
  "data": {}
}

How remote control works

Works like a cloud browser: run the VPBrowser app on any computer or server, then control its profiles from anywhere.

  1. YouYour scriptPuppeteer / Playwright
  2. RelayVPBrowser servervpbrowser.com
  3. Your computerVPBrowser appon the computer running the profile
  4. ProfileThe browserwith its own proxy & fingerprint
  • The computer only makes outgoing connections: no open ports, and its IP is never exposed.
  • Your script only ever sees the server address.
  • The ws link from browser/start is a signed ticket valid for 24 h for that one running profile. Get a fresh one from browser/active.

Engine support

Full browser control (Puppeteer/Playwright via CDP) works with Vanta profiles (Chromium engine). Vanta Fox (Firefox-based) profiles can be started and stopped via the API but return an empty ws (no remote control — Firefox has no CDP endpoint). Profiles created through the API are always Vanta (Chrome), so they are controllable by default; to control an existing Vanta Fox profile, switch its engine to Vanta in the profile editor.

Performance: control latency

Every CDP action (click, type, read) is a round-trip to the browser. On the Local API that's ~0 ms — the script and the browser are on the same machine. On the Remote API each action crosses the internet through the relay, ~200 ms each, which adds up over a form with many steps.

  • For heavy automation, run your agent on the same computer/server as the browser and use the Local API.
  • Minimize round-trips: use one fill() per field (instant, paste-style) instead of typing character by character, and batch reads in a single evaluate().
  • The site's own page loads are usually the real floor — control latency is small next to them.

Resume where you left off

A running profile is a persistent session: disconnecting a CDP client does not close the browser. Calling browser/start (or browser/active) again for the same user_id returns the same running session — its tabs, URL, cookies and form state are all still there. To continue instead of restarting:

  • Reconnect, then attach to the existing tab: browser.contexts()[0].pages()[0] — don't open a new page.
  • Read the current URL / DOM to detect which step you're on, and branch — don't blindly re-navigate to the start.

AI agents & computer use

Two ready-to-run examples ship in the repo under examples/: ai-agent (an LLM that drives a profile toward a goal with selector/screenshot tools) and computer-use-agent (the ChatGPT-Operator pattern — Claude computer-use looks at a screenshot and drives the browser with real mouse moves, clicks and typing, with a visible gliding cursor). Because they use genuine input events rather than DOM injection, there is no webdriver/automation tell.

There is also an MCP server under examples/mcp-server: add it to Claude Desktop, Claude Code or Cursor and manage and drive profiles in plain language (create_profile, start_browser, browser_goto, browser_click, rotate_proxy…). It wraps this same API, so it's bring-your-own-AI — your client runs the model.

Quick start

Start a profile through the Remote API, connect to it, open a page, then disconnect. Set VBROWSER_KEY to a key from Settings → Remote API.

curl -H "X-Api-Key: $VBROWSER_KEY" "https://vpbrowser.com/api/v1/browser/start?user_id=900000123"

Good to know

  • user_id accepts the profile's ID (UUID) or its numeric ID shown in the dashboard (e.g. 900000123).
  • When you are done, call disconnect() (Puppeteer) or just exit. Don't call browser.close() unless you want to close the profile's browser.

Endpoints

Paths below are for the Remote API. The Local API has the same browser, user and group endpoints at http://127.0.0.1:50325; endpoints marked Remote only exist only on the Remote API.

Service

GET/api/v1/status

Status

Remote + LocalNo auth

Health check. No authentication required.

Request
curl https://vpbrowser.com/api/v1/status
Response
{
  "code": 0,
  "msg": "success",
  "data": { "name": "VPBrowser", "version": "..." }
}
GET/api/v1/machines

List computers

Remote only API key

Your computers running the VPBrowser app. Use an id or name as the machine parameter of browser/start.

Request
curl -H "X-Api-Key: $VBROWSER_KEY" https://vpbrowser.com/api/v1/machines
Response
{
  "code": 0,
  "msg": "success",
  "data": {
    "list": [
      { "id": "...", "name": "...", "online": true, "last_seen": "..." }
    ]
  }
}

Browser

GETPOST/api/v1/browser/start

Start a profile

Remote + Local API key

Opens the profile's browser and waits until it is up. If the profile is already open, the running one is returned. The ws links are signed tickets valid for 24 h for that one running profile.

Parameters (query or body)
NameTypeDescription
user_idrequiredstringProfile ID (UUID) or the numeric ID shown in the dashboard, e.g. 900000123.
machineoptionalstringRemote only Computer id or name from /machines. Default: any of your online computers.
headlessoptional0 | 11 = no window. Vanta only.
open_urlsoptionalstringComma-separated http(s) URLs to open.
timeoutoptionalnumberSeconds to wait. Default 120, max 170. The first start can take longer while the engine downloads.

Local API returns ws: { puppeteer, selenium: "127.0.0.1:<port>" } plus debug_port.

Errors: no app online 409, profile not found 404, launch failed 502, timeout 504.

Request
curl -H "X-Api-Key: $VBROWSER_KEY" \
  "https://vpbrowser.com/api/v1/browser/start?user_id=900000123&machine=office-mac&open_urls=https://example.com"
Response
{
  "code": 0,
  "msg": "success",
  "data": {
    "user_id": "…uuid…",
    "numeric_id": 900000123,
    "name": "…",
    "status": "Active",
    "engine": "vanta",            // "vanta" | "vantafox" | "chromium"
    "machine": { "id": "…", "label": "…" },
    "ws": {
      "puppeteer": "wss://vpbrowser.com/cdp/<ticket>",
      "playwright": "wss://vpbrowser.com/cdp/<ticket>"
    }
  }
}
GETPOST/api/v1/browser/stop

Stop a profile

Remote + Local API key

Saves cookies & data and closes the browser.

Parameters (query or body)
NameTypeDescription
user_idrequiredstringProfile ID or numeric ID.

Local API returns { user_id, stopped }.

Response
{
  "code": 0,
  "msg": "success",
  "data": { "user_id": "…", "stopping": true }
}
GET/api/v1/browser/active

Profile status

Remote + Local API key

Returns the running entry (with a fresh ws link) or { user_id, status: "Inactive" }. Use it to get a new ticket for a profile that is already open.

Query parameters
NameTypeDescription
user_idrequiredstringProfile ID or numeric ID.
Response
{
  "code": 0,
  "msg": "success",
  "data": { "user_id": "…", "status": "Inactive" }
}
GET/api/v1/browser/list-active

List running profiles

Remote + Local API key

All running profiles you can see. Alias: /api/v1/browser/local-active.

Response
{
  "code": 0,
  "msg": "success",
  "data": { "list": [ { "user_id": "…", "status": "Active", ... } ] }
}

Profiles

GET/api/v1/user/list

List profiles

Remote + Local API key

Paginated list of profiles. Each item uses the AdsPower field names.

Query parameters
NameTypeDescription
pageoptionalnumberPage number.
page_sizeoptionalnumberItems per page, max 100.
group_idoptionalstringOnly profiles in this group.
user_idoptionalstringSearch by profile ID.
Response
{
  "code": 0,
  "msg": "success",
  "data": {
    "list": [
      {
        "user_id": "…",
        "numeric_id": 900000123,
        "serial_number": "…",
        "name": "…",
        "group_id": "…",
        "group_name": "…",
        "created_time": "…",
        "last_open_time": "…",
        "fingerprint_config": { "timezone": "…", "language": "…", "ua": "…", "screen_resolution": "1920_1080" },
        "browser_kernel_config": { "type": "…" },
        "proxy_config": { "proxy_soft": "…", "proxy_type": "…", "proxy_host": "…", "proxy_user": "…" }
      }
    ],
    "page": 1,
    "page_size": 50,
    "total": 1
  }
}
POST/api/v1/user/create

Create a profile

Remote + Local API key

JSON body with AdsPower fields. Omitted fingerprint fields are generated as a realistic, unique device. Returns the created profile.

Body parameters
NameTypeDescription
nameoptionalstringProfile name.
group_idoptionalstringGroup name.
user_proxy_configoptionalobjectproxy_soft ("other" | "no_proxy"), proxy_type ("http" | "socks5"), proxy_host, proxy_port, proxy_user, proxy_password.
fingerprint_configoptionalobjectOptional: ua, screen_resolution (e.g. "1920_1080"), timezone, language.

Plan limits apply: over the limit returns 402 “Your X plan allows N profiles”.

Request
curl -X POST https://vpbrowser.com/api/v1/user/create \
  -H "X-Api-Key: $VBROWSER_KEY" -H "Content-Type: application/json" \
  -d '{
    "name": "Shop account 1",
    "group_id": "Shops",
    "user_proxy_config": {
      "proxy_soft": "other",
      "proxy_type": "socks5",
      "proxy_host": "1.2.3.4",
      "proxy_port": "1080",
      "proxy_user": "user",
      "proxy_password": "pass"
    },
    "fingerprint_config": { "screen_resolution": "1920_1080", "language": "en-US" }
  }'
POST/api/v1/user/update

Update a profile

Remote + Local API key

Body: user_id plus the fields to change (same fields as create).

Body parameters
NameTypeDescription
user_idrequiredstringProfile to update.
Request
curl -X POST https://vpbrowser.com/api/v1/user/update \
  -H "X-Api-Key: $VBROWSER_KEY" -H "Content-Type: application/json" \
  -d '{ "user_id": "900000123", "name": "Renamed" }'
POST/api/v1/user/delete

Delete profiles

Remote + Local API key

Moves the profiles to the Recycle Bin.

Body parameters
NameTypeDescription
user_idsrequiredstring[]Profiles to delete. A single user_id is also accepted.
Request
curl -X POST https://vpbrowser.com/api/v1/user/delete \
  -H "X-Api-Key: $VBROWSER_KEY" -H "Content-Type: application/json" \
  -d '{ "user_ids": ["900000123"] }'

Proxy

GETPOST/api/v1/proxy/check

Check a profile's proxy

Remote only API key

Routes a geo/IP lookup through the profile's saved proxy and returns the real exit. On success it also marks the proxy OK and aligns the profile's timezone, language and location to the exit country.

Parameters (query or body)
NameTypeDescription
user_idrequiredstringProfile ID or numeric ID.
Request
curl -H "X-Api-Key: $VBROWSER_KEY" \
  "https://vpbrowser.com/api/v1/proxy/check?user_id=900000123"
Response
{
  "code": 0,
  "msg": "success",
  "data": {
    "user_id": "…",
    "exit_ip": "77.179.250.209",
    "country": "DE", "city": "Frankfurt", "region": "Hesse",
    "isp": "Telefonica Germany",
    "latency_ms": 420
  }
}
GETPOST/api/v1/proxy/rotate

Rotate a profile's proxy IP

Remote only API key

Gets a new exit IP: a VPBrowser proxy rerolls a fresh, quality-checked IP (sticky mode); a custom proxy with a rotation URL has it fetched. Rotating-mode proxies already change on every connection.

Body parameters
NameTypeDescription
user_idrequiredstringProfile ID or numeric ID.
through_proxyoptional0 | 1Send the rotation request through the proxy itself (custom rotation-URL proxies only).
Request
curl -X POST https://vpbrowser.com/api/v1/proxy/rotate \
  -H "X-Api-Key: $VBROWSER_KEY" -H "Content-Type: application/json" \
  -d '{ "user_id": "900000123" }'

Groups

GET/api/v1/group/list

List groups

Remote + Local API key

All profile groups.

POST/api/v1/group/create

Create a group

Remote + Local API key

Creates a profile group.

Body parameters
NameTypeDescription
group_namerequiredstringName of the new group.
POST/api/v1/group/update

Rename a group

Remote + Local API key

Renames a profile group.

Body parameters
NameTypeDescription
group_idrequiredstringGroup to rename.
group_namerequiredstringNew name.

Errors & limits

Errors use the envelope with code: -1, and the HTTP status is meaningful:

StatusMeaning
401Bad or missing API key.
402Plan limit reached when creating profiles, e.g. “Your X plan allows N profiles”.
403Suspended workspace, or an API key used on the wrong route.
404Not found (e.g. profile not found).
409No computer online, or the chosen computer is offline.
502Launch failed.
504Timed out waiting for the browser.
  • One profile can only be open on one computer at a time.
  • Keep keys secret. Revoke them in Settings; every key action appears in the Audit log.

Running VPBrowser as a cloud browser

  1. Install the appInstall the VPBrowser app on a computer or Windows/Mac server that stays on (download page).
  2. Sign inIt links automatically and appears in /api/v1/machines.
  3. Create an API keyDashboard Settings → Remote API → Create key.
  4. Start & connectStart profiles with machine=<name> and connect to the ws link from anywhere.

Proxies stay with the profile

Each profile keeps its own proxy, so websites see the profile's proxy IP, never your server's or your script's.