agentsclimarketplace

Browser via browserhost

Skill dadamsuk/browserhost/.claude/skills/browser-via-browserhost

Drive a real, visible Chrome browser running on the user's desktop (Windows/macOS) from this remote/headless machine, over the Chrome DevTools Protocol via BrowserHost + agent-browser. Use this whenever you need to load a live web page from a real browser and your own built-in fetch/search isn't enough — e.g. pages that need JavaScript, a real (residential/office) IP, a logged-in session, or human handoff for login/CAPTCHA/2FA — and whenever you need to test a web app you are building by clicking through it in a real browser (open it, snapshot the DOM, fill forms, take screenshots, assert behaviour). Trigger on requests like "open this URL in a real browser", "scrape this site", "log into X and grab Y", "test my app / dev server in a browser", "click through the signup flow", "screenshot this page", or any web automation that needs an actual browser rather than an HTTP fetch. Prefer this over plain WebFetch when the page is JS-rendered, gated behind auth, or IP-sensitive.From its SKILL.md

Install
npx -y skills add dadamsuk/browserhost --skill browser-via-browserhost

Assembled from the repository path, not quoted from the project. Check it against their README if it does not work.

One thing to look at

  • 0 stars0 stars. Stars are a popularity signal and not a quality one, but at this level it is likely that nobody has read this closely except its author, and you would be relying on your own review.

SKILL.md

7.6 KB, ~1.7k tokens by cl100k_base, as published. Nobody here has run it

Driving a real desktop browser via BrowserHost

You are typically running on a remote/headless machine with no display and no browser. BrowserHost gives you one: it runs a real, visible Chrome on the user's desktop (usually Windows or macOS) and exposes it over the Chrome DevTools Protocol on port 9000. You connect to it with a small CLI called agent-browser. Because the browser physically runs on the user's desktop, pages load from a residential/office IP, the user can watch what you do, and they can step in by hand (e.g. finish a hard login) before you resume.

Use this for two things: retrieving live web information and testing software you are building in a real browser.

Step 1 — Ensure agent-browser is installed

agent-browser is the only client you need. Check it first:

agent-browser --help

If it's missing, install it before doing anything else (see https://github.com/vercel-labs/agent-browser). Every action below depends on it. The full, authoritative list of subcommands and flags lives at https://agent-browser.dev/commands — consult it whenever you need a command you don't already know.

Step 2 — Get the BrowserHost host address

You must know the hostname or IP of the desktop running BrowserHost. It's whatever name this machine can reach their desktop by — often a Tailscale name (desktop.tailnet.ts.net), a VPN/LAN hostname, or a plain IP. Call it HOST.

This skill remembers a default host in a file named host.txt next to this SKILL.md, so you only have to ask once:

  1. Read host.txt from this skill's own directory (the same folder as this file). If it exists and is non-empty, use its contents (trimmed) as HOST — don't ask the user.
  2. If it's missing or empty, ask the user for the host, then write the value to host.txt so future runs reuse it. (The first command line of an environment variable isn't reliable across sessions — the file is what persists.)
  3. If the remembered host turns out to be wrong (see the reachability check below) or the user gives a new one, overwrite host.txt with the corrected value.

host.txt is intentionally git-ignored — it holds one machine-specific line and never ships with the distributed skill.

Optionally confirm it's reachable (the control API + dashboard live on port 9001):

curl http://HOST:9001/api/health

A healthy server returns JSON with its version and the Chrome path in use. A timeout usually means a wrong HOST, a down tunnel/VPN, or the server isn't running — surface that to the user rather than retrying blindly.

Step 3 — Pick a session name

Every connection carries a session query parameter naming a browser instance:

  • The first connect to a new name auto-launches a fresh Chrome on the desktop.
  • Reconnecting to the same name reuses that browser, so cookies, logins, and open pages persist across separate agent-browser calls.
  • Different names are fully isolated (separate Chrome, separate profile).

Use a stable, descriptive name so your state persists across commands and the user can spot it in the dashboard — a good default is the name of this agent/system or the task (e.g. claude-build, scrape-acme). Names must match ^[A-Za-z0-9._-]+$. Optionally append &who=<label> to the URL so the dashboard shows who's driving (e.g. &who=claude@ci).

Step 4 — Drive the browser

Point agent-browser at the fixed universal URL, varying only the session value. You never manage ports or per-session URLs — just the session name and the command:

agent-browser --cdp "ws://HOST:9000/cdp?session=<name>" open https://theurl.com
  • Replace HOST (Step 2) and <name> (Step 3).
  • The session name goes in the URL query (?session=...). Do not use agent-browser's own local --session flag for this — it never reaches BrowserHost.
  • Use wss:// only if the user has terminated TLS in front of the proxy.

Run as many commands as you need against the same URL — state carries over because the session is reused:

# Cold start: launches Chrome on the desktop and loads the page
agent-browser --cdp "ws://HOST:9000/cdp?session=claude-build" open https://example.com

# Later command, same session: reuses the same browser and its state
agent-browser --cdp "ws://HOST:9000/cdp?session=claude-build" snapshot

If a connection is rejected at the WebSocket upgrade, you almost certainly omitted or malformed the session query parameter — check the URL before anything else.

For every other subcommand (clicking, typing, waiting, get, screenshots, etc.), defer to https://agent-browser.dev/commands — it's the source of truth, so look there rather than guessing flags.

Workflows

Retrieving web information

  1. open the target URL on your session.
  2. Read the page with snapshot / get (see the agent-browser docs); the output is returned to you on stdout — parse what you need from it.
  3. Navigate, click, or search further. The session persists, so multi-step flows and logged-in pages keep working across commands.

Example — "use a real browser to get the headlines from https://news.bbc.co.uk":

agent-browser --cdp "ws://HOST:9000/cdp?session=news" open https://news.bbc.co.uk
agent-browser --cdp "ws://HOST:9000/cdp?session=news" snapshot   # headlines come back on stdout

Testing software you're building

  1. Make sure the desktop browser can reach your app. If your dev server runs on this remote machine, the desktop must be able to hit it (same tunnel/VPN, or an address it can reach). If unsure how the desktop should reach your dev server, ask the user.
  2. open your app's URL on the session.
  3. Drive it like a user — click, type, navigate — and use snapshot/get/screenshots to assert the UI behaves as expected.
  4. Because the browser is real and visible on the desktop, the user can watch and intervene (e.g. complete a manual login) before you continue on the same session.

Practical notes

  • Persistence: reuse the same session name to keep cookies/logins; use a new name for a clean browser.
  • Human handoff: if a step needs a human (hard CAPTCHA, 2FA, an awkward login), say so — the user can act in the live browser on their desktop, then you continue on the same session.
  • One fixed endpoint: only the session name and the command change between calls; the host, port 9000, and /cdp path stay constant.
  • More commands: always treat https://agent-browser.dev/commands as authoritative for what agent-browser can do.

What ships with it

Read from the repository

Just SKILL.md. No reference files, no scripts.

Keep looking

Skills are one crate of 326,286. Ordering is by how many stacks a row turns up in, so the top of any crate is what has actually been picked rather than what has the most stars.