Domain skill
browser-use-cloud
Markdown synced from browser-harness domain skills.
- Host
- browser-use-cloud
- Files
- 1
Agent prompt
Use this skill
Copy this prompt into your coding agent to make it enable browser-harness domain skills and read this exact domain folder before automating.
Set up https://github.com/browser-use/browser-harness for me if it is not already installed. If setup is needed, read `install.md` first to install and connect it to my real browser. Then read `SKILL.md` for normal usage and always read `helpers.py` because that is where the browser-harness functions are. Enable domain skills if they are not already enabled by setting `BH_DOMAIN_SKILLS=1` for browser-harness. Use the `browser-use-cloud` domain skill from `agent-workspace/domain-skills/browser-use-cloud/`. Read every markdown file for this domain before inventing an approach: - agent-workspace/domain-skills/browser-use-cloud/cloud.md Use those domain-skill notes to complete my task for `browser-use-cloud` in my real browser. When you open a setup, verification, or task tab, activate it so I can see the active browser tab.
Skill contents
What the agent will read
Programmatic Automation
cloud.md
- https://api.browser-use.com/api/v3 (REST). All five endpoints below were exercised end-to-end on 2026-05-05 with a real BROWSERUSEAPIKEY; the companion script cleanup-zombies.py next to this file is the field-test —...
- This skill is for users who already start cloud browsers via startremotedaemon() and want to manage the surrounding lifecycle — provisioning fleets, cleaning up zombies, listing what's running, sharing liveUrls —...
- REST uses a custom header (not Authorization: Bearer — that path returns a generic 401 silently):
- The key only authorises actions on browsers and profiles created under it — there are no organisation-level admin endpoints on the public API.
Show full markdown
https://api.browser-use.com/api/v3 (REST). All five endpoints below were
exercised end-to-end on 2026-05-05 with a real BROWSER_USE_API_KEY; the
companion script cleanup-zombies.py next to this file is the
field-test — running it lists active browsers and stops zombies via the
same wire calls the harness uses internally.
This skill is for users who already start cloud browsers via
start_remote_daemon() and want to manage the surrounding lifecycle —
provisioning fleets, cleaning up zombies, listing what's running, sharing
liveUrls — without clicking through cloud.browser-use.com.
Auth
REST uses a custom header (not Authorization: Bearer — that path
returns a generic 401 silently):
import os
HEADERS = {
"X-Browser-Use-API-Key": os.environ["BROWSER_USE_API_KEY"],
"Content-Type": "application/json",
}
The key only authorises actions on browsers and profiles created under it — there are no organisation-level admin endpoints on the public API.
Endpoint reference
All paths are under https://api.browser-use.com/api/v3. Verified status
codes and shapes from 2026-05-05 below.
POST /browsers — provision a cloud browser
Body (camelCase):
| Key | Type | Notes |
|---|---|---|
profileId | UUID | optional; logged-in cloud profile |
profileName | str | optional; resolved client-side |
proxyCountryCode | ISO2 | default "us"; pass null to disable BU proxy |
timeout | int | minutes, 1..240 |
customProxy | obj | {host, port, username, password, ignoreCertErrors} |
browserScreenWidth / browserScreenHeight | int | viewport |
allowResizing | bool | viewport user-resizable |
enableRecording | bool | session recording |
Returns 201 with this shape (also returned by GET /browsers/{id},
GET /browsers items, and PATCH /browsers/{id}):
{
"id": str,
"status": str, # e.g. "active"
"liveUrl": str, # host: live.browser-use.com (different from cloud.browser-use.com)
"cdpUrl": str, # https:// — daemon converts to ws via /json/version
"timeoutAt": str, # ISO 8601 UTC
"startedAt": str,
"finishedAt": None, # populated only after stop
"proxyUsedMb": str, # STRING — cast to float before arithmetic
"proxyCost": str, # STRING
"browserCost": str, # STRING
"agentSessionId": None,
"recordingUrl": None, # str only when enableRecording=True at create
}
The liveUrl carries the cdp WebSocket as a ?wss=... query param, so
sharing the URL alone hands off a viewable session — no extra setup.
PATCH /browsers/{id} — stop (end billing)
Body {"action": "stop"}. Returns 200 with the same browser object,
but liveUrl and cdpUrl come back as null and finishedAt is
populated. Use the returned proxyCost + browserCost for final cost.
Always wrap caller code in try/finally; every billed minute counts.
GET /browsers — list active sessions
Returns 200 and the standard envelope
{items: [...], totalItems, pageNumber, pageSize}. items[*] matches
the POST /browsers response shape. Already-finished browsers appear in
the listing for a window with finishedAt populated — filter them out
when computing age.
GET /profiles?pageSize=N&pageNumber=N — list cloud profiles
pageSize caps at 100. Same envelope as /browsers.
GET /profiles/{id} — profile detail
Returns the same shape as the listing items:
{
"id": str,
"userId": None, # null in observed responses
"name": str,
"lastUsedAt": str | None, # null until first use
"createdAt": str,
"updatedAt": str,
"cookieDomains": list[str] | None, # null on freshly-created profiles
}
browser_harness.admin.list_cloud_profiles() already wraps the listing
- per-id GET; prefer it unless you need raw access.
Companion script: cleanup-zombies.py
A self-contained operator script next to this file. Run it with:
BROWSER_USE_API_KEY=... python agent-workspace/domain-skills/browser-use-cloud/cleanup-zombies.py
# stops every active browser older than 30 minutes (default)
BROWSER_USE_API_KEY=... python .../cleanup-zombies.py --older-than 5 --dry-run
# preview only; no PATCH /stop sent
The script is the practical residue of the API verification — running it
exercises four of the five endpoints (GET /browsers, plus
PATCH .../stop per zombie). Use it as the live regression check
whenever this skill is updated.
Dashboard navigation (when API isn't enough)
The dashboard at cloud.browser-use.com requires a logged-in session;
the unauthenticated root redirects to /signup (verified 2026-05-05).
Beyond /signup the slugs below are inferred from typical SaaS layout
— confirm in your own browser before relying on the literal paths:
/signup (verified) /dashboard [verify] /browsers [verify] — likely the dashboard mirror of GET /browsers /browsers/<id> [verify] /profiles [verify] /api-keys [verify]
There is no /usage page mirror — GET /usage on the API returns 404,
so per-session cost has to come from each browser record (proxyCost +
browserCost). The dashboard surfaces aggregate billing somewhere, but
that's outside the API surface and not useful from inside bh.
For dashboard scraping, attach to your real Chrome and read cookies:
cookies = cdp("Network.getCookies", urls=["https://cloud.browser-use.com"])
parts = [c["name"] + "=" + c["value"] for c in cookies.get("cookies", [])]
dash_headers = {"Cookie": "; ".join(parts), "Accept": "text/html,application/json"}
Empty cookie jar = not logged in; open cloud.browser-use.com in your
real Chrome once, then retry.
Traps to avoid
- Auth header name is
X-Browser-Use-API-Key.Authorization: Bearer ...silently fails with a generic 401. - Cost fields are strings, not numbers.
proxyCost,browserCost,proxyUsedMbcome back as quoted strings ("0.0123"); cast tofloatbefore arithmetic. cookieDomainscan beNoneon freshly-created profiles, despite whatadmin.py:list_cloud_profiles's docstring says. Guard withc or [].liveUrlhost islive.browser-use.com, notcloud.browser-use.com. They're separate surfaces.start_remote_daemonoverwritesBU_CDP_WSin the daemon env; re-read frombrowser["cdpUrl"]if you need the value afterwards. (PR #300 stopsrun.pyfrom clobbering an explicitBU_CDP_URL, but the daemon env still gets set.)liveUrlis single-session — after stop, the URL no longer resolves; don't cache across calls._browser_usehas a 60s timeout inadmin.py; long-running ops (large profile sync) need their own polling.profile-useCLI is a separate install:curl -fsSL https://browser-use.com/profile.sh | sh.pageSizecaps at 100 silently — paginate viapageNumber.totalItemsin the envelope lets you size loops up front.proxyCountryCodedefaults to"us"when omitted; passNoneto disable BU proxy entirely. Wrong country = wrong egress IP = breaks geo-locked auth.
What this skill does NOT cover
- Billing / payment methods — dashboard only, intentionally sensitive.
- Organisation / team admin — outside the per-API-key surface.
- SDK features — Browser Use ships official SDKs separately; this
skill is the raw-HTTP path for power users inside
bh. - Cross-API-key reads — every endpoint is scoped to the calling key.
Provenance
Live-tested 2026-05-05 against https://api.browser-use.com/api/v3:
| Endpoint | Method | Status | Notes |
|---|---|---|---|
/profiles?pageSize=100&pageNumber=1 | GET | 200 | shape verified |
/profiles/{id} | GET | 200 | cookieDomains=None observed on a fresh profile |
/browsers | POST | 201 | liveUrl host is live.browser-use.com |
/browsers/{id} ({action:"stop"}) | PATCH | 200 | returns final cost |
/browsers | GET | 200 | paginated {items,totalItems,pageNumber,pageSize} |
/usage | GET | 404 | no public endpoint |
/ | GET | 404 | no root metadata |
Companion script cleanup-zombies.py re-runs the listing + stop subset
end-to-end and is the regression artefact for this skill. A full E2E
loop (spawn → list → stop → re-list) was executed on 2026-05-05 against
the production API and printed:
[STOP] 3ac4c964-...-d3d3e1ad7508 age= 0.0min cost=$0.0020 summary: 1 active session(s), stopped 1
Re-running the script in --dry-run mode against an empty pool is the
cheapest smoke test (no PATCH /stop calls, ~$0).