Skip to content

feat(domain-skills): add browser-use-cloud (REST + cleanup-zombies)#301

Merged
sauravpanda merged 2 commits intobrowser-use:mainfrom
ComBba:feat/domain-skills-browser-use-cloud
May 5, 2026
Merged

feat(domain-skills): add browser-use-cloud (REST + cleanup-zombies)#301
sauravpanda merged 2 commits intobrowser-use:mainfrom
ComBba:feat/domain-skills-browser-use-cloud

Conversation

@ComBba
Copy link
Copy Markdown
Contributor

@ComBba ComBba commented May 5, 2026

Summary

Adds an operator-facing skill for the Browser Use cloud REST API
(api.browser-use.com/api/v3) and a companion cleanup-zombies.py
script. Covers the same wire surface admin.py already speaks
(X-Browser-Use-API-Key, /browsers, /profiles), plus the most
common automation: stopping zombie sessions older than N minutes.

Why this style of skill

The README's contributor guidance says skills should be agent-generated.
This one takes a slightly different shape: it documents the
operator-facing REST surface that admin.py itself calls — there's
no browser DOM involved on the API path, so "what actually works in the
browser" partly doesn't apply. The provenance is still real:

  • Every endpoint was exercised live on 2026-05-05.
  • The companion script cleanup-zombies.py runs end-to-end
    (spawn → list → stop → re-list verified during authoring).
  • The verified-shape table at the bottom of cloud.md is from real
    responses, not speculation.

I'm happy to follow up with an agent-driven complement (a
dashboard-navigation skill from real session capture) if you'd prefer
that style for this domain, or to scope this as docs/ instead of
domain-skills/ if the API-first framing isn't a fit.

