CLI Reference
Every command in cbrowser help for cbrowser 20.0. cbrowser help <command> prints the part of the help for one command.
The examples call cbrowser, as after npm install -g cbrowser. Without a global install, put npx in front: npx cbrowser doctor. cbrowser 20 needs Node.js 20.9 or newer.
Upgrading from 19.x? The Changelog lists everything 20.0 changed.
Global Options
Browser options
Commands that open a browser read these.
| Option | Description |
|---|---|
--browser <name> |
chromium (default), firefox or webkit |
--device <name> |
Emulate a device: its screen size, pixel ratio, touch and user agent. 200+ presets (see Device Emulation). An unknown name exits 1 and names the closest presets |
--viewport <WxH> |
Page size, such as 390x844, or a size name such as mobile or desktop-md (see Size names). With --device, it sets the size and the device keeps its pixel ratio, touch and user agent |
--geo <location> |
A location preset (cbrowser geo list) or lat,lon |
--locale <locale> |
Browser locale, such as fr-FR. Default: the host's |
--timezone <tz> |
Timezone, such as Asia/Tokyo. Default: the host's |
--headless / --no-headless |
Run without or with a visible window (default: headless) |
--no-persistent |
Use a throwaway profile. By default a persistent profile keeps cookies, storage and the last URL between commands |
--no-restore |
Skip restoring the saved URL, to keep the page state after interactions |
--url <url> |
Commands that act on a page open this URL first |
--record-video |
Record a video of the browser session |
--force |
Proceed with a red-zone action (see Constitutional-Safety) |
--help, --version |
Show help, or the version |
A --device or --geo on one command applies to that command only. device set and geo set change the default for later commands.
Without these flags, pages render at 1920x1080 in the host's locale and timezone, unless an environment variable or the config file says otherwise (see Configuration).
Some commands run their own engines (cross-browser, responsive, ai-visual and others). They take the browser flags they can honour and exit 1, with the reason, on one they cannot. Each command's section says which.
Writing flags
- A value follows its flag:
--max-pages 50or--max-pages=50. - A flag that takes no value, such as
--forceor--html, never takes the next word as its value. test-suite,cognitive-journey,evaluate,keyboard,capture,askanduninstallcheck their flags. An unknown flag exits 1, and the error lists the flags the command accepts.
Size names
--viewport and the responsive --viewports list take these names. The same names mean the same sizes in the MCP tools.
| Name | Size | Name | Size |
|---|---|---|---|
mobile-sm |
320x568 | tablet-lg |
1024x1366 |
mobile |
393x852 | desktop-sm |
1280x800 |
mobile-lg |
414x896 | desktop-md |
1440x900 |
mobile-xl |
428x926 | desktop |
1920x1080 |
tablet-sm |
768x1024 | desktop-lg |
1920x1080 |
tablet |
834x1194 | desktop-xl |
2560x1440 |
--viewport mobile sets the size only. --device mobile also emulates touch and a phone's user agent. In responsive, the mobile and tablet presets emulate their device.
Output options
These make output usable by screen readers, CI pipelines and scripts:
| Option | Description |
|---|---|
--no-color |
No ANSI colour codes. Setting NO_COLOR to any value does the same (no-color.org) |
--plain |
No emoji or box drawing. Pass, fail and warning marks print as [PASS], [FAIL] and [WARN] |
--json-output |
One JSON envelope on stdout. doctor, ask, extract, analyze and network list put their results in data; other commands return their printed lines in data.output |
cbrowser doctor --plain
cbrowser doctor --json-output
NO_COLOR=1 cbrowser status
Report files
Report commands (test-suite, compare-personas, empathy-audit, agent-ready-audit, ai-benchmark, webmcp-ready, competitive-benchmark):
--output <file>saves the JSON report.--htmlwrites an HTML report beside it, with.htmlin place of.json. When the--outputname already ends in.html, the HTML report goes to<name>.report.html, so it never overwrites the JSON.--htmlwithout--outputwrites a default name, such astest-report.html.
Visual commands (ai-visual test, cross-browser, responsive, ab) and coverage write one file: with --html, --output names the HTML report; without it, the JSON report. coverage without --html writes JSON only when the name ends in .json, and a text report otherwise.
Exit codes
A command exits 0 when it did what it says, and 1 when it did not: a failed test, assertion or check, a refused red-zone action, a navigation that landed on another page, an unknown subcommand or flag. Scripts and CI can rely on it.
Timeouts
There is no global --timeout. Page loads wait up to CBROWSER_TIMEOUT milliseconds (default 30000). These commands take their own --timeout:
| Command | --timeout means |
|---|---|
test-suite |
Time per step (default 30000 ms) |
evaluate |
How long --wait-for waits (default 30000 ms) |
hunt-bugs |
Time for the whole hunt (default 60000 ms) |
webmcp-ready |
Request timeout (default 30000 ms) |
capture start |
How long a trigger may take to fire (default 30s) |
daemon start |
Idle time before the daemon stops (default 30 minutes) |
The millisecond timeouts also take 5s or 2m. daemon start --timeout takes minutes, or 90s, 45m, 2h.
Diagnostics
doctor
Check the environment, with pass or fail for each part.
cbrowser doctor [--plain]
Checks:
- Node.js version
- Playwright Chromium: the browser is on disk
- Anthropic API key: a warning, not a failure, when missing. Only journeys need it
- Data directory: writable
doctor exits 1 when a check fails, so cbrowser doctor && ... stops on a broken setup.
status
Show the data directories, browsers, config and heal cache.
cbrowser status
version
cbrowser version
cbrowser --version
ask
Ask the CBrowser docs a question. It prints an AI answer grounded in the documentation, with its sources.
cbrowser ask "<question>" [options]
| Option | Description |
|---|---|
--context <text> |
What you are looking at: a URL, a tool, a score |
--json |
Print the answer as JSON |
Your question goes to cbrowser.ai. It needs no account or API key, and it is rate-limited.
cbrowser ask \
"Best persona for a screen reader?"
Navigation
navigate
Open a URL and take a screenshot. It prints the final URL, title, load time and screenshot path.
cbrowser navigate <url>
Takes the browser options. A navigation that lands on a different page (an interstitial, a redirect to another host) exits 1.
cbrowser navigate https://example.com
cbrowser navigate --device pixel-9 \
https://example.com
cbrowser navigate \
--geo san-francisco \
https://example.com
screenshot
Take a screenshot of a URL, or of the current page.
cbrowser screenshot [url] [path]
| Option | Description |
|---|---|
--no-restore |
Capture the current state after interactions instead of reloading the saved URL |
cbrowser screenshot \
https://example.com
cbrowser screenshot \
https://example.com home.png
cbrowser screenshot home.png \
--viewport mobile
scroll
Scroll the page.
cbrowser scroll <top|bottom|up|down>
cbrowser scroll <up|down> <px>
| Option | Description |
|---|---|
--url <url> |
Open this URL first |
up and down scroll 300 pixels unless you give a number. Without the daemon, the next command reloads the page, so the scroll position does not carry over. Start the daemon to keep it.
cbrowser daemon start
cbrowser navigate https://example.com
cbrowser scroll down 600
cbrowser screenshot below-fold.png
Interaction
Commands that act on a page take --url <url> to open it first.
click
Click an element. The selector can be text, a label, a role or CSS.
cbrowser click <selector> [options]
| Option | Description |
|---|---|
--url <url> |
Open this URL first |
--verbose |
On failure, list the clickable elements and an AI suggestion |
--debug-dir <dir> |
Save debug screenshots here |
--force |
Proceed with a red-zone click |
A click that is refused or finds nothing exits 1.
smart-click
Click with retries and alternative selectors.
cbrowser smart-click <selector>
| Option | Description |
|---|---|
--url <url> |
Open this URL first |
--max-retries <n> |
Retry attempts (default: 3) |
--retry-delay <ms> |
Delay between retries (default: 1000) |
--dismiss-overlays |
Dismiss overlays before clicking |
--force |
Proceed with a red-zone click |
A click refused as red zone is never retried with a different selector.
cbrowser smart-click "Login"
cbrowser smart-click "Add to Cart" \
--url https://shop.example.com
fill
Fill an input field.
cbrowser fill <selector> <value>
| Option | Description |
|---|---|
--url <url> |
Open this URL first |
--verbose |
On failure, list the input fields and an AI suggestion |
--debug-dir <dir> |
Save debug screenshots here |
cbrowser fill email "[email protected]"
hover
Hover over an element.
cbrowser hover <selector>
press
Press a single key, such as Enter, Tab, Escape or Control+a.
cbrowser press <key>
type
Type a string into the focused element.
cbrowser type "<text>" [--delay <ms>]
--delay is the pause per character (default: 50).
drag
Drag one element onto another.
cbrowser drag <source> <target>
upload
Set a file input's value.
cbrowser upload <selector> <file>
keyboard
Send a key sequence: chords, key names and literal text in one command.
cbrowser keyboard <token> [token...]
| Option | Description |
|---|---|
--selector <sel> |
Focus this element first |
--delay <ms> |
Delay between steps (default: 50) |
--hold <mod> |
Hold a modifier across the whole sequence |
--repeat <n> |
Repeat the whole sequence n times |
--text |
Treat every token as literal text (for + in text) |
--url <url> |
Open this URL first |
Each token is classified before it is sent. A token with modifiers is a chord (Control+A). A known key name is that key (Enter, Tab, ArrowLeft). Anything else is typed as literal text. An unknown key name in a chord is rejected, not typed: the error names it, lists the valid modifiers (Control, Shift, Alt, Meta, ControlOrMeta) and points to --text for literal text.
For a single key use press. For a single string use type.
cbrowser keyboard "Control+A" \
"Delete" "Hello world"
cbrowser keyboard "ArrowRight" \
--repeat 5 --hold Shift
cbrowser keyboard Tab Tab Enter \
--selector "#email" --delay 120
dismiss-overlay
Detect and dismiss a modal overlay.
cbrowser dismiss-overlay [options]
| Option | Description |
|---|---|
--type <type> |
auto (default), cookie, age-verify, newsletter or custom |
--selector <sel> |
Selector of the overlay's close button |
--url <url> |
Open this URL first |
Extraction
extract
Extract one kind of data from a page.
cbrowser extract [url] [kind]
<kind> is one of text (the default), links, headings, images or forms. Anything else exits 1. Give the URL first, or open it with --url. With --json-output, the data is in data.
cbrowser extract \
https://example.com links
cbrowser extract headings \
--url https://example.com
Scripting
evaluate
Run JavaScript in the page and print the result. eval is an alias with the same flags.
cbrowser evaluate "<js>" [options]
| Option | Description |
|---|---|
--force |
Required. Page script can click, submit or delete without the element safety gate, so evaluate refuses and runs nothing without it |
--file <path> |
Read the script from a file instead of argv |
--arg <json> |
Argument for the script (repeatable, JSON-typed) |
--json |
Always print JSON |
--raw |
Print the raw value, unquoted |
--wait-for <selector> |
Wait for the selector before evaluating |
--timeout <ms> |
How long --wait-for waits: ms, or 5s / 2m (default: 30000) |
--expect-truthy |
Exit 1 when the result is falsy (CI assertion) |
What you can pass. Any of these prints a value:
- An expression:
document.title - Statements, which print the last value as a console would:
const n = document.links.length; n * 2 - Functions declared or used inside the script:
function t() { return document.title }; t(), or[...document.links].map(a => a.pathname) - A script with a top-level
return, run as a function body - A function on its own,
(sel) => ..., which is called with the--argvalues
Pass a function when you want arguments. Each --arg is parsed as JSON and handed to the function in order, so a string argument needs its own quotes inside the shell quotes: --arg '"nav"'.
With the daemon running, evaluate runs in the daemon's browser with the same flags and prints the same way. Results such as 0, false and "" print too.
cbrowser evaluate "document.title" \
--force
cbrowser evaluate --force \
--arg '"Example"' \
"(t) => document.title.includes(t)"
cbrowser evaluate --file check.js \
--arg '"#main"' --expect-truthy \
--force
By default a string prints unquoted and an object prints as indented JSON. --json always prints JSON, so "hello" keeps its quotes. --raw prints the value as a plain string, so an object becomes [object Object].
--expect-truthy turns the command into an assertion: exit 0 on a truthy result, exit 1 on a falsy one, with the reason on stderr.
false
β Expected a truthy result, got false
run
Run one natural-language command.
cbrowser run "<command>"
run understands navigation, clicks, typing, back, forward, reload, select, wait for and scroll. A click or fill that fails inside run exits 1.
cbrowser run \
"go to https://example.com"
cbrowser run "click the login button"
cbrowser run \
"type 'hello' in the search box"
script
Run a file of natural-language commands, one per line. A step that fails exits 1.
cbrowser script <file>
Assertions
assert
Check the page with a natural-language assertion.
cbrowser assert "<assertion>" [opts]
| Option | Description |
|---|---|
--url <url> |
Open this URL first |
cbrowser assert "title is 'Home'"
cbrowser assert \
"page contains 'Welcome'"
cbrowser assert \
"url contains '/dashboard'"
cbrowser assert \
"'Login' button exists"
cbrowser assert "page has 3 items"
AI Selectors
ai find / ai click
Find, or find and click, an element by what it is for.
cbrowser ai find "<intent>"
cbrowser ai click "<intent>"
cbrowser ai find "cheapest product"
cbrowser ai click "login button"
An ai click that is refused or misses exits 1. --force reaches the click.
heal
Manage the self-healing selector cache.
| Command | Description |
|---|---|
heal stats |
Show cache statistics |
heal list [--domain <d>] |
List cached selector mappings |
heal clear [--domain <d>] |
Clear the cache, or one domain's entries |
heal test <selector> [--url <url>] |
Test whether a selector would be healed |
Testing
test-suite
Run tests written in plain English.
cbrowser test-suite <file.txt> [opts]
cbrowser test-suite --inline "<test>"
| Option | Description |
|---|---|
--inline <steps> |
Run one inline test, steps separated by ; |
--continue-on-failure |
Keep running after a test fails |
--screenshot-on-failure |
Take screenshots on failure (default: on) |
--output <file> |
Save the JSON report |
--html |
Write an HTML report (see Report files) |
--timeout <ms> |
Time per step (default: 30000) |
--dry-run |
Show the parsed steps without running them |
--fuzzy-match |
Case-insensitive fuzzy matching for assertions |
--step-through |
Pause before each step |
--capture |
Record the run to GIF, WebP or video |
--capture-fps <n> |
Capture frame rate (default: 10) |
--capture-format <list> |
gif, webp, webm, mp4 (default: gif) |
--capture-out <dir> |
Capture output directory |
It also takes the browser options (--device, --viewport, --browser, --geo, --locale, --timezone, --no-headless). Any other flag, such as --persona, exits 1.
Each run is saved under the suite's name for export and sends test.pass or test.fail to the webhooks subscribed to it. A failed test exits 1.
Test file format:
# Test: Login Flow
go to https://example.com
click the login button
type "[email protected]" in email field
click submit
verify url contains "/dashboard"
cbrowser test-suite login.txt --html
cbrowser test-suite login.txt \
--dry-run
cbrowser test-suite --inline \
"go to https://example.com ;
verify title contains Example"
The four --capture flags record pixels; see Screen Capture. A captured run prints its capture summary and manifest path after the results table.
export
Export the last run of a suite as JUnit XML or TAP.
cbrowser export junit <name> [output]
cbrowser export tap <name> [output]
<name> is the suite's name, which test-suite prints after each run. Without a saved run, export exits 1.
repair-tests
Analyze failing tests and suggest or apply repairs.
cbrowser repair-tests <file> [opts]
| Option | Description |
|---|---|
--auto-apply |
Apply the best repair |
--verify |
Re-run the repaired tests |
--output <file> |
Save the repaired tests. Needs --auto-apply |
--json-out <file> |
Save the repair report as JSON |
--json |
Print the repair report as JSON |
It also takes --device, --viewport, --browser and --no-headless for the browser the tests run in. With --auto-apply, tests that are still failing exit 1.
cbrowser repair-tests broken.txt
cbrowser repair-tests tests.txt \
--auto-apply --verify
cbrowser repair-tests tests.txt \
--auto-apply --output fixed.txt
flaky-check
Run tests several times to find flaky ones.
cbrowser flaky-check <file> [opts]
| Option | Description |
|---|---|
--runs <n> |
Runs per test (default: 5) |
--threshold <n> |
Flakiness percentage, 0 to 100, to flag (default: 20) |
--delay <ms> |
Delay between runs (default: 500) |
--output <file> |
Save the JSON report |
It also takes --device, --viewport, --browser and --no-headless. A --threshold outside 0 to 100, or not a number, exits 1.
cbrowser flaky-check tests.txt
cbrowser flaky-check tests.txt \
--runs 10 --threshold 25
coverage
Map which pages of a site your tests cover.
cbrowser coverage <url> [options]
cbrowser coverage gaps <url>
| Option | Description |
|---|---|
--tests <glob> |
Test files to analyze (default: tests/*.txt) |
--sitemap <url> |
Use a sitemap.xml instead of crawling |
--max-pages <n> |
Pages to crawl (default: 100) |
--include <pattern> |
Only paths matching the pattern |
--exclude <pattern> |
Leave out paths matching the pattern |
--min-coverage <n> |
Coverage % below which a page is flagged (default: 50) |
--html |
Write an HTML report |
--output <file> |
Save the report (see Report files) |
The crawl takes --device, --viewport, --browser and --no-headless. With --sitemap no browser runs, so those four exit 1. coverage gaps shows only untested pages and takes --tests and --sitemap.
cbrowser coverage \
https://example.com \
--tests "tests/*.txt"
cbrowser coverage \
https://example.com \
--html --output coverage.html
generate
Analyze a page and generate test scenarios. generate-tests is an alias.
cbrowser generate <url> [options]
| Option | Description |
|---|---|
--format <format> |
summary (default), cbrowser, playwright or all. Anything else exits 1 |
--output <file> |
Save to a file instead of printing |
cbrowser generate \
https://example.com \
--format playwright \
--output tests.spec.ts
analyze
Show a page's structure without generating tests: its title, forms, buttons, links, and whether it has login, search and navigation.
cbrowser analyze <url> [--output <f>]
--output saves the analysis as JSON. With --json-output, the analysis is in data.
record
record records actions, not pixels; for video, use capture.
| Command | Description |
|---|---|
record list |
List saved recordings |
record generate <name> |
Generate Playwright test code from a recording |
record start, record stop and record save exit 1. Each cbrowser command is its own process, so a recording cannot survive between them. To record a flow, write it as a test and run it in one process, with test-suite --inline ... --capture if you want video.
Journeys and Personas
These run cognitive journeys and need an Anthropic API key: each step is a model call. Set it with cbrowser config set-api-key <key>.
cognitive-journey
Simulate a person with patience, frustration and the chance to give up.
cbrowser cognitive-journey [options]
| Option | Description |
|---|---|
--start <url> |
Starting URL (required; --url also works) |
--goal <goal> |
Goal statement (required) |
--persona <name> |
Persona name or description (default: first-timer) |
--max-steps <n> |
Steps before giving up (default: 50) |
--max-time <s> |
Seconds before giving up (default: 120) |
--verbose |
Step-by-step narration and inner monologue |
--no-vision |
Text only: faster, less accurate |
--output <file> |
Save the JSON report |
--trace |
Record the journey to ~/.cbrowser/traces/<id>.jsonl |
--replay-trace <file> |
Replay a recorded journey: no model calls, no API key |
--persistent |
Use the shared browser profile. Default: a fresh one, so the persona arrives as a new visitor |
--timezone <tz> |
Override the persona's timezone |
--locale <loc> |
Override the persona's locale |
--geo <preset or lat,lon> |
Override the persona's location (also --geolocation) |
--capture, --capture-fps, --capture-format, --capture-out |
Record the run to GIF, WebP or video |
Any other flag exits 1. Without a display it runs headless unless you pass --no-headless. Each journey sends journey.complete to the webhooks subscribed to it.
cbrowser cognitive-journey \
--start https://example.com \
--goal "Sign up for an account" \
--persona first-timer
A replay is deterministic. A page that has changed since the recording stops the replay at the step that diverged.
cbrowser cognitive-journey \
--start https://example.com \
--goal "sign up" --trace
cbrowser cognitive-journey \
--start https://example.com \
--goal "sign up" \
--replay-trace trace.jsonl
explore
A short cognitive journey. It needs an Anthropic API key; without one it exits 1.
cbrowser explore <persona> [options]
| Option | Description |
|---|---|
--start <url> |
Starting URL (required; --url also works) |
--goal <goal> |
What to accomplish |
--record-video |
Record the exploration as video |
cbrowser explore first-timer \
--start https://example.com \
--goal "Find contact information"
compare-personas
Run the same journey as several personas and compare them.
cbrowser compare-personas [options]
| Option | Description |
|---|---|
--start <url> |
Starting URL (required) |
--goal <goal> |
What to accomplish (required) |
--personas <list> |
Comma-separated persona names |
--concurrency <n> |
Browsers at once (default: 3) |
--device <name> |
Device every journey emulates |
--viewport <WxH> |
Page size for every journey |
--output <file> |
Save the JSON report |
--html |
Write an HTML report |
--browser exits 1: cognitive journeys take no engine choice.
cbrowser compare-personas \
--start https://example.com \
--goal "Complete signup" \
--personas power-user,first-timer
persona
Manage personas.
| Command | Description |
|---|---|
persona list |
List built-in and custom personas |
persona create "<desc>" [--name <name>] |
Create a persona from a description |
persona show <name> |
Show a persona's settings |
persona delete <name> |
Delete a custom persona |
persona export <name> |
Write the persona to <name>.persona.json in the current directory |
persona import <file> |
Import a persona from JSON |
persona cleanup [--dry-run] |
Remove custom personas that fail validation |
cbrowser persona list
cbrowser persona create \
"elderly user new to computers" \
--name grandma
cbrowser persona export elderly-user
persona-questionnaire
Build a persona by answering questions about behaviour.
| Command | Description |
|---|---|
persona-questionnaire start |
Answer 13 questions: 8 core cognitive traits and the five Big Five dimensions |
persona-questionnaire start --comprehensive |
Answer 30 questions: all 25 cognitive traits and the five Big Five dimensions |
persona-questionnaire list-traits |
List the traits with descriptions |
persona-questionnaire lookup |
Look up the behaviours for a trait value |
start also takes --name <name> (asked for if left out) and --output <file> to save the answers as JSON.
Audits
agent-ready-audit
Grade a site A to F for AI-agent friendliness. No API key.
cbrowser agent-ready-audit <url>
| Option | Description |
|---|---|
--device <name> |
Device to audit on, such as iphone-16 |
--geo-region <region> |
Run through a configured regional proxy. Exits 1 if none is configured (see Geo-Proxy) |
--lightpanda |
Use Lightpanda instead of Chromium (see Lightpanda) |
--output <file> |
Save the JSON report |
--html |
Write an HTML report |
Grades on findability (35%), stability (30%), agent perceivability (20%) and semantics (15%).
cbrowser agent-ready-audit \
https://example.com --html
ai-benchmark
Run agent-ready-audit on several sites and rank them.
cbrowser ai-benchmark --urls <list>
| Option | Description |
|---|---|
--urls <list> |
Comma-separated URLs (required) |
--concurrency <n> |
Sites audited at once (default: 3) |
--device <name> |
Device every audit uses |
--output <file> |
Save the JSON report |
--html |
Write an HTML report |
--viewport and --browser exit 1. A site that cannot be scored exits 1.
cbrowser ai-benchmark --html --urls \
"https://a.com,https://b.com"
empathy-audit
Simulate how people with disabilities experience a site.
cbrowser empathy-audit <url> [opts]
| Option | Description |
|---|---|
--goal <goal> |
Task goal. Without one, the page is checked for barriers and no API key is needed. With one, each persona also runs a short journey, which needs a key |
--personas <list> |
Disability personas, comma-separated (--disabilities also works) |
--device <name> |
Device to audit on |
--scope <scope> |
viewport (default) or full_page |
--wcag-level <level> |
A, AA (default) or AAA |
--max-steps <n> |
Steps per persona when there is a goal |
--max-time <s> |
Seconds per persona when there is a goal |
--output <file> |
Save the JSON report |
--html |
Write an HTML report |
Personas: motor-impairment-tremor, low-vision-magnified, cognitive-adhd, dyslexic-user, deaf-user, elderly-low-vision, color-blind-deuteranopia, autism-spectrum, intellectual-disability, aphasia-receptive, dyscalculia. Short aliases such as adhd and tremor work too. An overall score under 50 exits 1.
cbrowser empathy-audit \
https://example.com \
--personas adhd,deaf-user \
--html
webmcp-ready
Audit an MCP server for WebMCP compatibility.
cbrowser webmcp-ready <url> [opts]
| Option | Description |
|---|---|
--api-key <key> |
API key for an authenticated server |
--oauth-token <token> |
OAuth token for an OAuth-protected server |
--timeout <ms> |
Request timeout (default: 30000) |
--output <file> |
Save the JSON report |
--html |
Write an HTML report |
Scores six tiers: server (25%), tools (20%), instrumentation (15%), consistency (15%), agent options (15%) and docs (10%).
cbrowser webmcp-ready \
https://demo.cbrowser.ai/mcp
hunt-bugs
Look for UX bugs on a page. hunt is an alias.
cbrowser hunt-bugs <url> [options]
| Option | Description |
|---|---|
--max-pages <n> |
Pages to crawl (default: 10) |
--timeout <ms> |
Time for the whole hunt (default: 60000) |
competitive-benchmark
Run the same cognitive journey on your site and on competitors' sites. Needs an Anthropic API key: one journey per site.
cbrowser competitive-benchmark \
[options]
| Option | Description |
|---|---|
--sites <list> |
Comma-separated site URLs (required) |
--goal <goal> |
Task goal (required) |
--persona <name> |
Persona (default: first-timer) |
--max-steps <n> |
Steps per site (default: 30) |
--max-time <s> |
Seconds per site (default: 180) |
--device <name> |
Device every journey emulates |
--viewport <WxH> |
Page size for every journey |
--output <file> |
Save the JSON report |
--html |
Write an HTML report |
--browser exits 1. A site whose journey fails gets a failed result naming the error.
cbrowser competitive-benchmark \
--goal "sign up for free trial" \
--html --sites \
"https://a.com,https://b.com"
a11y
Run a WCAG accessibility audit.
cbrowser a11y audit [url]
cbrowser a11y audit --url <url>
Performance
perf
Collect performance metrics, or audit them against a budget.
cbrowser perf [url]
cbrowser perf audit [url] [options]
Option (perf audit) |
Description |
|---|---|
--budget-lcp <ms> |
LCP budget (default: 2500) |
--budget-fcp <ms> |
FCP budget (default: 1800) |
--budget-cls <score> |
CLS budget (default: 0.1) |
The budgets apply to perf audit only. An audit over budget exits 1.
cbrowser perf https://example.com
cbrowser perf audit \
https://example.com \
--budget-lcp 2000
perf-baseline
| Command | Description |
|---|---|
perf-baseline save <url> |
Measure and save a baseline |
perf-baseline list |
List saved baselines |
perf-baseline show <name> |
Show a baseline |
perf-baseline delete <name> |
Delete a baseline |
save takes --name <name>, --runs <n> (runs to average, default 3), --device and --viewport. The baseline records the device and size, and perf-regression renders with them. --browser exits 1: the cold-cache runs need Chromium.
cbrowser perf-baseline save \
https://example.com --name home
perf-regression
Compare current performance against a baseline.
cbrowser perf-regression <url> <name>
| Option | Description |
|---|---|
--sensitivity <level> |
strict, normal (default), ci or lenient |
--threshold-lcp <n> |
Allowed LCP increase in % (default: 20) |
--threshold-cls <n> |
Allowed CLS increase (default: 0.1) |
--threshold-fcp <n> |
Allowed FCP increase in % (default: 20) |
--threshold-ttfb <n> |
Allowed TTFB increase in % (default: 30) |
--threshold-tti <n> |
Allowed TTI increase in % |
--threshold-tbt <n> |
Allowed TBT increase in % |
--output <file> |
Save the JSON report |
It renders as the baseline was captured, so --device, --viewport and --browser exit 1.
cbrowser perf-regression \
https://example.com home \
--sensitivity strict
Visual Testing
visual
Pixel baselines of the current page.
| Command | Description |
|---|---|
visual save <name> [--url <url>] |
Save a baseline screenshot |
visual compare <name> |
Compare the page against it. --threshold is 0 to 1 (default: 0.1) |
visual list |
List baselines |
visual delete <name> |
Delete a baseline |
A failed comparison exits 1.
ai-visual
Visual regression with AI analysis of what changed.
| Command | Description |
|---|---|
ai-visual capture <url> --name <name> |
Capture a baseline |
ai-visual test <url> <baseline> |
Test a page against a baseline |
ai-visual suite <file.json> |
Run a suite |
ai-visual list |
List baselines |
ai-visual show <name> |
Show a baseline |
ai-visual delete <name> |
Delete a baseline |
capture takes --selector <sel> (one element), --device, --viewport (default 1920x1080; --width and --height also work), --browser (the baseline keeps it) and --wait <ms or selector>.
test renders with the baseline's engine, device and size, so --browser, --device and --viewport exit 1 there and in suite. test takes --threshold (0 to 1, default 0.9), --sensitivity (low, medium (default) or high), --html and --output. suite takes --threshold, --html and --output.
cbrowser ai-visual capture \
https://example.com --name home
cbrowser ai-visual test \
https://staging.example.com home
cross-browser
Compare rendering in Chromium, Firefox and WebKit.
cbrowser cross-browser <url> [opts]
cbrowser cross-browser suite <file>
| Option | Description |
|---|---|
--browsers <list> |
chromium,firefox,webkit (default: all) |
--viewport <WxH> |
Page size (default: 1920x1080; --width, --height also work) |
--device <name> |
Device preset (Firefox cannot emulate a mobile one) |
--wait <ms> |
Wait before the screenshot |
--wait-for <selector> |
Wait for a selector before the screenshot |
--sensitivity <level> |
low, medium or high |
--html |
Write an HTML report |
--output <file> |
Save the report |
--browser exits 1; use --browsers. The suite file:
{
"name": "My Site",
"urls": [
"https://example.com",
"https://example.com/about"
],
"options": {
"browsers": [
"chromium",
"firefox"
]
}
}
responsive
Compare rendering across page sizes.
cbrowser responsive <url> [options]
cbrowser responsive suite <file>
cbrowser responsive viewports
| Option | Description |
|---|---|
--viewports <list> |
Size names (default: mobile,tablet,desktop) |
--browser <engine> |
chromium, firefox or webkit (Firefox cannot emulate the mobile and tablet presets) |
--wait <ms> |
Wait before each screenshot |
--wait-for <selector> |
Wait for a selector before each screenshot |
--sensitivity <level> |
low, medium or high |
--html |
Write an HTML report |
--output <file> |
Save the report |
The mobile and tablet presets emulate their device: user agent, touch and pixel ratio. responsive viewports lists the presets (see Size names). --device and --viewport exit 1; the sizes come from --viewports.
cbrowser responsive \
https://example.com
cbrowser responsive \
https://example.com \
--viewports mobile,desktop-xl
ab
Compare two URLs visually.
cbrowser ab <urlA> <urlB> [options]
cbrowser ab suite <file.json>
| Option | Description |
|---|---|
--label-a <name> |
Label for URL A (default: "Version A") |
--label-b <name> |
Label for URL B (default: "Version B") |
--viewport <WxH> |
Page size (default: 1920x1080; --width, --height also work) |
--device <name> |
Device preset |
--browser <engine> |
chromium, firefox or webkit |
--wait <ms> |
Wait before the screenshot |
--wait-for <selector> |
Wait for a selector before the screenshot |
--sensitivity <level> |
low, medium or high |
--html |
Write an HTML report |
--output <file> |
Save the report |
cbrowser ab \
https://staging.example.com \
https://example.com --html
diff
Compare a page across browsers.
cbrowser diff <url> [options]
| Option | Description |
|---|---|
--browsers <list> |
chromium,firefox,webkit (default: all) |
--viewport <WxH> |
Page size (default: 1920x1080) |
--device <name> |
Device preset (Firefox cannot emulate a mobile one) |
Smart visual baselines and transport maps have no CLI command. They are the MCP tools visual_baseline, visual_regression (smart mode) and transport_map.
Parallel Runs
| Command | Description |
|---|---|
parallel devices <url> |
Open the URL on several devices |
parallel urls <url> <url>... |
Open several URLs |
parallel perf <url> <url>... |
Measure performance of several URLs |
All three take --concurrency <n> (browsers at once, default 3), --browser and --no-headless. parallel devices takes --devices <list>; without it, it runs cbrowser's own 12 presets. --device and --viewport exit 1 there. parallel urls and parallel perf also take --device and --viewport. Any failed run exits 1.
cbrowser parallel devices \
https://example.com \
--devices iphone-16,pixel-9
Chaos Testing
chaos
Test how a page copes with network trouble.
cbrowser chaos <url> [options]
| Option | Description |
|---|---|
--latency <ms> |
Add network latency |
--offline |
Simulate offline mode |
--block <patterns> |
Block URL patterns (comma-separated) |
--fail-api <pattern:status> |
Fail matching API calls with a status |
A failed run exits 1.
Sessions, Cookies and Location
session
| Command | Description |
|---|---|
session save <name> [--url <url>] |
Save cookies, storage and the URL |
session load <name> |
Load a saved session |
session list |
List saved sessions |
session show <name> |
Show a session's cookies, storage and URL |
session delete <name> |
Delete a session |
session cleanup [--older-than <days>] |
Delete sessions older than N days (default: 30) |
session export <name> [--output <file>] |
Write a session to JSON (default: <name>.json) |
session import <file> |
Import a session from JSON |
A session command on an unknown name exits 1.
cbrowser session save logged-in \
--url https://example.com
cbrowser session load logged-in
cookie
| Command | Description |
|---|---|
cookie list [--url <url>] |
List the page's cookies |
cookie set <name> <value> |
Set a session cookie. --domain (or the --url host) and --path (default /) |
cookie delete <name> |
Delete a cookie. --domain (or --url) limits it to one domain; without either, the name goes on every domain |
cookie clear |
Clear all cookies |
geo
| Command | Description |
|---|---|
geo list |
List location presets |
geo set <location> |
Set the default location: a preset or lat,lon. Later commands keep it until you change it |
cbrowser geo set new-york
cbrowser geo set 37.7749,-122.4194
For one command only, use --geo instead.
Device Emulation
device
Emulate a phone, tablet or laptop: its screen size, pixel ratio, touch support and user agent. Pass --device <name> to any command, or set a default.
| Command | Description |
|---|---|
device list [filter] |
One line per preset: name, size, pixel ratio, mobile or desktop, touch. The filter matches the preset name or the device's full name |
device set <name> |
Set the default device for later commands |
cbrowser device list iphone
cbrowser device set iphone-16
cbrowser screenshot \
https://example.com phone.png \
--device "iPhone 16"
Presets. More than 200, from three sources (more with newer Playwright versions):
- cbrowser's own:
iphone-15,iphone-15-pro-max,pixel-8,pixel-8-pro,samsung-galaxy-s24,ipad-pro-12,ipad-air,desktop-1080p,desktop-1440p, and the genericmobile,tabletanddesktop - Chrome DevTools' device list: the iPhone 16 family (
iphone-16,iphone-16-plus,iphone-16-pro,iphone-16-pro-max,iphone-16e),pixel-9,pixel-9-pro,pixel-10,galaxy-z-fold-6,pixel-9-pro-fold,ipad-pro-13,ipad-mini,surface-pro-10, laptops such aslaptop-with-hidpi-screen, and more - Playwright's device list, which grows with the installed Playwright version. Playwright 1.64 adds the iPhone 17 family, iPhone Air and Pixel 10 Pro
Phones and tablets also have a landscape preset, such as iphone-16-landscape.
Each preset is the device's full screen in CSS pixels. iphone-16 is 393x852 at 3x, so its screenshots are 1179 pixels wide.
Names. Case and spaces do not matter: --device "iPhone 16", --device iphone-16 and --device "IPHONE 16" are the same preset.
An unknown name is an error. The command exits 1 and names the closest presets. The same check applies to the MCP tools' device parameter, to CBROWSER_DEVICE and to a device in your config file.
A custom size. For a size no preset has, pass --viewport WIDTHxHEIGHT. With a device as well, --viewport sets the size and the device keeps its pixel ratio, touch support and user agent.
Screen Capture
capture records pixels over time: the screen as a GIF, WebP or video, plus a JSON manifest describing every frame.
capture is not record. They solve different problems and share no output format:
| Command | Records | Output |
|---|---|---|
capture |
Pixels over time | GIF / WebP / WebM / MP4, JPEG frames, manifest.json |
record |
User actions | Generated Playwright test code (see record) |
capture start
cbrowser capture start <url> [opts]
| Option | Description |
|---|---|
--fps <n> |
Target frames per second (default: 10) |
--duration <5s> |
Stop after this long (5s, 2m, 1500ms) |
--viewport <WxH> |
Page size, such as 1280x720, or a size name. A comma-separated list runs one capture per size |
--region <x,y,w,h> |
Capture a fixed region instead of the viewport |
--element <selector> |
Track an element; the crop follows it as it moves |
--element-padding <n> |
Expand the element box by n CSS px per side |
--device <name> |
Any device preset (see Device Emulation). An unknown name exits 1 and names the closest presets |
--format <list> |
gif, webp, webm, mp4 (default: gif) |
--quality <1-100> |
JPEG quality of captured frames (default: 80) |
--max-frames <n> |
Stop keeping frames after n (default: 3000) |
--contact-sheet |
Also write one JPEG summarising the capture |
--attention-overlay |
Paint the predicted attention heatmap over every frame (adds about 0.5 to 1 s per frame) |
--overlay-persona <name> |
Persona weighting the overlay (default: first-timer) |
--overlay-goal <text> |
Goal weighting goal relevance in the overlay |
--after <event> |
Start on load, domcontentloaded or networkidle |
--after-element <sel> |
Start when the element is present and visible |
--after-delay <500ms> |
Extra delay after the start trigger |
--until-element <sel> |
Stop when the element appears |
--until-element-gone <sel> |
Stop when the element disappears |
--until-idle <800ms> |
Stop after this long with no part of the page changing |
--timeout <30s> |
How long a trigger may take (default: 30s) |
--out <dir> |
Output directory (default: ~/.cbrowser/videos/<session>/<name>) |
--name <slug> |
Capture name |
cbrowser capture start \
https://example.com --duration 3s
cbrowser capture start \
https://example.com --duration 5s \
--format gif,webp --contact-sheet
cbrowser capture start \
https://example.com \
--element "#hero" --duration 3s
cbrowser capture start \
https://example.com \
--device iphone-16 --until-idle 1s
When it finishes, capture start prints the stop trigger, the frame count with the actual and requested frame rates, the duration, and the paths of the manifest and each encoded file.
The output directory holds the encoded files, a frames/ directory of JPEGs (0000.jpg, 0001.jpg and on), and manifest.json. The manifest records the target and actual frame rate, the capture target, the start and stop triggers, change points, frame gaps, and for each frame its timestamp, file path, crop box and similarity to the previous frame.
capture stop
Stop the running capture.
cbrowser capture stop
A capture is stopped from the process that started it, or through the daemon. With nothing running, capture stop says so instead of hanging.
capture status
Show the running capture, or the most recent one: its name, start time, frame count, capture method, files and manifest path.
cbrowser capture status
Start and stop triggers
A capture does not have to be timed. --after, --after-element and --after-delay decide when recording begins; --duration, --until-element, --until-element-gone and --until-idle decide when it ends.
# Start once the hero shows,
# stop once the spinner is gone
cbrowser capture start \
https://example.com \
--after-element "#hero" \
--after-delay 200ms \
--until-element-gone ".spinner"
--timeout bounds the wait for any trigger (default: 30s). A trigger that never fires does not hang: the capture stops, the manifest and the encoded files are still written, and the process exits non-zero, so CI sees a failure and you still get the footage. A page with a clock or a ticker is always changing, so --until-idle runs to the timeout there.
Capturing through the daemon
With the daemon running, capture start records the daemon's page while you drive it with other commands, and capture stop finishes it. The daemon's browser keeps the device, size and engine it started with, so --viewport, --device and --browser exit 1 there: pass them to daemon start instead.
Capturing a test run or journey
test-suite and cognitive-journey record themselves with --capture, --capture-fps, --capture-format and --capture-out. This is capture running underneath them: pixels, not actions.
cbrowser test-suite tests.txt \
--capture --capture-out ./run-video
Capture limits
Read these before you trust a capture.
- Capture is event-driven, not a fixed-rate sampler. The screencast only emits a frame when the page repaints, so
--fpsis a ceiling. A page that never repaints emits no frames. - Still stretches are reported, not padded. Instead of duplicating frames, the manifest records a frame gap, and the CLI prints the largest one.
- mp4 needs a full ffmpeg. Playwright's bundled binary only does WebM. Install a full ffmpeg and set
CBROWSER_FFMPEG_PATH, or use--format webm. When one format fails to encode, the formats that did encode are still written and the process exits non-zero. - An open-ended capture needs the daemon. Without
--durationor a stop trigger,capture startrefuses and tells you to runcbrowser daemon startor bound the capture. A capture in its own process also stops after 10 minutes when no--durationwas given. - A multi-size
--viewportruns one capture per size, each in its own subdirectory with its ownmanifest.json. It needs--durationor a stop trigger so each run can end.
See Screen-Capture.
Daemon
Every CLI command is its own process. The daemon keeps one browser open between commands, so the page you opened in one command is still there for the next, and anything that records over time (HAR, network requests, console messages) has a browser to record in.
daemon
| Command | Description |
|---|---|
daemon start |
Start the daemon |
daemon stop |
Stop it. Exits 1 if that fails |
daemon status |
Show whether it runs, its uptime and idle timeout. Exits 1 when no daemon is running |
Option (daemon start) |
Description |
|---|---|
--port <port> |
Daemon port (default: 9222) |
--timeout <min> |
Idle timeout: minutes, or 90s, 45m, 2h (default: 30) |
--device <name> |
Device the daemon's browser emulates |
--viewport <WxH> |
Page size of the daemon's browser |
--browser, --no-headless, --locale, --timezone, --geo |
The rest of the daemon's browser settings |
cbrowser daemon start
cbrowser daemon start --timeout 45m
cbrowser daemon start \
--device iphone-16 --port 9300
cbrowser daemon status
cbrowser daemon stop
What runs in the daemon. While it runs, navigate, click, fill, hover, type, press, keyboard, screenshot, extract, run, scroll, evaluate, capture, har, network and console use its browser. A failed action exits 1, as it does without the daemon. Status lines such as "Connected to running daemon" go to stderr.
What refuses while it runs. Commands that would open a second browser on its profile exit 1 until you stop it: smart-click, dismiss-overlay, assert, drag, upload, script, ai, explore, analyze, generate, hunt-bugs, chaos, a11y, perf, visual and reset.
Browser settings. The daemon's browser keeps the settings it started with. To change the device, size, engine, locale, timezone or location, stop the daemon and start it with those flags. Passing them to a command that runs in the daemon prints a warning and does not change the page.
The daemon listens on 127.0.0.1 and accepts commands only with a token from its state file, daemon.json in the CBrowser data directory (readable only by you); the CLI handles this. A daemon started by a version before 19.4.3 has no token: stop it and start it again after upgrading.
har
Record every request the daemon's browser makes as a HAR file.
cbrowser daemon start
cbrowser navigate https://example.com
cbrowser har start
cbrowser click "Pricing"
cbrowser har stop pricing.har
har needs the daemon. Without one, har start exits 1 and tells you to start it.
network
| Command | Description |
|---|---|
network list |
List the requests the daemon's browser made, newest first |
network clear |
Empty that list |
Option (network list) |
Description |
|---|---|
--filter <text> |
Only requests whose URL contains the text, or of that resource type or method |
--all |
List every request (default: the newest 20) |
--json |
Print the list as JSON |
cbrowser network list
cbrowser network list --filter api
cbrowser network list --all --json
Both need the daemon.
console
cbrowser console
cbrowser console --filter error
cbrowser console --clear --json
Lists the daemon tab's console: logs, warnings, errors, uncaught exceptions and failed resource loads, each with the page it came from. --filter takes all (the default), error, warning, log or info. --clear empties the list after reading it; --json prints the raw messages. Needs the daemon.
Text from the page is printed with control characters made visible, so a page cannot use its console output to change your terminal's title, write your clipboard or hide lines.
Webhooks
webhook
Send a notification when a test suite or a journey finishes.
| Command | Description |
|---|---|
webhook add <name> <url> |
Add a webhook (http or https) |
webhook list |
List webhooks |
webhook delete <name> |
Delete a webhook |
webhook test <name> |
Send a test notification |
Option (webhook add) |
Description |
|---|---|
--events <events> |
test.pass, test.fail, journey.complete, comma-separated (default: test.fail) |
--format <format> |
generic (default), slack or discord |
test-suite sends test.pass or test.fail once per run; cognitive-journey sends journey.complete once per journey. Each is a JSON POST with a 10-second timeout and no retries. A failed send is a warning and never fails the run.
webhook add exits 1 for a URL that is not http or https, a URL with a user name or password, an unknown event or an unknown format.
cbrowser webhook add ci \
https://hooks.example.com/cb \
--events test.fail,journey.complete
MCP Server
mcp-server
Run CBrowser as a local MCP server over stdio, for Claude Desktop, Claude Code and other MCP clients. It takes no options.
cbrowser mcp-server
It registers the same 131 tools as the hosted servers, plus 7 that keep their state in the local process. See MCP-Server.
mcp-remote
Run your own HTTP MCP server for remote clients, such as claude.ai connectors.
cbrowser mcp-remote [options]
| Option | Description |
|---|---|
--port <port> |
Port (default: 3000) |
--host <host> |
Host to bind (default: 0.0.0.0) |
--stateful |
Use stateful session mode |
See Remote-MCP-Server.
Claude Skill
| Command | Description |
|---|---|
install-skill |
Install CBrowser as a Claude skill in ~/.claude/skills/ |
sync-skill |
Update the installed skill to match your cbrowser version |
Both download the skill files from GitHub first, and change nothing if the download fails. See Claude-Skill-Installation.
Configuration
config
| Command | Description |
|---|---|
config set-api-key <key> |
Set the Anthropic API key for cognitive journeys |
config show-api-key |
Show the key, masked |
config remove-api-key |
Remove the key |
config set-model <model> |
Set the Claude model |
Environment variables
Environment variables override the config file, and command-line flags override both.
| Variable | Description |
|---|---|
CBROWSER_DATA_DIR |
Data directory (default: ~/.cbrowser) |
CBROWSER_BROWSER |
chromium, firefox or webkit |
CBROWSER_DEVICE |
Default device preset |
CBROWSER_VIEWPORT_WIDTH, CBROWSER_VIEWPORT_HEIGHT |
Default page size (default: 1920 and 1080) |
CBROWSER_LOCALE |
Browser locale (default: the host's) |
CBROWSER_TIMEZONE |
Timezone (default: the host's) |
CBROWSER_HEADLESS |
false shows the browser (default: true) |
CBROWSER_TIMEOUT |
Page-load timeout in ms (default: 30000) |
CBROWSER_RECORD_VIDEO |
Record video by default (true or false) |
NO_COLOR |
Any value turns off colour |
Config file
CBrowser reads the first of these it finds: .cbrowserrc.json, .cbrowserrc or cbrowser.config.json in the current directory, then ~/.cbrowser/config.json or ~/.cbrowserrc.json.
{
"browser": "chromium",
"device": "iphone-15",
"geolocation": "new-york",
"locale": "en-US",
"recordVideo": true,
"performanceBudget": {
"lcp": 2500,
"cls": 0.1
}
}
Storage and Cleanup
| Command | Description |
|---|---|
storage |
Show storage use |
cleanup |
Delete old files |
reset |
Clear the persistent browser state (cookies, storage) |
uninstall |
Remove CBrowser's data: credentials, sessions, captures |
cleanup options:
| Option | Description |
|---|---|
--dry-run |
Show what would be deleted |
--older-than <days> |
Delete files older than N days (default: 7) |
--keep-screenshots <n> |
Keep at least N screenshots (default: 10) |
--keep-journeys <n> |
Keep at least N journeys (default: 5) |
--keep-sessions <n> |
Keep at least N sessions (default: 3) |
uninstall is a dry run by default: it shows what would go and removes nothing. --yes removes it; --keep-config keeps the API key and proxy config for a reinstall. npm uninstall -g cbrowser does not remove any of this data.
Lightpanda
Lightpanda is an opt-in headless browser that only agent-ready-audit --lightpanda uses. It is beta software with no security audit, and its cloud mode sends your traffic to lightpanda.io, so never use it with logins, credentials or payments.
| Command | Description |
|---|---|
lightpanda-status |
Check whether Lightpanda is available and configured |
lightpanda-setup |
Show setup instructions and the security notice |
It reads LIGHTPANDA_ENDPOINT (a WebSocket endpoint) and LIGHTPANDA_TOKEN (a cloud API token).
Copyright: (c) 2026 Alexa Eden.
License: MIT License
Contact: [email protected]