agent-browser open # Launch browser (no nav); stays on about:blankagent-browser open <url> # Launch + navigate (aliases: goto, navigate)agent-browser read [url] # Fetch agent-readable text, or read rendered active-tab DOMagent-browser click <sel> # Click element (--new-tab to open in new tab)agent-browser dblclick <sel> # Double-clickagent-browser fill <sel> <text> # Clear and fillagent-browser type <sel> <text> # Type into elementagent-browser press <key> # Press key (Enter, Tab, Control+a) (alias: key)agent-browser keyboard type <text> # Type at current focus (no selector needed)agent-browser keyboard inserttext <text> # Insert text without key eventsagent-browser keydown <key> # Hold key downagent-browser keyup <key> # Release keyagent-browser hover <sel> # Hover elementagent-browser focus <sel> # Focus elementagent-browser select <sel> <val> # Select dropdown by value or visible labelagent-browser check <sel> # Check checkboxagent-browser uncheck <sel> # Uncheck checkboxagent-browser scroll <dir> [px] # Scroll (up/down/left/right, --selector <sel>)agent-browser scrollintoview <sel> # Scroll element into viewagent-browser drag <src> <dst> # Drag and dropagent-browser upload <sel> <files> # Upload filesagent-browser screenshot [path] # Screenshot (--full for full page)agent-browser screenshot --annotate # Annotated screenshot with numbered element labelsagent-browser screenshot --if-changed # Recommended: skip unchanged images to save tokensagent-browser screenshot --threshold 0.01 # Ignore changes affecting at most 1% of pixelsagent-browser screenshot --screenshot-dir ./shots # Save to custom directoryagent-browser screenshot --screenshot-format jpeg --screenshot-quality 80agent-browser pdf <path> # Save page as PDFagent-browser snapshot # Accessibility tree with refsagent-browser eval <js> # Run JavaScriptagent-browser connect <port|url> # Connect to browser via CDPagent-browser stream enable [--port <port>] # Start runtime WebSocket streamingagent-browser webmcp list # List experimental page toolsagent-browser webmcp invoke <tool> --params @input.jsonagent-browser stream status # Show runtime streaming state and bound portagent-browser stream disable # Stop runtime WebSocket streamingagent-browser close # Close browser (aliases: quit, exit)agent-browser close --all # Close all active sessionsagent-browser mcp # Start an MCP stdio server
Browser responses automatically announce WebMCP tools on first discovery and when the catalog changes. Summaries contain only names, brief descriptions, origins, and frame IDs. Choose a relevant tool, then fetch its full schema with agent-browser webmcp list <tool> --frame <frame-id> --json before invoking it. Schemas and annotations are never included proactively. Unchanged catalogs and pages without tools add no context. JSON exposes updates as data.webmcp; CLI and MCP text include the same bounded summary. See WebMCP for update semantics and security.
Clicks fail before dispatch when another element covers the target's click point. The error names the covering element, for example covered by <div#consent-banner>. Dismiss or interact with that element, take a fresh snapshot, then retry the original action.
Headless Chromium screenshots hide native scrollbars for consistent image output. Pass --hide-scrollbars false when launching to keep native scrollbars visible.
agent-browser get text <sel> # Get text contentagent-browser get html <sel> # Get innerHTMLagent-browser get value <sel> # Get input valueagent-browser get attr <sel> <attr> # Get attributeagent-browser get title # Get page titleagent-browser get url # Get current URLagent-browser get cdp-url # Get CDP WebSocket URLagent-browser get count <sel> # Count matching elementsagent-browser get box <sel> # Get bounding boxagent-browser get styles <sel> # Get computed styles
read fetches a URL without launching Chrome. Omit the URL to read the rendered DOM of the active tab in the current browser session, including browser auth state and client-side updates. Explicit URL reads send Accept: text/markdown by default, try the same URL with .md appended when the first response is not markdown, walk ancestor paths toward / to find the nearest llms.txt for a matching docs link, print markdown or plain text when available, and fall back to readable text extracted from HTML. --llms and --require-md with no URL use the active tab URL because they depend on HTTP resources. read does not read llms-full.txt unless you ask for it.
Options: --raw prints the response body without HTML extraction, --require-md fails unless the server returns Content-Type: text/markdown, --outline prints a compact heading outline for one page, --llms index prints a compact nearest-ancestor llms.txt link list, --llms full reads the nearest-ancestor llms-full.txt, --filter <text> narrows page sections, llms links/sections, or outline headings, and --timeout <ms> changes the request timeout. Global safeguards such as --allowed-domains, --content-boundaries, and --max-output also apply to read fetches and output.
agent-browser wait <selector> # Wait for elementagent-browser wait <ms> # Wait for timeagent-browser wait --text "Welcome" # Wait for text (substring match)agent-browser wait --url "**/dash" # Wait for URL patternagent-browser wait --load domcontentloaded # Wait for DOMContentLoadedagent-browser wait --load load # Wait for the load eventagent-browser wait --load networkidle # Use only for pages known to become quietagent-browser wait --fn "condition" # Wait for JS conditionagent-browser wait --download [path] # Wait for downloadagent-browser wait --fn "!document.body.innerText.includes('Loading...')" # Wait for text to disappearagent-browser wait "#spinner" --state hidden # Wait for element to disappear
After a page change, prefer a selector, text, URL, or JavaScript condition that represents the state you need. Use networkidle only when the page is known to become quiet, because SSE, WebSockets, polling, and long-polling can keep it from resolving.
agent-browser download <sel> <path> # Click element to trigger downloadagent-browser wait --download [path] # Wait for any download to complete
Use --download-path <dir> (or AGENT_BROWSER_DOWNLOAD_PATH env) to set a default download directory. Without it, downloads go to a temporary directory that is deleted when the browser closes.
See Files & Clipboard for upload, download, local file, screenshot, PDF, and clipboard workflows.
Use --human with click, drag, or mouse move for curved, eased movement from the current cursor position. For mouse move, --duration sets the target total milliseconds including browser response time, --steps sets the number of events, and --seed makes the path reproducible. A slow browser can still extend the requested duration.
agent-browser set viewport <w> <h> [scale] # Set viewport size (scale for retina, e.g. 2)agent-browser set device <name> # Emulate device ("iPhone 14")agent-browser set geo <lat> <lng> # Set geolocationagent-browser set offline [on|off] # Toggle offline modeagent-browser set headers <json> # Extra HTTP headersagent-browser set credentials <u> <p> # HTTP basic auth for current and future tabsagent-browser set media [dark|light] # Emulate color scheme (persists for session)
Use --color-scheme for persistent dark/light mode across all commands:
agent-browser --color-scheme dark open https://example.com
agent-browser cookies # Get all cookiesagent-browser cookies set <name> <val> # Set cookieagent-browser cookies clear # Clear cookiesagent-browser storage local # Get all localStorageagent-browser storage local <key> # Get specific keyagent-browser storage local set <k> <v> # Set valueagent-browser storage local clear # Clear allagent-browser storage session # Same for sessionStorage
agent-browser tab # List tabs (each row shows tabId and label)agent-browser tab new [url] # New tabagent-browser tab new --label docs [url] # New tab with a user-assigned labelagent-browser tab <t<N>|label> # Switch to a tab by id or labelagent-browser tab close [t<N>|label] # Close a tab (defaults to active)agent-browser window new # Open new browser windowagent-browser frame <sel> # Switch to iframe by CSS selectoragent-browser frame @e3 # Switch to iframe by element refagent-browser frame main # Back to main frame
Tab ids are stable strings of the form t1, t2, t3. They're never reused within a session, so t2 keeps pointing at the same tab even as other tabs are opened or closed. The t prefix mirrors the @e1 element-ref convention and is not interchangeable with positional integers — agent-browser tab 2 errors with a teaching message; use t2.
You can also assign a memorable label (docs, app, admin) at tab-creation time and use it anywhere an id is accepted:
agent-browser tab new --label docs https://docs.example.comagent-browser tab docs # switch to the docs tabagent-browser snapshot # populate refs for docsagent-browser click @e3 # click uses docs's refsagent-browser tab close docs # close by label
Labels are never auto-generated and never rewritten on navigation — an agent that names a tab docs keeps that name until the tab is closed. Labels are unique within a session; creating a second tab with an existing label errors.
Tabs opened through tab new or click --new-tab inherit the session's setup before their first document loads: user agent, set headers, set credentials, origin-scoped --headers, init scripts, route rules, and emulation overrides (color scheme, timezone, locale, geolocation, offline). Turning offline mode off or setting headers to {} restores the default setup for future tabs.
tab list --json also reports each tab's CDP targetId, and target ids are accepted anywhere a tab ref is accepted (tab <targetId>, tab close <targetId>). Unlike t<N> ids, which are per-daemon counters, target ids stay stable across daemon restarts. Each session is bound to its active tab by target id and returns to it after a daemon restart; with --pin-tab the binding is strict and a closed bound tab produces a tab_gone error instead of a silent fallback. JSON errors include code: "tab_gone", data.targetId, and optional sanitized data.lastUrl. Batch output carries the recovery object under result. See CDP Mode for the multi-session workflow.
Refs (@e1, etc.) are scoped to the tab that was active when the snapshot ran, so switch tabs first, then snapshot and interact:
Browsers discard background tabs to save memory, leaving a tab with no renderer to drive. Switching to a discarded tab reactivates it, which reloads the page and resets its unsaved state; the switch result adds "revived": true so the reload is visible rather than silent. A tab whose page is paused by a JavaScript dialog is alive rather than discarded: the switch leaves it untouched and adds "dialogBlocked": true. Resolve the dialog with dialog accept or dialog dismiss and the tab keeps its state. Closing the active tab onto a discarded successor revives it the same way and reports "activeTabRevived": true.
snapshot --delta returns full, unchanged, or incremental updates per tab and option set. URL changes or large deltas return full state; --full resets the baseline. Apply a delta’s changes to ref metadata and treeChange to the previous tree: split on newlines, replace deleteCount lines at zero-based startLine with lines, then rejoin. Apply both to baseRevision before advancing to revision.
Iframes are detected automatically during snapshots. Iframe nodes are resolved and their content is inlined beneath the iframe element in the snapshot output. Refs assigned to elements inside iframes carry frame context, so click, fill, and other interactions work without manually switching frames.
agent-browser snapshot -i# @e3 [Iframe] "payment-frame"# @e4 [input] "Card number"# @e5 [button] "Pay"# Interact directly using refs — no frame switch neededagent-browser fill @e4 "4111111111111111"agent-browser click @e5# Or switch frame context for scoped snapshotsagent-browser frame @e3agent-browser snapshot -i # Only elements inside that iframeagent-browser frame main # Return to main frame
The frame command accepts element refs (@e3), CSS selectors ("#my-iframe"), or frame name/URL.
agent-browser dialog accept [text] # Accept dialog (with optional prompt text)agent-browser dialog dismiss # Dismiss dialogagent-browser dialog status # Check if a dialog is currently open
By default, alert and beforeunload dialogs are automatically accepted so they never block the agent. confirm and prompt dialogs still require explicit handling. Use --no-auto-dialog (or AGENT_BROWSER_NO_AUTO_DIALOG=1) to disable automatic handling.
When a JavaScript dialog (alert, confirm, prompt) is pending, all command responses include a warning field with the dialog type and message.
agent-browser trace start # Start traceagent-browser trace stop [path] # Stop and save traceagent-browser profiler start # Start Chrome DevTools profilingagent-browser profiler stop [path] # Stop and save profile (.json)agent-browser record start <path> # Start video recording (.webm/.mp4, 30 fps; needs ffmpeg)agent-browser record start <path> --fps 60 # Record at 60 fps (--fps accepts 1-60)agent-browser record start <path> --cursor # Include an animated mouse pointeragent-browser record start <path> --contact-sheet # Also save a timestamped PNG summaryagent-browser record start <path> --contact-sheet-threshold 0.02 # Tune changed-frame selectionagent-browser record stop # Stop and save videoagent-browser record restart <path> # Stop current and start new recordingagent-browser console # View console messagesagent-browser console --json # JSON output with raw CDP argsagent-browser console --clear # Clear console logagent-browser errors # View page errorsagent-browser errors --clear # Clear error logagent-browser highlight <sel> # Highlight elementagent-browser inspect # Open Chrome DevTools for the active page
Recording requires ffmpeg on PATH. See Debugging for console, error, dialog, trace, highlight, and DevTools workflows. See Video Recording for recording requirements and record workflows, and Profiler for performance profiles.
agent-browser auth save <name> [opts] # Save auth profileagent-browser auth login <name> # Login using saved credentialsagent-browser auth login <name> --no-navigate # Use active page after origin validationagent-browser auth login <name> --credential-provider <plugin> [--item <ref>] [--url <url>] # Resolve credentials from pluginagent-browser auth login <name> --username-selector <s> --password-selector <s> [--submit-selector <s>] # Override selectors for one loginagent-browser auth list # List saved profiles (names and URLs only)agent-browser auth show <name> # Show profile metadata (no passwords)agent-browser auth delete <name> # Delete a saved profileagent-browser plugin add <ref> # Add a plugin from npm or GitHubagent-browser plugin list # List configured pluginsagent-browser plugin show <name> # Show one configured pluginagent-browser plugin run <name> <type> --payload <json> # Run an arbitrary plugin request
--password-stdin: read password from stdin (recommended to avoid shell history exposure)
--username-selector <sel>: custom CSS selector for username field
--password-selector <sel>: custom CSS selector for password field
--submit-selector <sel>: custom CSS selector for submit button
auth login filters matching controls by their layout size, computed visibility and opacity, and disabled/readonly state, including custom CSS selectors. If a selected credential field is replaced or redirects focus before entry, the command fails without submitting.
auth login navigates with load and then waits for the username/password/submit selectors to appear before interacting. This improves reliability on SPA login pages where fields render after initial page load.
Use --no-navigate after an in-page click, challenge clearance, consent dismissal, or other stateful setup that must survive credential entry:
agent-browser open https://example.com/agent-browser click "a[href='/login']"agent-browser auth login work --no-navigate
The flag suppresses only the initial auth-login navigation. It requires an existing active top-level HTTP(S) page and compares that page with the effective credential URL by scheme, host, and effective port. Paths, queries, and fragments may differ. Waiting, filling, clicking submit, and any submit-triggered navigation are unchanged. A command-level --url overrides profile or provider URL metadata and acts as the expected-origin constraint rather than a navigation destination.
Plugin login options:
--credential-provider <plugin>: resolve credentials from a configured plugin
--no-navigate: use the active top-level page after validating it against the effective credential origin
--username-selector <sel>: selector override for this login
--password-selector <sel>: selector override for this login
--submit-selector <sel>: selector override for this login
Credential provider plugins run out-of-process over the agent-browser.plugin.v1 stdio JSON protocol. They return credentials to the daemon for a single login and agent-browser does not save those credentials locally.
Other plugin capabilities use the same protocol:
browser.provider: use the plugin with --provider <name> to return a CDP WebSocket URL
launch.mutate: append local launch args, extensions, or init scripts before Chrome starts
command.run: run arbitrary namespaced requests through agent-browser plugin run
plugin run is for command.run and custom capabilities. Core capabilities and protocol request types use their dedicated command paths.
echo "pass" | agent-browser auth save github --url https://github.com/login --username user --password-stdinagent-browser auth login githubagent-browser plugin add agent-browser-plugin-vault --name vaultagent-browser auth login my-app --credential-provider vault --item "My App"agent-browser auth login my-app --credential-provider vault --item "My App" --no-navigate --url https://identity.example.com/loginagent-browser --provider cloud-browser open https://example.comagent-browser plugin run captcha captcha.solve --payload '{"siteKey":"...","url":"https://example.com"}'agent-browser auth list
When --confirm-actions is set, certain action categories return a confirmation_required response instead of executing immediately. Use confirm or deny to approve or reject the action.
agent-browser confirm <confirmation-id> # Approve a pending actionagent-browser deny <confirmation-id> # Deny a pending action
agent-browser state save <path> # Save auth state to fileagent-browser state load <path> # Load auth state from fileagent-browser state list # List saved state filesagent-browser state show <file> # Show state summaryagent-browser state rename <old> <new> # Rename state fileagent-browser state clear [name] # Clear states for session nameagent-browser state clear --all # Clear all saved statesagent-browser state clean --older-than <days> # Delete old states
agent-browser profiles # List available Chrome profilesagent-browser profiles --json # List profiles as JSONagent-browser --profile Default open https://gmail.com # Reuse a profile's login state
agent-browser dashboard [start] # Start the dashboard server (default port: 4848)agent-browser dashboard start --port <n> # Start on a specific portagent-browser dashboard start --allowed-origins <origins> # Allow exact HTTPS reverse-proxied browser originsagent-browser dashboard stop # Stop the dashboard server
Loopback dashboard origins are accepted by default without an access token. For a reverse-proxied or forwarded URL, pass its exact browser origin with --allowed-origins or set AGENT_BROWSER_DASHBOARD_ALLOWED_ORIGINS. Every configured origin must be a valid exact HTTPS origin. Ports must be integers from 1 to 65535. Unknown options, missing values, invalid ports, and malformed origins fail without starting the server. The command prints private tokenized access URLs only for external origins; open the matching URL once to establish the browser session and do not share it. Open the normal http://localhost:<port> URL for local access. The browser stays on the dashboard origin; per-session tabs, status, and stream traffic are proxied internally, so session ports do not need to be exposed. Stop the running dashboard before changing the port or allowed origins.
Diagnose your install, auto-clean stale daemon files, and optionally repair common problems.
agent-browser doctor # Full diagnosis (env, Chrome, daemons, config, providers, network, launch test)agent-browser doctor --offline --quick # Local-only, fastestagent-browser doctor --fix # Also run destructive repairs (reinstall Chrome, purge old state, ...)agent-browser doctor --webgpu # Also run a live WebGPU render probe (see the WebGPU page)agent-browser doctor --json # Structured JSON output for agents
Exit code is 0 if all checks pass (warnings are fine), 1 if any fail. See the Installation page for the full check catalog.
Use natural language to control the browser via AI. The chat command translates instructions into agent-browser commands, executes them, and streams the AI response. Requires AI_GATEWAY_API_KEY to be set.
agent-browser chat "open google.com and search for cats" # Single-shot instructionagent-browser chat # Interactive REPL (type quit to exit)echo "summarize this page" | agent-browser chat # Piped inputagent-browser -q chat "summarize this page" # Quiet: text only, no tool calls shownagent-browser -v chat "fill in the login form" # Verbose: show commands and their outputagent-browser --model openai/gpt-4o chat "take a screenshot" # Override the default AI modelagent-browser --json chat "open example.com" # Structured JSON output
Chat-specific options:
--model <name> # AI model (or AI_GATEWAY_MODEL env, default: anthropic/claude-sonnet-4.6)-v, --verbose # Show tool commands and their raw output-q, --quiet # Show only the AI text response (hide tool calls)
Some flows need routes, cookies, or init scripts configured before the first navigation (SSR debug, auth on protected origins, etc.). open without a URL launches the browser but stays on about:blank, leaving room to stage state. batch makes it one CLI invocation:
React commands require --enable react-devtools at launch (installs the React DevTools hook before any page JS runs). vitals and pushstate work on any site.
agent-browser open --enable react-devtools <url> # Launch with React hook installedagent-browser react tree # Full component treeagent-browser react inspect <fiberId> # Inspect one componentagent-browser react renders start # Begin fiber render recordingagent-browser react renders stop [--json] # Stop + print profileagent-browser react suspense [--only-dynamic] [--json] # Suspense boundaries + classifier # --only-dynamic hides the "static" listagent-browser vitals [url] [--json] # LCP/CLS/TTFB/FCP/INP + hydration
Works on any React app (Next.js, Remix, Vite+React, CRA, TanStack Start, React Native Web, etc.). vitals and pushstate are framework-agnostic.
Run an embedded axe-core audit against the current page or navigate to a URL first. The vendored engine works without a CDN request and runs under strict page CSP. It runs private partial audits across the page's frame tree and merges serialized results without page messaging, so page-provided window.axe values remain intact and iframe violations retain their frame selector paths. Accessibility audits require a CDP browser and are not available with Safari or iOS WebDriver sessions.
agent-browser a11y # Audit the current pageagent-browser a11y https://example.com # Navigate, then auditagent-browser a11y --tags wcag2a,wcag2aa # Filter by axe rule tagsagent-browser a11y --selector "#main" # Scope to a subtreeagent-browser a11y https://example.com --json # Structured results
The default output lists violations and incomplete checks with impact, rule ID, fix guidance, and failing-node paths. JSON output preserves axe's target selector path arrays, including nested arrays for shadow DOM boundaries and multiple entries for frame boundaries.
agent-browser open --init-script <path> # Register before first navigation (repeatable)agent-browser addinitscript <js> # Register at runtime (returns identifier)agent-browser removeinitscript <identifier> # Remove from every tab in the session
See Init Scripts & Extensions for launch-time scripts, runtime scripts, built-in React DevTools, and extensions.
Starts a Model Context Protocol server over stdio. MCP clients launch this command as a subprocess and exchange newline-delimited JSON-RPC on stdin and stdout. The server defaults to MCP protocol 2025-11-25 and accepts older supported client protocol versions during initialization.
The default tools profile is core, which keeps MCP context small for everyday browser automation. Use --tools all for the full typed CLI parity surface, or combine profiles with commas, such as --tools core,network,react.
With --tools all, the server exposes typed tools across the CLI command surface, including navigation, snapshots, input, waits, screenshots/PDF, get/is/find, mouse, network, storage, cookies, tabs, windows, frames, dialogs, tracing, recording, accessibility audits, clipboard, auth, state, iOS, diff, React, vitals, sessions, skills, plugins, doctor, dashboard, install, upgrade, chat, eval, and close.
Common tools include:
agent_browser_tools_profiles
agent_browser_open
agent_browser_snapshot
agent_browser_click
agent_browser_fill
agent_browser_type
agent_browser_press
agent_browser_wait_for_selector
agent_browser_screenshot
agent_browser_get_url
agent_browser_eval
agent_browser_close
Each tool has typed fields such as url, selector, text, key, session, allowedDomains, and idleTimeout, so MCP clients show meaningful approval prompts instead of raw command arrays. The common allowedDomains array maps to --allowed-domains and activates the same WebRTC containment and launch-mode restrictions. The common idleTimeout string maps to --idle-timeout, accepts values such as 30s, 5m, 1h, or raw milliseconds, and accepts 0 to disable idle shutdown. Each tool also accepts extraArgs for advanced CLI flags and exact CLI parity. Tool discovery is paginated and includes read-only/open-world annotations so modern MCP clients can load the large typed surface incrementally.
Tool invocations use the same config files and environment variables as the CLI. Use session in the tool arguments, or set AGENT_BROWSER_SESSION, to isolate browser state.
Chain commands with && in a single shell invocation. The browser persists via a background daemon, so chaining works naturally and is more efficient than separate calls:
agent-browser open example.com && agent-browser wait --load domcontentloaded && agent-browser snapshot -iagent-browser fill @e1 "user@example.com" && agent-browser fill @e2 "pass" && agent-browser click @e3agent-browser open example.com && agent-browser wait --load load && agent-browser screenshot page.png
Use && when you don't need to read intermediate output. Run commands separately when you need to parse output first (e.g., snapshot to discover refs, then interact with those refs).
agent-browser --allow-file-access open file:///path/to/document.pdfagent-browser --allow-file-access open file:///path/to/page.htmlagent-browser screenshot output.png
The --allow-file-access flag enables JavaScript to access other local files. Chromium only.
See Files & Clipboard for local files, uploads, downloads, screenshots, PDFs, and clipboard workflows.