Live verification log (2026-05-05)

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 (not cloud.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; documented accordingly
/ GET 404 no root metadata

Wire gotchas surfaced and documented

  • Cost / proxy fields are JSON strings, not numbers — proxyCost,
    browserCost, proxyUsedMb need float() cast before arithmetic.
  • liveUrl host is live.browser-use.com, separate from
    cloud.browser-use.com; the cdp WebSocket is encoded as a ?wss=
    query parameter.
  • cookieDomains can be None on freshly-created profiles,
    contradicting admin.py:list_cloud_profiles's docstring.
  • GET /usage returns 404 — per-session cost lives on each browser
    record; aggregate billing only on the dashboard.

Companion script live demo

$ BROWSER_USE_API_KEY=... python cleanup-zombies.py --older-than 0
[STOP] 3ac4c964-9945-4a5e-b007-d3d3e1ad7508  age=  0.0min  cost=$0.0020
summary: 1 active session(s), stopped 1

--dry-run mode is the cheapest smoke test (no PATCH /stop calls).

Tests

The skill is a markdown + utility script; no harness code is touched.

$ uv run --with pytest --with pillow pytest tests/ -q
83 passed in 0.39s

Style refs

Refs


Summary by cubic

Adds an operator-facing Browser Use Cloud skill and a cleanup-zombies.py utility to stop stale cloud browsers. Documents the /browsers and /profiles REST surface used by admin.py, with live-verified wire shapes.

  • New Features
    • New skill browser-use-cloud/cloud.md for https://api.browser-use.com/api/v3: POST/GET/PATCH /browsers, GET /profiles, GET /profiles/{id}; GET /usage is not public (404).
    • Companion cleanup-zombies.py to stop sessions older than N minutes; supports --older-than, --dry-run, --json; continues on transient network errors during stop calls.
    • Uses X-Browser-Use-API-Key from BROWSER_USE_API_KEY.
    • Notes key gotchas: cost/proxy fields are strings; liveUrl host is live.browser-use.com; cookieDomains may be null.
    • Live-verified on 2026-05-05; no test harness changes.

Written for commit 3de7fe0. Summary will update on new commits.

Adds an operator-facing skill for cloud.browser-use.com / api.browser-use.com,
covering the same REST surface that the harness's own admin.py already
uses (X-Browser-Use-API-Key header, /browsers, /profiles), plus a
companion script for the most common automation -- stopping zombie
sessions older than N minutes.

Live-tested on 2026-05-05 with a real BROWSER_USE_API_KEY:

  POST   /browsers              201 - shape verified incl. liveUrl on live.browser-use.com
  PATCH  /browsers/{id} stop    200 - returns final cost
  GET    /browsers              200 - paginated {items, totalItems, ...}
  GET    /profiles              200 - same envelope
  GET    /profiles/{id}         200 - cookieDomains=None on fresh profiles
  GET    /usage                 404 - no public endpoint, doc'd accordingly
  GET    /                      404 - no root metadata

The cleanup-zombies.py companion is the regression artefact; running it
in dry-run mode is the cheapest smoke test, and a full E2E loop
(spawn -> list -> stop -> re-list) was confirmed end-to-end during
authoring.

Notable wire gotchas surfaced and documented:

- Cost / proxy fields (proxyCost, browserCost, proxyUsedMb) are returned
  as JSON strings, not numbers; cast to float before arithmetic.
- liveUrl host is live.browser-use.com (different from cloud.browser-use.com),
  with the cdp WebSocket encoded as a ?wss= query parameter.
- cookieDomains can be null on a freshly-created profile despite
  list_cloud_profiles' docstring describing it as an array.
- GET /usage returns 404 -- per-session cost lives on each browser
  record; aggregate billing only on the dashboard.

Style follows the claude-ai/share-export (browser-use#267) pattern of
markdown-skill-with-companion-py, sized at 222 + 161 LOC. Discovery
under helpers.py:163's current logic would resolve cloud.browser-use.com
to "cloud/" rather than "browser-use-cloud/" -- the skill folder name
mirrors the convention used by claude-ai/, vercel/, and tasksquad-ai/
which are also not auto-discoverable today; PR browser-use#165 is the broader fix
for that.

Refs: PR browser-use#300 (run.py precedence fix in the same area), PR browser-use#267
(claude-ai companion-script pattern), PR browser-use#288 (vercel dashboard skill
header style).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Copy link
Copy Markdown

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 84e7a2c0ae

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment on lines +138 to +139
except urllib.error.HTTPError as e:
record["action"] = f"stop_failed: HTTP {e.code}"
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Handle network errors when stopping zombie sessions

When PATCH /browsers/{id} hits a transient network failure (e.g., timeout/DNS/socket reset), urlopen raises URLError, but this loop only catches HTTPError. That exception currently bubbles out, aborting the run before remaining zombies are processed, which can leave older sessions running and still accruing cost during exactly the cleanup workflow this script is meant to automate.

Useful? React with 👍 / 👎.

Copy link
Copy Markdown
Contributor

@cubic-dev-ai cubic-dev-ai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

3 issues found across 2 files

Prompt for AI agents (unresolved issues)

Check if these issues are valid — if so, understand the root cause of each and fix them. If appropriate, use sub-agents to investigate and fix each issue separately.


<file name="agent-workspace/domain-skills/browser-use-cloud/cloud.md">

<violation number="1" location="agent-workspace/domain-skills/browser-use-cloud/cloud.md:1">
P2: This skill is placed in a directory name that the current domain-skill resolver will never surface for `cloud.browser-use.com`/`api.browser-use.com`, so it is effectively undiscoverable through normal skill loading.</violation>

<violation number="2" location="agent-workspace/domain-skills/browser-use-cloud/cloud.md:181">
P1: Documentation recommends piping a remote script directly into `sh` without integrity verification, creating a supply-chain/code-execution risk for operators.</violation>
</file>

<file name="agent-workspace/domain-skills/browser-use-cloud/cleanup-zombies.py">

<violation number="1" location="agent-workspace/domain-skills/browser-use-cloud/cleanup-zombies.py:106">
P2: `stop_browser()` can raise `URLError`, but the PATCH path only catches `HTTPError`, so a transient network failure can abort the cleanup run mid-loop and skip remaining browsers.</violation>
</file>

Reply with feedback, questions, or to request a fix. Tag @cubic-dev-ai to re-run a review, or fix all with cubic.

- **`_browser_use` has a 60s timeout** in `admin.py`; long-running ops
(large profile sync) need their own polling.
- **`profile-use` CLI is a separate install**:
`curl -fsSL https://browser-use.com/profile.sh | sh`.
Copy link
Copy Markdown
Contributor

@cubic-dev-ai cubic-dev-ai Bot May 5, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1: Documentation recommends piping a remote script directly into sh without integrity verification, creating a supply-chain/code-execution risk for operators.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At agent-workspace/domain-skills/browser-use-cloud/cloud.md, line 181:

<comment>Documentation recommends piping a remote script directly into `sh` without integrity verification, creating a supply-chain/code-execution risk for operators.</comment>

<file context>
@@ -0,0 +1,222 @@
+- **`_browser_use` has a 60s timeout** in `admin.py`; long-running ops
+  (large profile sync) need their own polling.
+- **`profile-use` CLI is a separate install**:
+  `curl -fsSL https://browser-use.com/profile.sh | sh`.
+- **`pageSize` caps at 100** silently — paginate via `pageNumber`.
+  `totalItems` in the envelope lets you size loops up front.
</file context>
Fix with Cubic

@@ -0,0 +1,222 @@
# Browser Use Cloud — Programmatic Automation
Copy link
Copy Markdown
Contributor

@cubic-dev-ai cubic-dev-ai Bot May 5, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2: This skill is placed in a directory name that the current domain-skill resolver will never surface for cloud.browser-use.com/api.browser-use.com, so it is effectively undiscoverable through normal skill loading.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At agent-workspace/domain-skills/browser-use-cloud/cloud.md, line 1:

<comment>This skill is placed in a directory name that the current domain-skill resolver will never surface for `cloud.browser-use.com`/`api.browser-use.com`, so it is effectively undiscoverable through normal skill loading.</comment>

<file context>
@@ -0,0 +1,222 @@
+# Browser Use Cloud — Programmatic Automation
+
+`https://api.browser-use.com/api/v3` (REST). All five endpoints below were
</file context>
Fix with Cubic

Comment thread agent-workspace/domain-skills/browser-use-cloud/cleanup-zombies.py
…n't abort the loop

A DNS/timeout/socket error during PATCH /browsers/{id} was bubbling out
of the loop, leaving remaining zombies running and still billing.
HTTPError is a subclass of URLError, so the existing clause stays first
and the URLError catch handles only the transport-level failures.
@sauravpanda sauravpanda merged commit 0c9597b into browser-use:main May 5, 2026
3 checks passed
@sauravpanda
Copy link
Copy Markdown
Collaborator

Thank you!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants