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
npx -y skills add dadamsuk/browserhost --skill browser-via-browserhostAssembled 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:
- Read
host.txtfrom this skill's own directory (the same folder as this file). If it exists and is non-empty, use its contents (trimmed) asHOST— don't ask the user. - If it's missing or empty, ask the user for the host, then write the value to
host.txtso future runs reuse it. (The first command line of an environment variable isn't reliable across sessions — the file is what persists.) - If the remembered host turns out to be wrong (see the reachability check below) or the
user gives a new one, overwrite
host.txtwith 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-browsercalls. - 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 useagent-browser's own local--sessionflag 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
openthe target URL on your session.- 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. - 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
- 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.
openyour app's URL on the session.- Drive it like a user — click, type, navigate — and use
snapshot/get/screenshots to assert the UI behaves as expected. - 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
sessionname and the command change between calls; the host, port9000, and/cdppath stay constant. - More commands: always treat https://agent-browser.dev/commands as authoritative
for what
agent-browsercan do.
What ships with it
Read from the repository
Just SKILL.md. No reference files, no scripts.