BLOG
Install Agent-Browser: CLI Setup and Remote Runtime
Install agent-browser, wire it to a hosted Chromium runtime, and skip local Playwright browser downloads. Step-by-step CLI and CDP setup.
# Install Agent-Browser: CLI Setup and Remote Runtime
To install agent-browser, you install a CLI package and point it at a browser it can drive. The CLI itself is small; the real decision is where the browser lives. You can let it launch a local Chromium build, or you can connect it to a hosted runtime over the Chrome DevTools Protocol (CDP) and skip the local download entirely. This guide covers both paths, the trade-offs between them, and the production criteria that matter once you move past a laptop demo.
If you have read Remote Browser for AI agents, you already know the runtime layer is the part that breaks at scale. This post is the concrete install path: package, config, connection, and verification.
What agent-browser actually is
Agent-browser is a browser automation CLI built for AI agents. It exposes commands for navigation, clicking, typing, screenshots, and DOM extraction, and it can drive a browser either locally or over CDP. That second capability is the one worth understanding, because it decouples the CLI from the browser binary.
Two things follow from that decoupling:
- You do not need Chrome, Chromium, or Playwright's browser bundles on the machine running the CLI.
- The browser can live on infrastructure sized for the workload, not for your laptop.
The CLI is the control surface. The browser is the execution surface. Most install problems come from conflating the two.
Install the CLI
Agent-browser ships as an npm package. Install it globally if you want the command on your PATH, or as a project dependency if you want version pinning.
# Global install
npm install -g agent-browser
# Or pin it in a project
npm install --save-dev agent-browserVerify the binary resolves:
agent-browser --version
agent-browser --helpIf --help lists navigation and session commands, the CLI is installed. If it does not, check your Node version and npm prefix before debugging anything else. A surprising share of "install failed" reports are PATH problems, not package problems.
The local browser path and its costs
By default, an automation CLI expects a browser it can launch. With Playwright underneath, that means running playwright install to fetch browser binaries. That command downloads Chromium, Firefox, and WebKit builds into a cache directory, and it is where most install friction lives.
Things that go wrong with local browser installs:
- Disk and image size. Browser bundles add a large amount of data to CI images and containers.
- Version drift. A
playwright installon one machine can pull a different build than another, so tests pass locally and fail in CI. - Missing system libraries. Headless Chromium needs shared libraries that minimal container images do not ship.
- No persistence. Every fresh container re-downloads unless you cache the browser directory.
You can manage all of this. Teams do. But it is ongoing maintenance, and it is unrelated to whatever your agent is actually trying to accomplish.
If you want to keep browsers local, run playwright install deliberately and pin the Playwright version so the browser revision is deterministic. If you want to stop maintaining that, read on.
The remote runtime path
A hosted runtime gives you a Chromium session you connect to over CDP. You install the CLI, request a session, get a WebSocket endpoint, and connect. No browser binary on your machine.
This is the same mechanism Playwright uses for connectOverCDP, documented in the Playwright CDP guide. The protocol is standard; what differs is who operates the browser.
Remote Browser provides hosted Chromium sessions with CDP access, Playwright, Puppeteer, and Selenium compatibility, a live viewer for debugging, persistent profiles, configurable browser settings, and session isolation. You can see the connection surface in the documentation.
Comparison: local vs. hosted browser
| Dimension | Local browser | Hosted Chromium runtime |
|---|---|---|
| Install step | playwright install downloads binaries | None; connect over CDP |
| Image size | Large added footprint | CLI only |
| Version determinism | Manual pinning required | Managed by the runtime |
| System libraries | You install them | Not your concern |
| Session persistence | Local profile dirs | Persistent profiles via API |
| Debugging | Local headed mode | Live viewer + CDP |
| Scaling | Bound by host resources | Session-based, metered |
| Best for | Single-machine dev, offline work | CI, agents, multi-session workloads |
The table is not an argument that local is wrong. It is an argument that local and hosted solve different problems, and the install instructions diverge accordingly.
Connect the CLI to a remote browser
Once you have a session endpoint, connecting is a few lines. The pattern below uses Playwright's connectOverCDP, which is the same call agent-browser makes internally.
import { chromium, Browser, Page } from 'playwright';
interface SessionInfo {
cdpUrl: string;
}
async function connectToRemoteBrowser(
session: SessionInfo
): Promise<{ browser: Browser; page: Page }> {
// connectOverCDP returns a Browser bound to the remote instance.
const browser = await chromium.connectOverCDP(session.cdpUrl, {
timeout: 30_000,
});
// Reuse the existing context so cookies and storage persist
// across reconnects within the same session.
const context = browser.contexts()[0] ?? (await browser.newContext());
const page = context.pages()[0] ?? (await context.newPage());
await page.goto('https://example.com', { waitUntil: 'domcontentloaded' });
return { browser, page };
}
async function main(): Promise<void> {
const { browser, page } = await connectToRemoteBrowser({
cdpUrl: process.env.CDP_URL!,
});
console.log('Title:', await page.title());
// Do not call browser.close() on a shared remote session
// unless you intend to end it. Disconnect instead.
await browser.close();
}
main().catch((err) => {
console.error(err);
process.exit(1);
});Two details matter here. First, connectOverCDP is Chromium-only; Firefox and WebKit do not expose CDP in the same way, which is why hosted runtimes standardize on Chromium. Second, closing the browser object ends the remote session in most implementations. If you want to keep the session alive between runs, disconnect rather than close, and reconnect with the same session ID.
Verify the install end to end
A working install is not "the command ran." It is a full round trip. Check these in order:
- CLI resolves.
agent-browser --versionreturns a version string. - Session endpoint is reachable. A WebSocket handshake to the CDP URL succeeds.
- Browser responds.
browser.version()returns a Chromium build string. - Page control works. Navigate, read the title, take a screenshot.
- Reconnect works. Disconnect, reconnect with the same session, confirm cookies persist.
If step 5 fails, your problem is session lifecycle, not installation. That distinction saves time.
Common install failures
`connectOverCDP` times out. Usually a network path issue: the endpoint is not reachable from your environment, or a proxy is intercepting the WebSocket upgrade. Test the raw WebSocket connection before blaming the CLI.
Browser launches but pages are blank. Often a missing waitUntil or a navigation that races the page load. Use domcontentloaded or networkidle explicitly rather than relying on defaults.
Session dies between runs. You called browser.close() instead of disconnecting, or the session hit an idle timeout. Persistent profiles and session reuse are covered in the runtime documentation.
Version mismatch errors. The Playwright client version and the remote Chromium build can drift. Pin your Playwright version and check the runtime's supported browser versions.
Auth state disappears. You are creating a new context each run instead of reusing the existing one. Reuse browser.contexts()[0] when the session is meant to persist.
Production criteria before you commit
Installing the CLI takes minutes. Choosing where the browser runs is the decision that lasts. Evaluate on these axes:
- Session lifecycle. Can you create, reuse, and terminate sessions explicitly? Do idle timeouts match your workload?
- Profile persistence. Can you keep cookies, localStorage, and auth state across runs without re-authenticating?
- Isolation. Are sessions isolated from each other, so one agent's state cannot leak into another's?
- Observability. Can you watch a live session when something fails, or are you limited to logs and screenshots?
- Network controls. Can you route traffic through proxies and configure browser settings for the sites you target?
- Usage controls. Do you have visibility into session consumption before the bill arrives?
Remote Browser addresses these with hosted Chromium sessions, CDP access, persistent profiles, a live viewer, session isolation, and configurable browser settings. Current limits and metering are on the pricing page; check there rather than assuming a specific concurrency ceiling.
When local is still the right call
Hosted runtimes are not universally better. Keep browsers local when:
- You are developing offline or on an unreliable network.
- You need a browser build the runtime does not offer.
- Your workload is a single short script run occasionally.
- You are debugging browser internals that require direct filesystem access.
For everything else, the maintenance cost of local browser installs tends to exceed the cost of connecting to a managed session. The remote browser online guide walks through the hosted path in more depth.
Next steps
Install the CLI, then decide where the browser lives. If you go remote, connect over CDP, verify the full round trip including reconnect, and treat session lifecycle as a first-class part of your design rather than an afterthought.
Start with the documentation for the connection details, and review pricing before you scale a workload. The install is the easy part. Getting session lifecycle right is what keeps agents running in production.