Core Usage
Extracting Data
When what you want is the data on a page rather than to act on it, don't dump the whole
HTML into your context. chrome-use offers a full ladder of extraction techniques from light to heavy: a structured
snapshot, precise reads by ref, custom-shaped eval, community site adapters, all the way up to the
one-shot extract --schema. This page helps you pick the cheapest one for each kind of page.
Pick the cheapest tool first
Driving a real browser is heavy work. chrome-use is only worth starting up when you genuinely need a logged-in session, interaction, JS rendering, or an anti-bot page. To read a piece of public, static text, don't open a browser at all. Use the table below to decide whether to open a browser at all.
| What you want | What to use |
|---|---|
| Discover what's out there / find sources | WebSearch |
| A specific fact on a static or public page | WebFetch or curl (no browser) |
| Structured data from a known site (GitHub issues, Reddit/HN search, Bilibili/Twitter feeds), especially when logged in | chrome-use site <name>/<cmd> (see below) — skip snapshot+click |
| Structured data from any page (no community adapter) — tables, search results, feed rows, dashboards | chrome-use extract --schema '{rows,fields}' — clean JSON in one call |
| A logged-in session, interaction, JS rendering, or an anti-bot page | chrome-use (this tool) |
| A page the user saved earlier / an internal system | chrome-use find-url <keywords> |
Structured snapshot: snapshot --json
To make a model reason about page content, the best input is a structured snapshot.
snapshot -i --json outputs the interactive elements together with their refs as a single line of
parseable JSON — compact and stable, ready to feed straight into downstream logic. For how to read the snapshot
itself, see Reading Pages.
# structured snapshot — best for letting AI reason over page content
$ chrome-use snapshot -i --json > page.json
Precise extraction: get text / get attr
Once you already have an @ref from a snapshot, reading by ref is the least effort:
get text pulls the visible text, get attr pulls a given attribute (such as a link's
href). Refs are reassigned on every snapshot, so snapshot first, then read.
# targeted extraction by ref
$ chrome-use snapshot -i
$ chrome-use get text @e5
$ chrome-use get attr @e10 href
get text also accepts a CSS selector; pair it with switches like --main (body only, skip
nav/sidebar) and --pierce (read through closed shadow DOM). For more ways to locate elements, see
Finding Elements.
Any shape: extract with eval
For data that needs a custom shape, like tables and lists, a snippet of JavaScript is the most direct:
querySelectorAll in the page and map it into the array of objects you want. eval runs in
the page's MAIN world, so it reads the real DOM directly.
# feed the script to eval --stdin via a heredoc
$ cat <<'EOF' | chrome-use eval --stdin
const rows = document.querySelectorAll("table tbody tr");
Array.from(rows).map(r => ({
name: r.cells[0].innerText,
price: r.cells[1].innerText,
}));
EOF
eval --stdin (heredoc), eval --file <path>, or eval -b <base64>.
Inline chrome-use eval "..." gets mangled by shell escaping and only works for simple ASCII expressions.
tail/head/pipe it. eval --json outputs a single line of
parseable JSON, ready for programmatic consumption.
MAIN-world state persists across calls
Because eval runs in the page's MAIN world and state persists across calls, a
top-level const x/let x/var x in one call collides with the next
(SyntaxError: Identifier 'x' has already been declared). The fixes: use non-colliding variable names,
assign to window.x, or wrap the whole snippet in an IIFE
(() => { const x = …; return x; })().
Site adapters: the cheapest path to "structured data from site X"
A site adapter is a small piece of community-written JS that hits a site's own JSON API
from your logged-in tab and returns clean structured data — no clicking, no scraping, no screenshots,
much cheaper than snapshot+click. Prefer one when it exists.
One shot: extract --schema
When there's no community adapter and you don't feel like writing eval, use
extract --schema: give it a {rows, fields} shape and it extracts tables, search results,
feed rows, and dashboards into clean JSON in a single call — no N rounds of
find/get, and no dumping the whole page's HTML into your context to blow out the window.
# rows = selector for the repeating container; fields = what to pull per row
# a field is either shorthand CSS (text by default) or { "sel": "…", "get": "text|@attr|html|value" }
$ chrome-use extract --schema '{"rows":".product","fields":{"name":".name","price":".price","href":{"sel":"a","get":"@href"}}}'
# with rows, you get a JSON array — one object per matched container
[
{"name": "Widget A", "price": "$12.00", "href": "/p/a"},
{"name": "Widget B", "price": "$8.50", "href": "/p/b"}
]
rows, fields read against the whole document and return one object — handy for
page-header / metadata:
extract --schema '{"fields":{"title":"h1","canonical":{"sel":"link[rel=canonical]","get":"@href"}}}'.
For a long schema, pass it via --schema-file <path> or --stdin (heredoc).
rows and field selectors are CSS. If rows isn't valid CSS or
matches nothing, extract auto-detects the page's dominant repeating container
(li/tr/a repeated class) as a fallback; if there genuinely is none, it returns a
diagnostic listing the repeating containers that ARE present
(li×3, a[href*=pulls]×3) instead of a signal-less []. An array-shaped schema
works too: {"items":[{"title":"…","url":"@href"}]}.
extract --schema is one call over one page. To accumulate across pages and filter by condition, wrap
it in a script loop: paginate → extract → merge. Measured: crawling 3 HN pages for high-score stories
drops from 13+ calls to one. See Scripting & Batching.
How to choose: a cheat card
The same page of data often has several routes; roughly from cheap to expensive, this is the order. The full "which extraction tool" decision table (with a "why" column) is maintained on the Site Adapters page.