Browser Cloud Lite is a small self-hosted browser-session service for Hermes agents. It provides the subset of Browser Use Cloud that agents usually need for human-reviewable browser automation:
POST /api/v3/browserscreates an isolated Chromium session.- The response includes a Playwright/Chrome DevTools
cdpUrland a browserliveUrlserved through noVNC. PATCH /api/v3/browsers/{id}with{ "action": "stop" }stops and removes the session.- Sessions auto-expire after a configurable timeout.
It is intentionally Cloud-lite, not an anti-detect or CAPTCHA-bypass product. It gives agents CDP + live review + lifecycle APIs. If a site requires a human verification step, use the live URL for human-in-the-loop review.
Tailscale Serve or local browser
└─ optional Caddy gateway (:8088)
├─ / → existing local dashboard/app
└─ /browser/<id> → Browser Cloud Lite broker
FastAPI broker
├─ validates API keys from X-Browser-Use-API-Key or Authorization headers
├─ starts one Docker container per browser session
├─ publishes random localhost ports for agent CDP access
├─ proxies /browser/<id>/... to that session's internal noVNC/websockify port
├─ returns Browser Use-style JSON: id, cdpUrl, liveUrl, status, timeoutAt
└─ reaps expired sessions
browser session container
├─ Xvfb virtual display
├─ fluxbox window manager
├─ Chromium DevTools on loopback, bridged by socat to :9222
├─ x11vnc
└─ noVNC/websockify
git clone https://github.com/BearHuddleston/browser-cloud-lite.git
cd browser-cloud-lite
cp .env.example .env
# edit BCL_API_KEY before exposing beyond localhost
docker compose up -d --build
python3 scripts/smoke_test.pyDefault local URLs:
- Broker:
http://127.0.0.1:8765 - Health:
http://127.0.0.1:8765/health
curl -sS -X POST http://127.0.0.1:8765/api/v3/browsers \
-H "Content-Type: application/json" \
-H "X-Browser-Use-API-Key: $BCL_API_KEY" \
-d '{}'Response:
{
"id": "...",
"status": "active",
"cdpUrl": "ws://127.0.0.1:49153/devtools/browser/...",
"connectUrl": "ws://127.0.0.1:49153/devtools/browser/...",
"liveUrl": "http://127.0.0.1:8765/browser/<session-id>",
"startedAt": "2026-06-11T...Z",
"timeoutAt": "2026-06-11T...Z",
"finishedAt": null,
"browserCost": 0,
"proxyCost": 0,
"proxyUsedMb": 0,
"agentSessionId": null,
"recordingUrl": null
}curl -sS -X PATCH http://127.0.0.1:8765/api/v3/browsers/$SESSION_ID \
-H "Content-Type: application/json" \
-H "X-Browser-Use-API-Key: $BCL_API_KEY" \
-d '{"action":"stop"}'Other Hermes agents on the same host can use the included helper without remembering headers:
python3 scripts/bcl_client.py health
python3 scripts/bcl_client.py create --start-url https://example.com
python3 scripts/bcl_client.py stop <session-id>The create command prints JSON containing cdpUrl and liveUrl.
Have Hermes or any other agent create a session, then connect Playwright to the returned cdpUrl:
const { chromium } = require('playwright');
const browser = await chromium.connectOverCDP(cdpUrl);The API shape intentionally mirrors the Browser Use browsers endpoint. A Hermes browser provider plugin can target this broker by replacing Browser Use's base URL with http://127.0.0.1:8765/api/v3 and using BCL_API_KEY as the browser API key.
Keep the broker and gateway bound to localhost unless you know what you are doing. The included Caddy gateway lets you put Browser Cloud Lite behind an existing tailnet hostname without allocating a new Tailscale Serve port per session.
Example root gateway flow:
BCL_PUBLIC_BASE_URL=https://your-host.tailnet-name.ts.net
BCL_GATEWAY_BIND_HOST=127.0.0.1
BCL_GATEWAY_PORT=8088docker compose up -d --build
sudo tailscale serve --bg --yes http://127.0.0.1:8088With that configuration, each create response returns a stable human-review URL:
https://your-host.tailnet-name.ts.net/browser/<session-id>
The broker multiplexes /browser/<session-id>/... to the correct session container and returns 410 Gone after a session is stopped or expired.
- Set a real
BCL_API_KEYbefore exposing the broker. - The default compose binds the broker to
127.0.0.1:8765. - Session containers are per-session and removed on stop/timeout.
- This service mounts the Docker socket into the broker container. Treat broker access as privileged.
- Do not use this as a CAPTCHA bypass system. Use the
liveUrlfor explicit human-in-the-loop steps.
docker compose build
docker compose up -d
python3 scripts/smoke_test.py
python3 scripts/smoke_test.py --playwright