Camou is a local-first CLI and background daemon for driving Camoufox through Playwright, without depending on the Camoufox Python SDK.
- npm package:
camou - installed command:
camou - project/repo name: camoucli
Camou is built for agent-style browser workflows:
- keep a browser session alive across separate CLI invocations
- preserve login state with persistent profiles
- operate named tabs in parallel without ref collisions
- interact through stable
@eNrefs from text snapshots - install, switch, and diagnose Camoufox browser versions from the CLI
Camou takes strong inspiration from vercel-labs/agent-browser and BUNotesAI/agent-browser-session, but is built for the Camoufox + Playwright Firefox path and persistent local daemon workflows.
| Feature | Why it matters |
|---|---|
| Persistent profiles | Login once and reuse the same authenticated browser state later |
| Named sessions | Keep separate workspaces like work, shopping, or github isolated |
| Named tabs | Run multiple agents against the same browser session without fighting over one active page |
| Snapshot refs | Use @e1, @e2, ... from snapshot instead of brittle selectors when driving pages |
| Version manager | Install and switch Camoufox builds without bundling the browser into the npm package |
| Doctor diagnostics | Check launch compatibility, bundle health, and Linux shared-library issues quickly |
Requirements:
- Node.js
>=20 - a supported Camoufox release for your OS
Global install (recommended):
npm install -g camou
camou installOne-off usage with npx:
npx camou install
npx camou open https://example.comFrom this repo:
npm install
npm run build
npm run dev -- --helpNotes:
- Browser download is explicit. Installing the npm package does not download Camoufox.
camou installruns a quick headless launch probe after download.camou use <version>runs the same compatibility check when you switch versions.
Camou also ships an agent skill that can be installed through the open skills ecosystem at skills.sh.
Install it from this repo:
npx skills add txchen/camoucli --skill camouUseful variants:
# Preview available skills in the repo
npx skills add txchen/camoucli --list
# Install globally for a specific agent
npx skills add txchen/camoucli --skill camou -g -a opencodeThe skill teaches agents the recommended Camou workflow: open -> snapshot -i -> interact with @refs -> re-snapshot, plus session/tab/version troubleshooting guidance.
camou install # Install the default browser build
camou open https://example.com # Open the target page
camou snapshot -i # Capture interactive refs
# @e1 a "Learn more"
camou click @e1 # Click the chosen ref
camou get title # Read the current page titleWhat happens behind the scenes:
camou openauto-starts the local daemon if needed.- Camoufox launches with a persistent profile for the default session.
snapshot -ireturns interactive elements with refs like@e1.- Later commands reuse the same browser session and profile.
Important ref rule:
- Re-run
snapshotafter navigation or major page changes. Refs are per tab and are invalidated on navigation or a new snapshot.
If you use Camou inside a coding project, you do not need to repeat --session and --tabname on every command.
Camou resolves defaults in this order:
- explicit CLI flags
- environment variables
- nearest project config file in the current directory or any parent directory
- built-in defaults:
session=default,tabname=main
Supported environment variables:
export CAMOU_SESSION=my-project
export CAMOU_TAB=main
export CAMOU_BROWSER=135.0.1-beta.24
export CAMOU_HEADLESS=true
export CAMOU_PRESET=cache,low-bandwidthAlso supported:
CAMOU_TABNAMECAMOU_PRESETS- legacy aliases:
CAMOUCLI_SESSION,CAMOUCLI_TAB,CAMOUCLI_TABNAME,CAMOUCLI_BROWSER,CAMOUCLI_HEADLESS,CAMOUCLI_PRESET,CAMOUCLI_PRESETS
Supported project config file names:
.camou.jsoncamou.json
Example .camou.json:
{
"session": "my-project",
"tabname": "main",
"browser": "135.0.1-beta.24",
"headless": true,
"preset": ["cache", "low-bandwidth"]
}Then you can run commands like:
camou open https://example.com # Open the target page
camou snapshot -i # Capture interactive refs
camou click @e1 # Click the chosen refand they automatically use the configured session, tab, browser version, headless mode, and presets unless you override them with flags.
Camou can also be used as a Node library, not just a CLI.
The programmatic API is Playwright-based: it launches Camoufox for you and gives you a real Playwright BrowserContext, similar in spirit to the Camoufox Python wrapper.
import { Camoufox } from 'camou';
const camou = await Camoufox.launch({
session: 'script',
headless: false,
fingerprint: {
locales: ['en-US', 'fr-FR'],
screenProfile: 'desktop-fhd',
blockImages: true,
},
});
const page = await camou.open('https://example.com');
console.log(await page.title());
await camou.close();If you prefer a scoped helper:
import { Camoufox } from 'camou';
await Camoufox.with({ session: 'script' }, async (camou) => {
const page = await camou.open('https://example.com');
console.log(await page.title());
});Useful exported helpers include:
Camoufox.launch()Camoufox.launchContext()Camoufox.with()AsyncCamoufoxlaunchCamoufox()launchCamoufoxContext()resolveCamoufoxLaunchSpec()withCamoufox()installCamoufox()listInstalledBrowsers()setCurrentBrowser()doctorCamoufox()
Notes:
- install a browser first with
camou installorinstallCamoufox() - use a dedicated
sessionname in scripts if you do not want to share the default CLI profile - the returned context is a normal Playwright context, so you can use standard Playwright APIs from there
For agents and automation loops, this is the happy path:
camou open https://target.site # Open the target page
camou snapshot -i --json # Capture JSON refs
camou click @e3 # Act on a chosen ref
camou fill @e5 "hello" # Fill the next field
camou snapshot -i --json # Refresh refs after changesWhy this works well:
snapshotgives a stable text representation of the page- refs are deterministic within the current tab snapshot
--jsongives machine-readable success and error payloads- the daemon keeps browser state alive between commands
A session is a named browser workspace selected with --session <name>.
- sessions have separate persistent profile directories
- different sessions isolate cookies, storage, downloads, and artifacts
- reuse the same session name to keep login state across runs
Example:
camou open https://github.com --session work # Open the work session
camou open https://mail.google.com --session personal # Open a separate personal sessionA tab is a named page binding inside a session selected with --tabname <name>.
- tabs in the same session share browser profile state
- tabs keep separate page bindings and separate ref maps
- named tabs make concurrent agent workflows much safer
Example:
camou open https://reddit.com --session work --tabname reddit # First named tab
camou open https://news.ycombinator.com --session work --tabname hn # Second named tabA ref is a snapshot-generated handle like @e1 or @e2.
- refs come from
camou snapshotorcamou snapshot -i - refs are only valid for the tab that created them
- refs are cleared when the page navigates or you take a new snapshot
Camou keeps an active Camoufox version, but you can also pick a version per command.
camou use <version>changes the active default versioncamou <command> ... --browser <version>runs a command against a specific installed version without changing the default
camou open https://github.com/login --session work --tabname github # Start a named session
# log in once in the browser
camou open https://github.com/settings/profile --session work --tabname github # Reuse saved loginUse the same --session name later and the login state is still there.
camou open https://reddit.com --session research --tabname reddit # Shared session, first tab
camou open https://news.ycombinator.com --session research --tabname hn # Shared session, second tab
camou snapshot -i --session research --tabname reddit # Inspect the reddit tab
camou snapshot -i --session research --tabname hn # Inspect the hn tabBoth tabs share the same browser profile, but each tab has its own page and ref map.
camou remote-versions # Show compatible remote versions
camou install 135.0.1-beta.24 # Install one version
camou install 135.0.1-beta.23 # Install another version
camou versions # Show installed and active versions
camou use 135.0.1-beta.24 # Switch the default version
camou doctor --json # Check compatibility in JSONcamou open https://example.com --session canary --browser 135.0.1-beta.24 # Pin one runcamou snapshot -i --json # JSON interactive snapshot
camou get title --json # JSON scalar output
camou eval 'document.title' --json # JSON eval result
camou cookies export --json # JSON cookie export
camou doctor --json # JSON diagnostics
camou remote-versions --json | jq -r '.remoteVersions[].version' # Extract versionsErrors are also structured when --json is enabled.
camou daemon stop # Stop the local daemon process
camou daemon restart # Restart the daemon after upgrades or cleanup
camou daemon cleanup # Stop sessions, stop daemon, kill stray Camoufox processesUse camou daemon restart after upgrading the CLI if an older background daemon is still running. Use camou daemon cleanup when the daemon is gone but orphan Camoufox processes remain.
camou install [version] # Install the default or one specific build
camou remove [version] # Remove an installed browser build
camou use <version> # Switch the default browser version
camou versions # List installed versions and the default
camou remote-versions # List compatible remote versions
camou presets # Show built-in launch presets
camou version # Print the active camoucli version
camou path # Show the active browser executable path
camou doctor # Diagnose install and launch issuescamou open <url> # Open a URL in the current tab
camou back # Go back in the current tab history
camou forward # Go forward in the current tab history
camou reload # Reload the current page
camou eval <expression> # Run JavaScript in the current tab
camou snapshot # Capture page state and refs
camou snapshot -i # Interactive elements only; recommended
camou click <selectorOrRef> # Click a selector or @eN ref
camou hover <selectorOrRef> # Hover a selector or @eN ref
camou fill <selectorOrRef> <text> # Set an input value directly
camou type <selectorOrRef> <text> # Type text with key events
camou check <selectorOrRef> # Check a checkbox or radio input
camou uncheck <selectorOrRef> # Uncheck a checkbox
camou select <selectorOrRef> <value> # Choose a select option
camou press <key> # Press a keyboard key in the page
camou scroll <direction> [amount] # Scroll up, down, left, or right
camou scrollintoview <selectorOrRef> # Scroll until visible
camou wait [selectorOrRef] [--text <text>] [--load <state>] # Wait for element, text, or load
camou screenshot [path] # Save a screenshot of the current page
camou get url # Read the current page URL
camou get title # Read the current page title
camou get text <selectorOrRef> # Read visible text from an element
camou get value <selectorOrRef> # Read an element's form valueUse session for live daemon state and profile for stored disk-backed browser data.
camou session list # List running daemon sessions
camou profile list # List stored profiles on disk
camou profile inspect <name> # Show one profile's paths
camou profile remove <name> # Delete a profile; stops it first if needed
camou cookies export [path] # Export context cookies as JSON
camou cookies import <path> # Import cookies into session context
camou close --all # Stop all running sessions
camou daemon stop # Stop the local daemon process
camou daemon restart # Restart the local daemon process
camou daemon cleanup # Stop sessions, stop daemon, kill stray Camoufox processes
camou session stop [name] # Stop one session or the current session
camou tab list # List tabs in the current session
camou tab new [url] # Create a new tab, optionally opening a URL
camou tab close [nameOrIndex] # Close one tab by name or indexMost browser commands support:
--session <name>--tabname <name>--headless--browser <version>--config <path>--config-json <json>--prefs <path>--prefs-json <json>--fingerprint <path>--fingerprint-json <json>--preset <name>--proxy <url>--locale <locale>--locales <locale[,locale...]>--region <code>--timezone <timezone>--screen-profile <name>--window-profile <name>--block-images--block-webrtc--block-webgl--disable-coop--width <px>--height <px>--json--verbose
wait also supports:
--text <text>--load <domcontentloaded|load|networkidle>
Built-in presets give you a small layer of tested ergonomics on top of raw config and prefs JSON.
| Preset | What it does |
|---|---|
default |
Baseline launch with no extra overrides |
cache |
Enables the Firefox cache/session prefs used by the Python library |
low-bandwidth |
Blocks images and speculative requests for lighter automation sessions |
disable-coop |
Relaxes Cross-Origin-Opener-Policy isolation for troublesome embedded flows |
List them:
camou presetsList built-in fingerprint profiles:
camou fingerprint-profilesApply one or more:
camou open https://example.com --preset cache --preset low-bandwidthCamou now includes a higher-level helper layer for common Camoufox identity settings without forcing you to handcraft raw config keys.
CLI shortcuts:
camou open https://example.com \
--locales en-US,fr-FR \
--region US \
--screen-profile desktop-fhd \
--window-profile desktop \
--block-imagesYou can also pass a helper JSON object:
camou open https://example.com --fingerprint-json '{"screenProfile":"retina-mac","locales":["en-US","en"],"blockWebRtc":true}'Node API example:
import { Camoufox } from 'camou';
const camou = await Camoufox.launch({
fingerprint: {
region: 'CA',
locales: ['en-CA', 'fr-CA'],
screenProfile: 'desktop-fhd',
windowProfile: 'desktop',
blockImages: true,
},
});Supported helper fields include:
localesto keepnavigator.language,navigator.languages, andAccept-Languagealignedregionto apply a curated locale, timezone, and geolocation bundle for a target country or territoryscreenProfile/windowProfilefor curated screen and window templatesscreen/windowin the Node API for direct helper objectsblockImages,blockWebRtc,blockWebGl, anddisableCoopas Python-style toggle helpersfontsandfontSpacingSeedin the Node API for higher-level font config
Current region helpers seed representative locale, timezone, and geolocation values for supported regions. Direct IP-based GeoIP lookup is not bundled yet.
Built-in screen profiles:
laptop-hddesktop-fhddesktop-qhdretina-mac
Built-in window profiles:
laptopdesktopdesktop-largeretina
camou doctor --json reports:
- installed Camoufox versions
- which version is active
- whether each version can launch with the current
playwright-core - bundle file checks
- Linux shared-library diagnostics
- remediation hints
Useful commands:
camou versions
camou use 135.0.1-beta.24
camou doctor --jsonCommon fixes:
Browser.setContrast is not supported- the selected Camoufox build is older than the bundled Playwright runtime
- switch to a newer browser version with
camou use <version>
- profile/session locked
- another browser process is using that session profile
- stop the other browser or use a different
--session
- executable missing or damaged
- reinstall with
camou install --force
- reinstall with
- Linux launch failures
- run
camou doctor --jsonand install the missing shared libraries it reports
- run
Current local verification with playwright-core 1.51.1:
| Camoufox | Status | Notes |
|---|---|---|
135.0.1-beta.24 |
launches | smoke-tested successfully |
135.0.1-beta.23 |
incompatible | Browser.setContrast is not supported |
The repo now also includes:
- Linux/macOS CI in
.github/workflows/ci.yml - a workflow-driven compatibility probe in
.github/workflows/compatibility-matrix.yml - local scripts to generate compatibility reports and markdown summaries
See docs/compatibility-matrix.md for the workflow and local tooling.
Camou keeps its own runtime state and profiles, but stores browser binaries in the shared Camoufox cache layout when possible.
- session data lives under
profiles/<session>/{user-data,downloads,artifacts} - daemon state and logs live under platform runtime/state directories
- Camoufox binaries live in the shared cache used by the Python library:
- Linux:
~/.cache/camoufox/browsers/official/<version>/ - macOS:
~/Library/Caches/camoufox/browsers/official/<version>/ - Windows:
%LOCALAPPDATA%\camoufox\Cache\browsers\official\<version>\
- Linux:
This lets Camou reuse compatible Camoufox installs from the Python ecosystem and vice versa.
npm install
npm run build
npm testOptional targeted integration suite:
npm run test:integrationLocal development commands:
npm run dev -- --help
npm run dev:daemonCompatibility tooling:
# produce a raw compatibility report JSON
node scripts/run-compatibility-report.mjs --output compatibility-report.json
# turn one or more reports into a markdown table
node scripts/generate-compatibility-matrix.mjs compatibility-report.jsonCamou learned a lot from these projects:
- vercel-labs/agent-browser for the agent-oriented command workflow and skill ecosystem patterns
- BUNotesAI/agent-browser-session for persistent-session and named-tab ergonomics