Back to docs

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 50 or --max-pages=50.
  • A flag that takes no value, such as --force or --html, never takes the next word as its value.
  • test-suite, cognitive-journey, evaluate, keyboard, capture, ask and uninstall check 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.
  • --html writes an HTML report beside it, with .html in place of .json. When the --output name already ends in .html, the HTML report goes to <name>.report.html, so it never overwrites the JSON.
  • --html without --output writes a default name, such as test-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?"

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 --arg values

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

See Performance-Regression.


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
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 generic mobile, tablet and desktop
  • 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 as laptop-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 --fps is 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 --duration or a stop trigger, capture start refuses and tells you to run cbrowser daemon start or bound the capture. A capture in its own process also stops after 10 minutes when no --duration was given.
  • A multi-size --viewport runs one capture per size, each in its own subdirectory with its own manifest.json. It needs --duration or 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]

From the Blog