Reference

Command Reference

This is the complete cheat sheet of every chrome-use command, alias, and flag. It's organized by command group so it's easy to scan and verify. To get a feel for the overall rhythm first, read the Core Loop; when a command doesn't work, check Troubleshooting.

ℹ️ Conventions
The @e1, @e2 in interaction commands are element references (refs) from snapshot output. Run snapshot -i first to get the refs, then act on them. Any command with a @ref always targets the tab that was active when the snapshot ran.

Navigation

Open, navigate, go back/forward, and close the browser. Without a URL, open just launches the browser and stops at about:blank — handy for registering network interceptors, cookies, or init scripts before the first real navigation.

navigation
# launch the browser only, no navigation; stops at about:blank
$ chrome-use open
# launch and navigate (aliases: goto, navigate); prepends https:// when no protocol
$ chrome-use open <url>
$ chrome-use back                # go back
$ chrome-use forward             # go forward
$ chrome-use reload              # reload
# SPA client-side navigation: auto-detects Next.js router.push, falls back to history.pushState
$ chrome-use pushstate <url>
$ chrome-use close               # close the browser (aliases: quit, exit)
$ chrome-use connect 9222        # connect over a CDP port

You can line up all the pre-navigation setup in one shot with batch — launch cleanly, register interceptors / cookies in order, then navigate. This suits SSR-only debugging (block everything except --resource-type script), authenticating against a protected origin, or capturing a clean react suspense / vitals state.

pre-navigation batch
$ chrome-use batch \
    '["open"]' \
    '["network","route","*","--abort","--resource-type","script"]' \
    '["cookies","set","--curl","cookies.curl","--domain","localhost"]' \
    '["navigate","http://localhost:3000/target"]'

Snapshot (page analysis)

snapshot gives you a structured accessibility view of the page — the starting point for all interaction. snapshot -i is recommended: it lists only interactive elements, so the output is compact and every ref is present.

snapshot
$ chrome-use snapshot            # full accessibility tree
$ chrome-use snapshot -i         # interactive elements only (recommended)
$ chrome-use snapshot -c         # compact output
$ chrome-use snapshot -d 3       # limit depth to 3
$ chrome-use snapshot -s "#main" # scope to a CSS selector
✅ Tip
snapshot -i only surfaces visible, interactive elements — it does not show hidden inputs or a control's actual submitted value. When a form "looks filled in" but won't pass validation, don't guess from the snapshot — inspect the DOM directly with eval.

Interactions

Drive the real browser with the @ref values from snapshot: click, type, check, drag, upload.

interactions
$ chrome-use click @e1           # click
$ chrome-use click @e1 --new-tab # click and open in a new tab
$ chrome-use dblclick @e1        # double-click
$ chrome-use focus @e1           # focus the element
$ chrome-use fill @e2 "text"     # clear then type
$ chrome-use type @e2 "text"     # type directly (no clear)
$ chrome-use press Enter         # press a key (alias: key)
$ chrome-use press Control+a     # key combo
$ chrome-use keydown Shift       # hold a key down
$ chrome-use keyup Shift         # release a key
$ chrome-use hover @e1           # hover
$ chrome-use check @e1           # check a checkbox
$ chrome-use uncheck @e1         # uncheck
$ chrome-use select @e1 "value"   # pick a dropdown option
$ chrome-use select @e1 "a" "b"   # multi-select
$ chrome-use scroll down 500     # scroll the page (default down 300px)
$ chrome-use scrollintoview @e1  # scroll element into the viewport (alias: scrollinto)
$ chrome-use drag @e1 @e2        # drag and drop
$ chrome-use upload @e1 file.pdf # upload a file
⚠️ Click "succeeds but nothing happens"
Autocomplete / menu <li> items often close when the input loses focus. If click reports success but the page doesn't react, retry that click with AGENT_BROWSER_CLICK_MODE=dom — DOM dispatch doesn't move focus the way a real pointer does, so the option still gets selected.

Reading information

Read text, HTML, attributes, values, bounding boxes, and computed styles from elements or the page.

get
$ chrome-use get text @e1        # element text
$ chrome-use get html @e1        # innerHTML
$ chrome-use get value @e1       # input value
$ chrome-use get attr @e1 href   # attribute
$ chrome-use get title           # page title
$ chrome-use get url             # current URL
$ chrome-use get cdp-url         # CDP WebSocket URL
$ chrome-use get count ".item"   # number of matching elements
$ chrome-use get box @e1         # bounding box
$ chrome-use get styles @e1      # computed styles (font, color, background, etc.)

Check state

is
$ chrome-use is visible @e1      # is it visible
$ chrome-use is enabled @e1      # is it enabled
$ chrome-use is checked @e1      # is it checked

Screenshots & PDF

screenshot / pdf
$ chrome-use screenshot          # save to a temp directory
$ chrome-use screenshot path.png # save to a specific path
$ chrome-use screenshot --full   # full-page screenshot
$ chrome-use pdf output.pdf      # save as PDF

Headless Chromium hides native scrollbars in screenshots for consistent image output. Pass --hide-scrollbars false at launch to keep the native scrollbars.

Recording

record
$ chrome-use record start ./demo.webm    # start recording
$ chrome-use click @e1                   # perform actions
$ chrome-use record stop                 # stop and save
$ chrome-use record restart ./take2.webm # stop the current one + start a new recording

Waiting

Wait for an element, text, URL, network idle, or any JS condition before asserting state.

wait
$ chrome-use wait @e1                     # wait for an element
$ chrome-use wait 2000                    # wait a number of milliseconds
$ chrome-use wait --text "Success"        # wait for text (or -t)
$ chrome-use wait --url "**/dashboard"    # wait for a URL pattern (or -u)
$ chrome-use wait --load networkidle       # wait for network idle (or -l)
$ chrome-use wait --fn "window.ready"     # wait for a JS condition (or -f)

Mouse control

mouse
$ chrome-use mouse move 100 200      # move the mouse
$ chrome-use mouse down left         # press a button
$ chrome-use mouse up left           # release a button
$ chrome-use mouse wheel 100         # wheel

Semantic locators

An alternative to refs: locate by role, text, label, placeholder, alt, title, testid, or position, and chain the action to perform directly after it.

find
$ chrome-use find role button click --name "Submit"
$ chrome-use find text "Sign In" click
$ chrome-use find text "Sign In" click --exact      # exact match only
$ chrome-use find label "Email" fill "user@test.com"
$ chrome-use find placeholder "Search" type "query"
$ chrome-use find alt "Logo" click
$ chrome-use find title "Close" click
$ chrome-use find testid "submit-btn" click
$ chrome-use find first ".item" click
$ chrome-use find last ".item" click
$ chrome-use find nth 2 "a" hover

Browser settings

set
$ chrome-use set viewport 1920 1080          # viewport size
$ chrome-use set viewport 1920 1080 2        # 2x retina (CSS size unchanged, higher-res screenshots)
$ chrome-use set device "iPhone 14"          # emulate a device
$ chrome-use set geo 37.7749 -122.4194       # geolocation (alias: geolocation)
$ chrome-use set offline on                  # toggle offline mode
$ chrome-use set headers '{"X-Key":"v"}'     # extra HTTP headers
$ chrome-use set credentials user pass       # HTTP basic auth (alias: auth)
$ chrome-use set media dark                  # emulate color scheme
$ chrome-use set media light reduced-motion  # light + reduced motion

Cookies & storage

cookies / storage
$ chrome-use cookies                     # get all cookies
$ chrome-use cookies set name value      # set a cookie
$ chrome-use cookies clear               # clear cookies
$ chrome-use storage local               # all of localStorage
$ chrome-use storage local key           # a specific key
$ chrome-use storage local set k v       # set a value
$ chrome-use storage local clear         # clear everything

Import cookies from cURL

Auto-detects the format: a JSON array of {name, value}, a DevTools → Network → Copy as cURL dump, or a bare Cookie header. Cookie values are never echoed back on error.

cookies set --curl
$ chrome-use cookies set --curl <file>                       # auto-detect JSON / cURL / Cookie header
$ chrome-use cookies set --curl <file> --domain example.com  # scope to a domain

Network interception

Intercept, block, mock responses, rewrite requests, or edit real responses. For in-depth usage, see the network section in the Core Loop.

network
$ chrome-use network route <url>              # intercept requests
$ chrome-use network route <url> --abort      # block requests
# mock a response (fulfill)
$ chrome-use network route <url> --body '{}' --status 200 --header K=V --content-type application/json
# rewrite a request (continue)
$ chrome-use network route <url> --method POST --set-body '{}' --set-header K=V --rewrite-url <u>
# edit a real response
$ chrome-use network route <url> --edit-status 503 --edit-header K=V --replace 'from=>to'
$ chrome-use network unroute [url]            # remove a route
$ chrome-use network requests                 # view tracked requests
$ chrome-use network requests --filter api    # filter requests

Intercept by resource type

network route --resource-type
# block scripts only (SSR-lock mode)
$ chrome-use network route '*' --abort --resource-type script
# replace images and fonts with empty responses
$ chrome-use network route '*' --resource-type image,font --body ''

Tabs & windows

Tab ids are stable strings like t1, t2 and are not reused within a session. Positional integers are not accepted — tab 2 errors; use t2. You can also give a tab a readable label (docs, app), interchangeable with the id.

tab / window
$ chrome-use tab                              # list tabs (with tabId and label)
$ chrome-use tab new [url]                    # new tab
$ chrome-use tab new --label docs [url]       # new tab with a readable label
$ chrome-use tab t2                           # switch by id
$ chrome-use tab docs                         # switch by label
$ chrome-use tab close                        # close the current tab
$ chrome-use tab close t2                     # close by id
$ chrome-use tab close docs                   # close by label
$ chrome-use window new                       # new window
ℹ️ refs belong to the tab active at snapshot time
The daemon maintains a single active tab, and @eN belongs to the tab that was active when the snapshot ran. To operate on another tab, switch to it first, then snapshot. Labels are never auto-generated, aren't rewritten after navigation, and are unique within a session.

Frames (iframe)

iframes are detected automatically during a snapshot, and their contents are inlined beneath the iframe element (one level of nesting). refs inside an iframe can be operated on directly; you can also switch frame context for a scoped snapshot.

frame
$ chrome-use frame "#iframe"     # switch to an iframe by CSS selector
$ chrome-use frame @e3           # switch to an iframe by element ref
$ chrome-use frame main          # return to the main frame

