Core Usage

Reading Pages

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.

snapshot: a structured view of the page

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.

snapshot
$ chrome-use snapshot                    # full tree (verbose)
$ chrome-use snapshot -i                 # interactive elements only (recommended)
$ chrome-use snapshot -i -u              # include href url on 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 --json             # machine-readable output
✅ Tip
Start with 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.

Reading snapshot's output

The output is an indented accessibility tree, where indentation represents nesting depth:

snapshot -i · example output
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.

⚠️ Note: refs are reassigned every time
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.

filter / narrow
$ 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.

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.

ℹ️ Note
These 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.

get
$ 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).

✅ When text looks missing or wrong
Don't guess — just run 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.

read
$ 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

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), and --timeout <ms>. --json returns metadata alongside the content.

ℹ️ A doc-lookup workflow
For an unfamiliar docs site, start with 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 vs. snapshot/extract
Want readable prose (docs, a blog post, a guide)? Use 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).

eval --frame
$ chrome-use frames                                       # get the index / url first
$ chrome-use eval --frame accounts.google.com "location.href"
ℹ️ main world vs. isolated world
A cross-origin (cross-process) frame runs in its own main world; a same-process in-page frame runs in an isolated world (the DOM is readable, but the page JS's global variables are not).

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.

✅ Clicking such controls is good news
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.

Next steps

Once you understand the page, take those refs and text and do something with them.