Core Usage
Reading Pages
For task-specific CLI guidance, load chrome-use skills get core/reading. Ordinary clicks and form actions are already covered by core.
snapshot turns the page into
an accessibility tree with refs — you click and type based on it; get text
grabs body text across every frame, piercing even closed shadow DOM.
Valid incremental snapshots return JSON refs only for nodes in the delta. A no-change delta has empty refs; the complete live session map and previously captured refs remain available. A full-tree fallback keeps the normal full-snapshot behavior.
read --filter uses literal, ASCII-case-insensitive text matching, not a regex. It prefers matching page headings with their descendants, then matching sections. Use read --outline to find a heading. snapshot --filter separately accepts a regex. read --help lists the reading options.
snapshot: a structured view of the page
After cross-site navigation or reconnecting, page reads use the current document. If the page keeps changing while its private reading context is being recreated, the read fails explicitly; observe the page again before acting.
snapshot generates the page structure from the accessibility tree. By default it prints the full tree (fairly verbose);
in practice you almost always add -i: keep only interactive elements,
each carrying a ref. Pass it as @eN to a following command to act on it.
For scoped, depth-limited, regex-filtered or budgeted snapshots, JSON refs contains only references rendered in the returned excerpt. The session keeps its complete live ref map; narrowing output does not invalidate a previously captured ref. Sparse-page detection still uses the complete map.
$ chrome-use snapshot # full tree (verbose)
$ chrome-use snapshot -i # interactive elements only (recommended)
$ chrome-use snapshot -i -u # include each link's absolute url (first 400 links)
$ chrome-use snapshot -i -c # compact: drop empty structural nodes
$ chrome-use snapshot -i -d 3 # depth limit of 3 levels
$ chrome-use snapshot -i --dom # list actionable elements from a DOM walk (pierces shadow roots)
$ chrome-use snapshot --json # machine-readable output
snapshot -i by default. It's small, contains only what you can act on,
and gives stable, usable @ref values — the proper entry point for driving clicks and typing.
Interactive snapshots add context only to repeated controls with the same role and name when named parent lines do not already distinguish them. Context omits the control’s own name and punctuation, stays within about 100 characters (60 for unnamed controls), and must differ between controls. Unique controls have no context; use a scoped or full snapshot for missing details such as a unique product’s price.
Keep input focused
Use snapshot -i -c when empty structural nodes add no context, and scope reads to the panel you need. Use a full tree when compact output omits necessary context. Re-read with --diff only when the previous observation leaves a question. Byte counts are not token counts; measure each separately.
Text and refs are the default. For a visual question, add --with-screenshot <path> to a snapshot or observed action to capture pixels alongside the read. Do not capture images on every step when labels and values answer the question. See settling and observation limits.
Reading snapshot's output
The output is an indented accessibility tree, where indentation represents nesting depth:
Page: Example - Log in
URL: https://example.com/login
- heading "Log in" [level=1, ref=e1]
- textbox "Email" [ref=e2]
- textbox "Password" [ref=e3]
- button "Continue" [ref=e4]
- link "Forgot password?" [ref=e5]
Each line has the format - <role> "<accessible name>" [<attributes>, ref=eN].
Pass the ref as @eN to a command to act on it, for example
click @e4.
ref values are renumbered on every snapshot. Don't cache an old
@eN and reuse it across operations — after the page changes, run snapshot again first and grab the new ref.
Filtering a huge snapshot
Synology DSM, NAS / router admin panels, and ExtJS apps render many independent "application windows"
into a single accessibility tree, and snapshot -i can easily blow past the token limit and
bury the control you want. Don't pipe to tail — narrow it precisely with filters.
$ chrome-use snapshot -s "#main" # scope to one container with a CSS selector
$ chrome-use snapshot -i -f "SSH|端口|应用" # keep matching lines + their ancestors (regex)
-f/--filter <regex> keeps only the matching lines plus their ancestor context,
with refs intact; -s <css> scopes the whole tree to one
window's container. The two can be stacked.
Re-read a page for a few bytes
$ chrome-use snapshot -i --diff # only what changed since the last snapshot
$ chrome-use snapshot -i --max-bytes 4000 # cut between nodes, report what was omitted
$ chrome-use snapshot -i --max-bytes 4000 --from 70 # read on from where it stopped
After an action, most of the tree is what it was. --diff returns only the lines
that changed since this session's last snapshot of the same page, with the
same options: on a 143 KB HN comment thread, an unchanged re-read costs
1 byte instead of 143,490. With no valid baseline — no previous
snapshot, the page navigated, different options — it returns the full tree and says
which, because an empty diff and an unchanged page are indistinguishable.
--max-bytes <n> solves a different problem: unlike -i/-s/-d/-f,
a budget needs no advance knowledge of what you are looking for. It
cuts only on whole-node boundaries (truncating the string would leave a severed
[ref=eN]) and tells you what it left out and where to resume:
truncated: nodes 0–70 of 1908 (1838 omitted).
--diff or --observe?--observe (it rides on the action).
To simply look at the page again, use --diff (it rides on snapshot).
Validation errors show up too
When a form refuses to submit, the reason is appended to the -i output as a top-level
alert line, for example - alert "字数已超过 8 个字" or
- alert "Email is required" — even when the message is just a styled
<span> (.is-error, .invalid-feedback,
[role=alert], aria-live) that -i would otherwise filter out as a
non-interactive element.
alert lines are informational and deliberately carry no ref (you read it, you don't click it).
So when a click submission does nothing, don't guess the reason — just run
snapshot -i again and read those alert lines.
get text: reading body text unstructured
When you don't need a ref and just want to read text, use get text. It can read the whole page, a single element,
skip navigation boilerplate, and even pierce closed shadow DOM.
$ chrome-use get text # whole page — aggregates all frames by default (see below)
$ chrome-use get text @e1 # visible text of a single element (a CSS selector works too)
$ chrome-use get text --main # body only — skips nav / header / sidebar
$ chrome-use get text --pierce # pierce closed shadow DOM (injected panels)
$ chrome-use frames # list each frame + where the text lives
$ chrome-use get html @e1 # innerHTML
$ chrome-use get attr @e1 href # any attribute
$ chrome-use get value @e1 # value of an input
$ chrome-use get title # page title
$ chrome-use get url # current URL
$ chrome-use get count ".item" # count matching elements
Whole-page text spans frames by default
chrome-use get text without a selector aggregates the visible text of every frame
— the top-level document, same-process child frames, and cross-origin iframes — so you won't silently miss
content hidden inside an iframe (Yahoo Auctions / Rakuten / Mercari product descriptions, embedded checkout / spec frames).
Each child frame is delimited by a ----- frame [kind] url ----- marker. You don't need to remember any flag;
it reads all frames by default (--all-frames remains as an explicit alias).
chrome-use get text to read everything. To see the structure (which frame
holds what), run chrome-use frames; to strip boilerplate (global nav/header/footer,
"related products" sidebars), use get text --main. If the content is lazy-loaded, first
scroll it into view before reading.
read: pull a URL as agent-readable text
read [url] fetches a URL and does its best to hand back clean
markdown/text: it prefers a .md version and a nearby
llms.txt, and falls back to readable text extracted from the HTML when neither
exists. Omit the URL and it reads the rendered DOM of the
active tab instead. It has a different job from snapshot/extract:
read pulls human-facing prose/markdown, while
snapshot/extract pull interactive elements / structured data.
$ chrome-use read https://docs.example.com/guide # read a URL
$ chrome-use read https://docs.example.com/guide --outline # just the heading outline
$ chrome-use read # read the active tab
$ chrome-use read https://news.ycombinator.com --links # plus a "## Links" list: [text](absolute URL)
Common flags: --raw (return the response body untouched), --require-md
(fail unless the response is text/markdown), --llms <index|full>
(the nearest llms.txt's index or full view), --outline (heading
outline only), --filter <text> (keep only matching sections/headings),
--timeout <ms>, and --links (append a ## Links section with
the page's links as absolute URLs, unique, the first 100 by default, --max-links <n> up to
1000; a cut list says how many it left out; a URL over 2048 bytes is omitted and counted, never truncated into
a different address; scanning, de-duplication and output are bounded, and a cut makes the count "at least N"). --json returns metadata alongside the content.
read https://site/docs/ --llms index
to list the pages its llms.txt advertises (it walks up to the nearest
llms.txt), then read <page> --require-md to demand the
markdown version; without --require-md it falls back to HTML-extracted prose.
--llms can't be combined with --outline.
read. Want
interactive elements to click or type into? Use the snapshot above.
Want structured JSON? Use extract.
eval: running inside a specific frame
eval runs in the main frame by default. It won't silently bind to whatever frame
Chrome happens to return — a bare eval always targets the top-level document. To run inside a child frame
(for example a cross-origin Google account picker), use
--frame <index|url-substring|@ref|css-selector>
(index / url come from chrome-use frames).
$ chrome-use frames # get the index / url first
$ chrome-use eval --frame accounts.google.com "location.href"
Piercing closed shadow DOM
Some injected UIs (a browser extension's debug panel, Web Components) render into a
closed shadow root that eval / innerText can't read.
chrome-use get text --pierce reads through closed shadow roots and child documents via CDP's DOM tree
— use it when the content is clearly on screen (a screenshot shows it) but get text /
eval returns empty.
snapshot -i is built from the accessibility tree, and the AX tree already pierces
closed shadow roots — a closed-shadow <button> /
[role=button] shows up as an ordinary @ref and clicks as usual.
Only a semantically empty clickable <div> inside a closed root
can dodge both the AX tree and the cursor-element scan.
Whole page inside shadow roots: automatic DOM-walk fallback
Some web-component SPAs (developer.apple.com/contact, for example) render the entire page inside shadow
roots and the accessibility tree comes back with no refs at all. snapshot / snapshot -i
then no longer print "(no interactive elements)": they automatically list actionable elements from a
DOM.getDocument(pierce:true) walk (open and closed shadow roots, same-process child documents).
Those [ref=eN] work with click / type / fill like normal refs;
the JSON carries source: "dom" plus a note line, and roles / names are derived from
tags and attributes. snapshot --dom forces that path.
Masked values, placeholder selects, errors inside iframes
A field holding a card number, CVC, expiry, password or one-time code shows <filled 19 chars> in snapshot and get value instead of its value (decided by autocomplete, type=password, name/id or the label). Pass --reveal-values only when you need to check the value itself; it then lands in the transcript.
A select still sitting on a disabled or "Select…" option shows (nothing selected; shows "Select") instead of looking chosen. A field the page has flagged carries invalid, and validation messages inside cross-origin frames (Stripe and other payment widgets) are listed as alert lines like the page's own.
Next steps
Once you understand the page, take those refs and text and do something with them.