frame accepts three kinds of input: an element ref (frame @e3), a CSS selector (frame "#payment-iframe"), and a frame name / URL (matched against the browser's frame tree).

Dialogs

By default alert and beforeunload are accepted automatically so the agent doesn't block; confirm and prompt still need explicit handling. Use --no-auto-dialog to turn that behavior off.

dialog
$ chrome-use dialog accept [text]  # accept the dialog
$ chrome-use dialog dismiss        # dismiss the dialog
$ chrome-use dialog status         # check whether a dialog is open

Running JavaScript

eval runs in the page's MAIN world, so state persists and handlers fire. When your code contains nested quotes or special characters, -b / --stdin is more reliable — shell escaping is easy to get wrong.

eval
$ chrome-use eval "document.title"          # simple expressions only
$ chrome-use eval -b "<base64>"             # arbitrary JS (base64-encoded)
$ chrome-use eval --stdin                   # read the script from stdin

# multi-line scripts via stdin + heredoc:
$ cat <<'EOF' | chrome-use eval --stdin
const links = document.querySelectorAll('a');
Array.from(links).map(a => a.href);
EOF

Debug forms / hidden state with eval

form debugging
# dump every field's name → value, including hidden inputs and unchecked radios
$ chrome-use eval "JSON.stringify([...document.forms[0].elements].map(e=>({name:e.name,type:e.type,value:e.value,checked:e.checked})).filter(e=>e.name))"
# why won't it submit? ask the browser's own validity API
$ chrome-use eval "[...document.forms[0].elements].filter(e=>!e.validity?.valid).map(e=>e.name+': '+e.validationMessage)"

Single-pass scripting (batch / script)

Multi-step flows don't need one round-trip per command. batch runs a fixed sequence in one round-trip; script adds values between steps, loops, conditions, and asserts. See Single-pass Scripting.

script
# JSON op-list: value bus {{name.path}} + waitUntil/forEach/assert/return, --dry-run to validate
$ chrome-use script prog.json
$ chrome-use script - --dry-run < prog.json

# JS form: a synchronous JS program driven by cu.* helpers (ego's code-base idiom)
$ chrome-use script --timeout 120000 <<'JS'
  cu.open('https://news.ycombinator.com');
  const rows = cu.eval("[...document.querySelectorAll('.athing')].length");
  return { count: rows };
JS

Options: --timeout <ms>, --dry-run (validate the JSON program only), --yes (auto-confirm inside the script), --arg k=v (seed a variable). Exit codes: 0 ok, 1 runtime failure or failed assert, 2 invalid program.

State management

state
$ chrome-use state save auth.json    # save cookies, storage, and auth state
$ chrome-use state load auth.json    # restore saved state

Init scripts

init scripts
$ chrome-use open --init-script <path>       # register before the first navigation (repeatable)
$ chrome-use addinitscript <js>            # register at runtime (returns an identifier)
$ chrome-use removeinitscript <id>         # remove a registered init script

React / Web Vitals

The react ... commands require launching with --enable react-devtools; vitals and pushstate are framework-agnostic.

react / vitals
$ chrome-use open --enable react-devtools <url>    # launch with the React hook
$ chrome-use react tree                            # full component tree
$ chrome-use react inspect <fiberId>               # props / hooks / state / source
$ chrome-use react renders start                   # start recording re-renders
$ chrome-use react renders stop [--json]           # stop and print the render analysis
$ chrome-use react suspense [--only-dynamic] [--json]  # Suspense boundaries + classifier
$ chrome-use vitals [url] [--json]                 # LCP/CLS/TTFB/FCP/INP + hydration
$ chrome-use pushstate <url>                       # SPA client-side navigation (auto-detects Next router)

Debugging

console / errors capture is off by default — an active CDP Runtime domain is a detectable bot signal. Start the session with AGENT_BROWSER_CAPTURE_CONSOLE=1 when you need it.

debugging
$ chrome-use --headed open example.com   # show the browser window
$ chrome-use --cdp 9222 snapshot         # connect over a CDP port
$ chrome-use connect 9222                # alternative: the connect command
$ chrome-use console                     # view console messages (needs AGENT_BROWSER_CAPTURE_CONSOLE=1)
$ chrome-use console --limit 20          # only the last 20 console messages
$ chrome-use console --clear             # clear the console
$ chrome-use errors                      # view page errors (needs AGENT_BROWSER_CAPTURE_CONSOLE=1)
$ chrome-use errors --clear              # clear errors
$ chrome-use diagnose                    # why is the page blank: checks asset 404/MIME + mount state
$ chrome-use highlight @e1               # highlight an element
$ chrome-use inspect                     # open DevTools for this session
$ chrome-use trace start                 # start recording a trace
$ chrome-use trace stop trace.zip        # stop and save
$ chrome-use profiler start              # start profiling
$ chrome-use profiler stop trace.json    # stop and save the profile

Find pages the user saved (find-url)

Search local Chrome/Edge bookmarks by keyword — for internal systems or previously saved pages that public search can't reach. Reads locally; no browser / daemon required. Results are sorted by most recently added, and javascript: / data: bookmarks are skipped.

find-url
$ chrome-use find-url jira board          # all keywords must match (name or url)
$ chrome-use find-url --limit 10 invoices
$ chrome-use find-url --browser edge --profile "Profile 1" wiki
$ chrome-use find-url grafana --json      # {results:[{name,url,folder}], count}

Drive your real logged-in Chrome (extension)

Chrome 136 locked down --remote-debugging-port on the default profile, so to drive the user's existing logged-in window, chrome-use goes through a Chrome extension + native messaging — no port, no token, no per-use confirmation. A one-time install writes the native messaging host manifest:

extension
$ chrome-use extension install        # write the native messaging host manifest (one-time)
$ chrome-use extension connect        # auto-attach to the real logged-in tabs
$ chrome-use tab                      # list the real tabs it now controls
$ chrome-use tab t3                   # switch the session to one of them
$ chrome-use snapshot -i              # drive it like any normal session
$ chrome-use extension status         # is the host installed?
$ chrome-use extension uninstall      # remove the host manifest
✅ Install from the Chrome Web Store (recommended)
The Store build is stable across restarts and auto-updates (store id knfcmbamhjmaonkfnjhldjedeobeafmk). A loaded unpacked dev build can be disabled / dropped when Chrome restarts, silently breaking the relay — use the Store build for unattended scenarios.
ℹ️ Security
The extension↔host link is authenticated by Chrome (the extension id); the host↔chrome-use CDP link uses an unguessable URL in a 0600 file. --extension <path> is unrelated — that loads an extension into a freshly launched browser.

Global options

These flags go before the command and apply to the whole session. Note: headless mode is forbidden (a bot signal) — it's headed by default and always (stealth); on a display-less server, use AGENT_BROWSER_ALLOW_HEADLESS=1.

global options
$ chrome-use --session <name> ...    # isolated browser session
$ chrome-use --json ...              # JSON output, easy to parse
$ chrome-use --headed ...            # default and always on (stealth)
$ chrome-use --full ...              # full-page screenshot (-f)
$ chrome-use --cdp <port> ...        # connect over CDP
$ chrome-use -p <provider> ...        # cloud browser provider (--provider)
$ chrome-use --proxy <url> ...       # use a proxy server
$ chrome-use --proxy-bypass <hosts>   # hosts that bypass the proxy
$ chrome-use --headers <json> ...    # HTTP headers scoped to the URL origin
$ chrome-use --executable-path <p>   # custom browser executable
$ chrome-use --extension <path> ...  # load an extension (repeatable)
$ chrome-use --ignore-https-errors   # ignore SSL certificate errors
$ chrome-use --hide-scrollbars false # keep native scrollbars in headless Chromium screenshots
$ chrome-use --help                  # help (-h)
$ chrome-use --version               # version (-V)
$ chrome-use <command> --help       # detailed help for a command

Environment variables

environment
AGENT_BROWSER_SESSION="mysession"            # default session name
AGENT_BROWSER_EXECUTABLE_PATH="/path/chrome" # custom browser path
AGENT_BROWSER_EXTENSIONS="/ext1,/ext2"       # comma-separated extension paths
AGENT_BROWSER_INIT_SCRIPTS="/a.js,/b.js"     # comma-separated init script paths
AGENT_BROWSER_ENABLE="react-devtools"        # comma-separated built-in init features
AGENT_BROWSER_HIDE_SCROLLBARS="false"        # keep native scrollbars
AGENT_BROWSER_PROVIDER="browserbase"         # cloud browser provider
AGENT_BROWSER_STREAM_PORT="9223"             # override the WebSocket stream port
AGENT_BROWSER_HOME="/path/to/chrome-use"     # custom install location
AGENT_BROWSER_CLICK_MODE="dom"               # click strategy: ""(default) / "coord" / "dom"

Stealth / anti-detection knobs (fork)

stealth knobs
AGENT_BROWSER_CAPTURE_CONSOLE="1"     # enable console/errors capture (off by default; the Runtime domain is a bot signal)
AGENT_BROWSER_TIMEZONE="Asia/Tokyo"   # --launch only. native timezone override (IANA id or "auto")
AGENT_BROWSER_BLOCK_WEBRTC="1"        # --launch only. hide the local IP via WebRTC
AGENT_BROWSER_HIDE_CANVAS="1"         # --launch only. session-stable canvas/audio fingerprint noise
AGENT_BROWSER_ADAPTIVE_REF="0"        # disable adaptive @ref relocation (on by default)
⚠️ console / errors return empty by default
In this stealth fork, both return {"messages":[]} / {"errors":[]} plus a hint until you start the session with AGENT_BROWSER_CAPTURE_CONSOLE=1 — this keeps the CDP Runtime domain disabled on the common automation paths. When something doesn't work, cross-check Troubleshooting.