{"_id":"@alessioz/mcp-camoufox","_rev":"2-818c31e9f96f449f57e285234385bd4d","name":"@alessioz/mcp-camoufox","dist-tags":{"latest":"0.9.3"},"versions":{"0.9.2":{"name":"@alessioz/mcp-camoufox","version":"0.9.2","keywords":["mcp","camoufox","browser","automation","stealth","anti-detection","playwright","modelcontextprotocol","claude"],"author":{"name":"RobithYusuf","email":"robithdev@gmail.com"},"license":"MIT","_id":"@alessioz/mcp-camoufox@0.9.2","maintainers":[{"name":"alessioz","email":"alessio.zamparelli@gmail.com"}],"homepage":"https://github.com/RobithYusuf/mcp-camoufox#readme","bugs":{"url":"https://github.com/RobithYusuf/mcp-camoufox/issues"},"bin":{"mcp-camoufox":"dist/index.js"},"dist":{"shasum":"aa9a32d248bb86decd0216754059a94e6d185153","tarball":"https://registry.npmjs.org/@alessioz/mcp-camoufox/-/mcp-camoufox-0.9.2.tgz","fileCount":5,"integrity":"sha512-+eNVUe0GXS3nwijWpBPR4gfjWhcUPgMK4xNKPmEUfllnrHLp9j0WgC2ri5XxfUVB9EAPPautSak4GJq4w6sZ5w==","signatures":[{"sig":"MEUCIQDTl5BXGJJFhDIgjRkpdYQpHMiTgjZZLnwyaDicB82FMgIgEspSOGrHXp9mIJxDWfaJfsdOgWcsCqRoHTq3rXVKIO8=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":245153},"main":"dist/index.js","type":"module","types":"./dist/index.d.ts","engines":{"node":">=22.0.0"},"gitHead":"0724bae85bc955bbd802a4484a5c09b7482cdbd8","scripts":{"dev":"tsc --watch","build":"tsc","start":"node dist/index.js","prepublishOnly":"npm run build"},"_npmUser":{"name":"alessioz","email":"alessio.zamparelli@gmail.com"},"repository":{"url":"git+https://github.com/RobithYusuf/mcp-camoufox.git","type":"git"},"_npmVersion":"11.6.0","description":"MCP server for stealth browser automation via Camoufox — 104 tools, Chrome DevTools MCP-level power with anti-bot stealth","directories":{"doc":"docs"},"_nodeVersion":"24.9.0","dependencies":{"zod":"^4.3.6","impit":"^0.13.0","camoufox-js":"^0.10.2","playwright-core":"<1.61.0","@modelcontextprotocol/sdk":"^1.29.0"},"_hasShrinkwrap":false,"devDependencies":{"typescript":"^6.0.3","@types/node":"^25.6.0"},"_npmOperationalInternal":{"tmp":"tmp/mcp-camoufox_0.9.2_1787059148577_0.28918493665211886","host":"s3://npm-registry-packages-npm-production"}},"0.9.3":{"name":"@alessioz/mcp-camoufox","version":"0.9.3","description":"MCP server for stealth browser automation via Camoufox — 104 tools, Chrome DevTools MCP-level power with anti-bot stealth","keywords":["mcp","camoufox","browser","automation","stealth","anti-detection","playwright","modelcontextprotocol","claude"],"homepage":"https://github.com/alessio-zamparelli/mcp-camoufox#readme","bugs":{"url":"https://github.com/alessio-zamparelli/mcp-camoufox/issues"},"repository":{"type":"git","url":"git+https://github.com/alessio-zamparelli/mcp-camoufox.git"},"license":"MIT","author":{"name":"RobithYusuf","email":"robithdev@gmail.com"},"type":"module","main":"dist/index.js","types":"./dist/index.d.ts","bin":{"mcp-camoufox":"dist/index.js"},"directories":{"doc":"docs"},"scripts":{"build":"tsc","start":"node dist/index.js","dev":"tsc --watch","prepublishOnly":"npm run build"},"dependencies":{"@modelcontextprotocol/sdk":"^1.29.0","camoufox-js":"^0.10.2","impit":"^0.13.0","playwright-core":"<1.61.0","zod":"^4.3.6"},"devDependencies":{"@types/node":"^25.6.0","typescript":"^6.0.3"},"engines":{"node":">=22.0.0"},"gitHead":"402f9a9b12ef955c18f82ce8919bff4b50e9bc3d","_id":"@alessioz/mcp-camoufox@0.9.3","_nodeVersion":"24.19.0","_npmVersion":"11.17.0","dist":{"integrity":"sha512-zuAeDCT+QZxx6FLAxVo7jJ0WjzdZ732nbp1GhP3Srr7EbUz/Icx0EaD2ZZNlPAFpS/AQt/j9G/kDCO8Qrb9ZDA==","shasum":"e1d2250a9fd0c9e24f274956d0201db9b24faab7","tarball":"https://registry.npmjs.org/@alessioz/mcp-camoufox/-/mcp-camoufox-0.9.3.tgz","fileCount":5,"unpackedSize":245174,"attestations":{"url":"https://registry.npmjs.org/-/npm/v1/attestations/@alessioz%2fmcp-camoufox@0.9.3","provenance":{"predicateType":"https://slsa.dev/provenance/v1"}},"signatures":[{"keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U","sig":"MEUCIQCzVaKNZ9WhjG5SXnemuVSNOAeCb66qrcaoTT0yG82+XgIgT+O8Wd8NH2bl0pG5vUtH6cQLZKMoS1DiKGrB0x8etCQ="}]},"_npmUser":{"name":"GitHub Actions","email":"npm-oidc-no-reply@github.com","trustedPublisher":{"id":"github","oidcConfigId":"oidc:a3179563-b281-44a0-9b1b-8b94310709aa"}},"maintainers":[{"name":"alessioz","email":"alessio.zamparelli@gmail.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages-npm-production","tmp":"tmp/mcp-camoufox_0.9.3_1787060283810_0.3628939815462986"},"_hasShrinkwrap":false}},"time":{"created":"2026-08-18T13:19:08.248Z","modified":"2026-08-18T13:38:04.497Z","0.9.2":"2026-08-18T13:19:08.720Z","0.9.3":"2026-08-18T13:38:03.959Z"},"bugs":{"url":"https://github.com/alessio-zamparelli/mcp-camoufox/issues"},"author":{"name":"RobithYusuf","email":"robithdev@gmail.com"},"license":"MIT","homepage":"https://github.com/alessio-zamparelli/mcp-camoufox#readme","keywords":["mcp","camoufox","browser","automation","stealth","anti-detection","playwright","modelcontextprotocol","claude"],"repository":{"type":"git","url":"git+https://github.com/alessio-zamparelli/mcp-camoufox.git"},"description":"MCP server for stealth browser automation via Camoufox — 104 tools, Chrome DevTools MCP-level power with anti-bot stealth","maintainers":[{"name":"alessioz","email":"alessio.zamparelli@gmail.com"}],"readme":"<div align=\"center\">\n\n<img src=\"https://i.imgur.com/enUBkXt.png\" alt=\"Camoufox\" width=\"280\">\n\n# MCP Camoufox\n\n[![npm version](https://img.shields.io/npm/v/mcp-camoufox.svg)](https://www.npmjs.com/package/mcp-camoufox)\n[![npm downloads](https://img.shields.io/npm/dm/mcp-camoufox.svg)](https://www.npmjs.com/package/mcp-camoufox)\n[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)\n[![Node.js](https://img.shields.io/badge/Node.js-18%2B-green.svg)](https://nodejs.org)\n\n</div>\n\nThe most feature-rich stealth browser MCP server. **127 tools** for full browser control powered by [Camoufox](https://github.com/daijro/camoufox) — a Firefox fork with C++ level anti-detection that bypasses Cloudflare, bot detection, and anti-automation.\n\n> **One command. No Python. No manual setup. Everything auto-installs.**\n\n```bash\nclaude mcp add camoufox -- npx -y mcp-camoufox@latest\n```\n\n## What Can It Do?\n\n- Login to Google, ChatGPT, GitHub — without getting blocked\n- Fill forms, click buttons, type text, upload files\n- Manage cookies, localStorage, sessions across visits\n- Take screenshots, export PDFs, capture network traffic\n- Work with multiple tabs, iframes, dialogs\n- Execute JavaScript, inspect elements, scroll pages\n- Scrape structured data (job listings, products) with auto-detected selectors\n- All while being **undetectable** by anti-bot systems\n\n## Comparison\n\n| MCP Server | Tools | Stealth | npx Install | Persistent Session |\n|------------|-------|---------|-------------|--------------------|\n| Chrome DevTools MCP | 30+ | No | Built-in | Yes |\n| whit3rabbit/camoufox-mcp | 1 | Yes | Yes | No |\n| redf0x1/camofox-mcp | 45 | Yes | No (clone) | Yes |\n| Sekinal/camoufox-mcp | 49 | Yes | No (clone) | Yes |\n| Playwright CLI | 60+ | No | Yes | Yes |\n| **[mcp-camoufox](https://github.com/RobithYusuf/mcp-camoufox)** | **127** | **Yes** | **Yes** | **Yes** |\n\n## Proven on Real Sites\n\n| Site | Challenge | Result |\n|------|-----------|--------|\n| `2captcha.com/demo/cloudflare-turnstile` | Cloudflare Turnstile widget | ✅ **\"Success!\"** via `click_turnstile()` tool ([proof](docs/images/turnstile.jpg)) |\n| `bot.sannysoft.com` | Firefox fingerprint tests | ✅ All green ([proof](docs/images/sannysoft.jpg)) |\n| `browserscan.net/bot-detection` | WebDriver/UA/CDP/Navigator | ✅ All categories \"Normal\" ([proof](docs/images/browserscan.jpg)) |\n\n### 🎯 Cloudflare Turnstile → Success via `click_turnstile()`\n\n<img src=\"docs/images/turnstile.jpg\" alt=\"Cloudflare Turnstile success\" width=\"500\">\n\n`click_turnstile()` auto-detects the widget via 6 selector fallback (`iframe[src*=challenges.cloudflare.com]`, `[data-sitekey]`, `.cf-turnstile`, …), computes checkbox position (offset_x=30 from widget left), and clicks with a 3-step Bezier-like approach — combined with Camoufox's native `humanize` + `disable_coop` for cross-origin iframe click.\n\n**Scope:** works on **Interactive Turnstile** (visible iframe widget). **Managed Challenge** interstitials (\"Just a moment...\") render the widget in shadow DOM — not supported here; use sister project [mcp-stealth-chrome](https://github.com/RobithYusuf/mcp-stealth-chrome) (Chrome+CDP) for those. Real-world bypass success also depends on IP reputation and browser fingerprint — code alone doesn't guarantee it.\n\n### 🧪 bot.sannysoft.com → Firefox Fingerprint Pass\n\n<img src=\"docs/images/sannysoft.jpg\" alt=\"sannysoft Firefox pass\" width=\"500\">\n\nUser Agent reports `Firefox/135.0`, WebDriver missing, WebDriver Advanced passed, Permissions prompt, Plugins length 5 passed, Languages `en-US,en`, WebGL Intel HD Graphics — all green. (\"Chrome: missing\" is expected — Camoufox spoofs Firefox, not Chrome.)\n\n### 🔍 browserscan.net/bot-detection → All Categories Normal\n\n<img src=\"docs/images/browserscan.jpg\" alt=\"browserscan normal\" width=\"500\">\n\nWebDriver, User-Agent, CDP, Navigator — every detection category returns **\"Normal\"**. Camoufox's C++-level Firefox patches leave zero automation signals.\n\n## Setup\n\n<details>\n<summary><b>Claude Code</b></summary>\n\n**Global** (available in all projects):\n```bash\nclaude mcp add camoufox --scope user -- npx -y mcp-camoufox@latest\n```\n\n**Project only** (current project):\n```bash\nclaude mcp add camoufox -- npx -y mcp-camoufox@latest\n```\n</details>\n\n<details>\n<summary><b>Claude Desktop</b></summary>\n\n**Global** — add to config file:\n- **macOS:** `~/Library/Application Support/Claude/claude_desktop_config.json`\n- **Windows:** `%APPDATA%\\Claude\\claude_desktop_config.json`\n- **Linux:** `~/.config/Claude/claude_desktop_config.json`\n\n```json\n{\n  \"mcpServers\": {\n    \"camoufox\": {\n      \"command\": \"npx\",\n      \"args\": [\"-y\", \"mcp-camoufox@latest\"]\n    }\n  }\n}\n```\n\n> Claude Desktop is always global — no project-level config.\n</details>\n\n<details>\n<summary><b>Cursor</b></summary>\n\n**Global** — Preferences > Features > MCP, or `~/.cursor/mcp.json`:\n\n**Project** — `.cursor/mcp.json` in project root:\n\n```json\n{\n  \"mcpServers\": {\n    \"camoufox\": {\n      \"command\": \"npx\",\n      \"args\": [\"-y\", \"mcp-camoufox@latest\"]\n    }\n  }\n}\n```\n</details>\n\n<details>\n<summary><b>Windsurf</b></summary>\n\n**Global** — `~/.windsurf/mcp.json`:\n\n**Project** — `.windsurf/mcp.json` in project root:\n\n```json\n{\n  \"servers\": {\n    \"camoufox\": {\n      \"command\": \"npx\",\n      \"args\": [\"-y\", \"mcp-camoufox@latest\"]\n    }\n  }\n}\n```\n</details>\n\n<details>\n<summary><b>VS Code (Continue / Cline / Kilo Code)</b></summary>\n\n**Global** — VS Code settings or `~/.continue/config.json`:\n\n**Project** — `.vscode/mcp.json` in project root:\n\n```json\n{\n  \"mcpServers\": {\n    \"camoufox\": {\n      \"command\": \"npx\",\n      \"args\": [\"-y\", \"mcp-camoufox@latest\"]\n    }\n  }\n}\n```\n</details>\n\n<details>\n<summary><b>Factory (Droid)</b></summary>\n\n**Global** — `~/.factory/mcp.json`:\n\n**Project** — `.factory/mcp.json` in project root:\n\n```json\n{\n  \"mcpServers\": {\n    \"camoufox\": {\n      \"type\": \"stdio\",\n      \"command\": \"npx\",\n      \"args\": [\"-y\", \"mcp-camoufox@latest\"],\n      \"disabled\": false\n    }\n  }\n}\n```\n\nOr via CLI:\n```bash\ndroid mcp add camoufox \"npx -y mcp-camoufox@latest\"\n```\n</details>\n\n<details>\n<summary><b>OpenCode</b></summary>\n\n**Global** — `~/.config/opencode/opencode.json`:\n\n**Project** — `opencode.json` in project root:\n\n```json\n{\n  \"mcp\": {\n    \"camoufox\": {\n      \"type\": \"local\",\n      \"command\": [\"npx\", \"-y\", \"mcp-camoufox@latest\"],\n      \"enabled\": true\n    }\n  }\n}\n```\n\n> Note: OpenCode uses `\"type\": \"local\"` (not `\"stdio\"`) and `command` as a single array.\n</details>\n\n<details>\n<summary><b>Trae (ByteDance)</b></summary>\n\n**Global** — `~/.trae/mcp.json`:\n\n**Project** — `.trae/mcp.json` in project root:\n\n```json\n{\n  \"mcpServers\": [\n    {\n      \"name\": \"camoufox\",\n      \"command\": [\"npx\", \"-y\", \"mcp-camoufox@latest\"]\n    }\n  ]\n}\n```\n\n> Note: Trae uses an **array** format for `mcpServers`, not an object.\n</details>\n\n<details>\n<summary><b>Antigravity (Google)</b></summary>\n\n**Global** — `~/.gemini/antigravity/mcp_config.json`:\n\n```json\n{\n  \"mcpServers\": {\n    \"camoufox\": {\n      \"command\": \"npx\",\n      \"args\": [\"-y\", \"mcp-camoufox@latest\"]\n    }\n  }\n}\n```\n\nOr via UI: Agent Panel > `...` > MCP Servers > Manage MCP Servers > View raw config.\n\n> Antigravity is global only — no project-level MCP config.\n</details>\n\n### Requirements\n\n| Requirement | Version | Check |\n|-------------|---------|-------|\n| **Node.js** | 18+ | `node --version` |\n\nThat's all. Camoufox browser binary (~80MB) downloads automatically on first launch.\n\n## All 127 Tools\n\n### Browser Lifecycle (4)\n\n| Tool | Description |\n|------|-------------|\n| `browser_launch` | Launch stealth browser. Options: `url`, `headless`, `humanize`, `geoip`, `locale`, `width`, `height`, `fresh_profile`. If a browser is already running these options are ignored — `browser_close` first to relaunch. |\n| `browser_close` | Close browser. Reports exactly what survived — e.g. *\"3 persisted, 1 session-only (dropped)\"* — so a lost login is never a mystery. Temp profile removed if `fresh_profile` was used. |\n| `reset_profile` | Wipe the persistent profile at `~/.camoufox-mcp/profile` (browser must be closed first) |\n| `browser_recover` | Escape hatch when the browser is wedged and `browser_close` can't finish: force-drops the connection, resets state, and reports a profile lock held by another Camoufox |\n\n### Navigation (4)\n\n| Tool | Description |\n|------|-------------|\n| `navigate` | Go to URL. Options: `wait_until` (domcontentloaded/load/networkidle), `timeout` |\n| `go_back` | Back in history |\n| `go_forward` | Forward in history |\n| `reload` | Reload page |\n\n### DOM & Content (7)\n\n| Tool | Description |\n|------|-------------|\n| `browser_snapshot` | Get interactive elements with ref IDs. **Call after every navigation.** On large pages narrow with `roles=[\"button\",\"textbox\"]` or paginate with `offset`/`limit` — refs stay stable. |\n| `screenshot` | Capture viewport, full page, or **one element** (`ref` / `selector` — perfect for documenting a modal). Returns the **image inline** plus the saved path, so no second read step. `return_image=false` for path only. |\n| `get_text` | Text from page or selector (max 5000 chars) |\n| `get_html` | HTML from page or selector (max 10000 chars) |\n| `get_url` | Current URL + title |\n| `save_pdf` | ⚠️ Not available on Camoufox — Playwright implements PDF generation only for headless Chromium, and Camoufox is Firefox. Returns a clear error; use `screenshot(full_page=true)` instead. |\n| `search_page` | Grep the current page's visible text with surrounding context — costs nothing next to a snapshot or screenshot |\n\n### Element Interaction (12)\n\n| Tool | Description |\n|------|-------------|\n| `click` | Click by ref ID. Options: `button`, `dblclick`. If the real mouse click is blocked, it falls back to a full synthetic pointer sequence (`pointerdown`→`mousedown`→`pointerup`→`mouseup`→click) **and says so** — a degraded click is never reported as a clean one. |\n| `click_text` | Click by visible text. **Refuses to guess:** several matches → fails with a numbered candidate list (tag, text, ancestor path, ref). Narrow with `within` (`\"@dialog\"`, a CSS selector, or `\"ref:e5\"`) or choose with `index`. |\n| `click_role` | Click by ARIA role + name. Same `within` / `index` / ambiguity guard as `click_text`. |\n| `hover` | Hover over element |\n| `fill` | Fill input/textarea — always **replaces** the old value (`email`/`number` inputs are cleared explicitly first; Firefox's select-all is a no-op on those, which otherwise made a re-fill append) |\n| `select_option` | Select from dropdown |\n| `check` / `uncheck` | Toggle checkbox/radio |\n| `upload_file` | Upload file to input |\n| `click_element_offset` | Click at an x%/y% position inside an element — wide labels whose real checkbox sits at the left edge, sliders, split buttons |\n| `click_at_corner` | Click a corner (close/X, delete, dismiss controls live there, not in the centre) |\n| `paste_text` | Fill via a **real** clipboard paste (Ctrl/Cmd+V) so frameworks that only listen for `paste` — Svelte 5 / Solid runes, some Qwik forms — actually receive it |\n\n### Keyboard (2)\n\n| Tool | Description |\n|------|-------------|\n| `type_text` | Type char by char. Options: `delay`. For OTP, masked inputs, date pickers. |\n| `press_key` | Key or combo: `Enter`, `Escape`, `Tab`, `Control+a`, `Meta+c` |\n\n### Mouse XY (4)\n\n| Tool | Description |\n|------|-------------|\n| `mouse_click_xy` | Click at exact coordinates. Optional `steps` (0=instant, 15-30=human-like pre-movement) |\n| `mouse_move` | Move cursor to coordinates. Optional `steps` for interpolated path |\n| `click_turnstile` | Auto-find + humanized click on Cloudflare Turnstile widget. Params: `offset_x` (default 30), `offset_y`, `wait_render_ms`. Works on Interactive Turnstile (visible iframe widget). Not for Managed Challenge interstitials. |\n| `drag_and_drop` | Drag between two elements |\n\n### Wait (7)\n\n| Tool | Description |\n|------|-------------|\n| `wait_for` | Wait for selector or text (visible/hidden/attached/detached) |\n| `wait_for_navigation` | Wait for page load |\n| `wait_for_url` | Wait for URL pattern match. Wrap in `/…/` for regex; a bare `/path` is treated as a substring. |\n| `wait_for_response` | Wait for network response pattern |\n| `wait_for_change` | Wait until the page actually CHANGES and report what changed (url/title/DOM size/text) — the honest replacement for a fixed sleep after a click |\n| `wait_for_request` | Block until the page ISSUES a matching request — confirms an action really fired its API call |\n| `wait_for_any_of` | Race several conditions (`selector`/`text`/`url_contains`/`title_contains`) — returns the first that matches so the agent can branch in one call. Ideal for post-login flows. |\n\n### Tabs (4)\n\n| Tool | Description |\n|------|-------------|\n| `tab_list` | List all tabs. Pages the site opens itself (`window.open` / `target=_blank`, e.g. OAuth popups) are auto-tracked and appear here too. |\n| `tab_new` | Open new tab |\n| `tab_select` | Switch tab by `index` or `url_contains` (first tab whose URL matches) |\n| `tab_close` | Close tab by `index` (-1 = active) or `url_contains`. The active tab is tracked by identity, so closing a lower-indexed tab never silently switches you to another one. |\n\n### Cookies (3)\n\n| Tool | Description |\n|------|-------------|\n| `cookie_list` | List cookies. Options: `domain` filter |\n| `cookie_set` | Set cookie with `expires_days`, `http_only`, `secure`, `same_site`. **`expires_days=0` (default) makes a session cookie that dies at `browser_close`** — pass a lifetime to keep a login across relaunches. |\n| `cookie_delete` | Delete by name/domain. Empty = clear all. |\n\n### Local Storage (3)\n\n| Tool | Description |\n|------|-------------|\n| `localstorage_get` | Get all or specific key |\n| `localstorage_set` | Set key-value |\n| `localstorage_clear` | Clear all |\n\n### Session Storage (3)\n\n| Tool | Description |\n|------|-------------|\n| `sessionstorage_get` | Get all or specific key |\n| `sessionstorage_set` | Set key-value |\n| `sessionstorage_clear` | Clear all sessionStorage for the origin (parity with `localstorage_clear`) |\n\n### JavaScript (2)\n\n| Tool | Description |\n|------|-------------|\n| `evaluate` | Run JS in page context |\n| `inject_init_script` | Inject script that runs on every page load |\n\n### Element Inspection (5)\n\n| Tool | Description |\n|------|-------------|\n| `inspect_element` | Full element info: tag, attributes, box, styles |\n| `get_attribute` | Get specific attribute |\n| `query_selector_all` | Query multiple elements by CSS selector |\n| `get_links` | Get all links with URL + text. Options: `filter` |\n| `form_introspect` | Whole-form analysis in one call: label, type, value, required/pattern/length, validation state, and the JS framework each field is bound to |\n\n### Frames (2)\n\n| Tool | Description |\n|------|-------------|\n| `list_frames` | List all frames/iframes |\n| `frame_evaluate` | Run JS inside a frame |\n\n### Batch Operations (6)\n\n| Tool | Description |\n|------|-------------|\n| `batch_actions` | Multiple actions in one call (click, fill, type, press, wait) |\n| `fill_form` | Fill multiple fields + optional submit |\n| `login_classic` | Composite login for email→password forms (Google/Microsoft/generic). Auto email→Next→password→submit, optional TOTP 2FA (`totp_secret` or `totp_code`). Collapses 5–8 calls into one. |\n| `navigate_and_snapshot` | Navigate + snapshot in one call |\n| `smart_fill` | Fill fields by **label text** (fuzzy) instead of refs — no snapshot needed; optional `submit_label` |\n| `workflow_run` | Run a list of tool calls in sequence; resumable via `start_at` after a failure |\n\n### Viewport (2)\n\n| Tool | Description |\n|------|-------------|\n| `get_viewport_size` | Get width x height |\n| `set_viewport_size` | Set dimensions |\n\n### Scroll (2)\n\n| Tool | Description |\n|------|-------------|\n| `scroll` | Scroll up/down/left/right by pixel amount |\n| `scroll_to` | Scroll a specific element into view (`ref`/`selector`, `block` alignment) |\n\n### Dialog (2)\n\n| Tool | Description |\n|------|-------------|\n| `dialog_handle` | Pre-set accept/dismiss for the next alert/confirm/prompt on **any** open tab (first dialog wins, then disarms) |\n| `dialog_auto_handle` | PERSISTENT handler — stays armed across every dialog and every tab, including popups. `enabled=false` removes it |\n\n### Accessibility (1)\n\n| Tool | Description |\n|------|-------------|\n| `accessibility_snapshot` | Accessibility tree for LLM understanding |\n\n### Console & Network (5)\n\n| Tool | Description |\n|------|-------------|\n| `console_start` / `console_get` | Capture and retrieve browser console messages. Capture spans **all tabs** and follows newly opened tabs/popups (re-calling `console_start` resets cleanly — no listener stacking). |\n| `network_start` / `network_get` | Capture network requests across **all tabs** (follows tab switches + popups). `network_start(capture_bodies=true)` also records request/response headers + text bodies. `network_get(filter=...)` narrows by URL substring; each row shows an `#id`. |\n| `network_get_detail` | Full request + response (headers + text body) for one captured request by `#id` or `url` substring. Needs `capture_bodies=true`. Replaces the `evaluate()`+`fetch()` workaround for inspecting API payloads. |\n\n### Compound (reduce round-trips) (4)\n\n| Tool | Description |\n|------|-------------|\n| `wait_and_snapshot` | Wait for selector/text + return snapshot in one call |\n| `back_and_snapshot` | Navigate back + return snapshot |\n| `reload_and_snapshot` | Reload page + return snapshot |\n| `click_and_snapshot` | Click + wait + return snapshot. Perfect for buttons that trigger navigation. |\n\n### Smart Selectors (skip snapshot) (3)\n\n| Tool | Description |\n|------|-------------|\n| `find_by_text` | Find by visible text — returns **every** match with a ref, ancestor path and total, so you can see whether the one you'd click is the one you mean. Supports `within`. |\n| `find_by_label` | Find input by label text, returns ref (lists all candidates if several match). Supports `within`. |\n| `find_by_placeholder` | Find input by placeholder, returns ref (lists all candidates if several match). Supports `within`. |\n\n### Session Portability (7)\n\n| Tool | Description |\n|------|-------------|\n| `cookie_export` | Export all cookies as JSON (for transfer) |\n| `cookie_import` | Import cookies from JSON (restore session) |\n| `cookie_export_file` | Write all cookies to a JSON file (Playwright format) |\n| `cookie_import_file` | Load cookies from a JSON file (Playwright format) |\n| `storage_state_save` | Save cookies + localStorage + sessionStorage to JSON file. Reload to skip login/CF. |\n| `storage_state_load` | Restore session from JSON (cookies + storage). Use `navigate_to` param to apply localStorage. |\n| `auth_capture` | Convenience: save current session to `~/.camoufox-mcp/sessions/<name>.json` |\n\n### Humanize / Anti-Bot (5)\n\n| Tool | Description |\n|------|-------------|\n| `humanize_click` | 3-step Bezier mouse approach + small jitter before click. Scrolls the target into view first (a real mouse click can't reach an off-screen element). Use for CF/DataDome pages. |\n| `humanize_type` | Gaussian-distributed keystroke delays (mean 80ms, sigma 30ms). Mimics human rhythm. |\n| `mouse_drift` | Random mouse movements over duration — builds mouse history before action. |\n| `mouse_record` / `mouse_replay` | Capture human mouse path then replay (anti-bot gold). |\n\n### Session Warmup & Detection (2)\n\n| Tool | Description |\n|------|-------------|\n| `session_warmup` | Visit Google/Wikipedia (random) before targeting protected site. Helps IP scoring. |\n| `detect_anti_bot` | Heuristic detection of CF/DataDome/Akamai/PerimeterX/Imperva/reCAPTCHA/hCaptcha. |\n\n### Assertions (4)\n\n| Tool | Description |\n|------|-------------|\n| `assert_element_visible` | PASS/FAIL — element exists and is visible |\n| `assert_text_present` | PASS/FAIL — text substring on page |\n| `assert_url_matches` | PASS/FAIL — URL matches pattern (substring or regex) |\n| `assert_clickable` | Hit-test **without clicking**: would a real click land? Names the element that would intercept it |\n\n### Workflow Helpers (3)\n\n| Tool | Description |\n|------|-------------|\n| `click_and_wait` | Click + wait for navigation/selector atomically (fewer roundtrips) |\n| `wait_for_network_idle` | Wait until there are zero in-flight requests for `idle_ms` continuously (tracked per request — the threshold really is yours, not Playwright's fixed 500 ms) |\n| `describe_page` | Compact LLM-friendly summary (title, h1, buttons, links, forms) + `intent` classifier (`login_email`, `otp_input`, `captcha`, `stay_signed_in`, …) — cheaper than `browser_snapshot` |\n\n### Scraping & Extraction (4)\n\n| Tool | Description |\n|------|-------------|\n| `detect_content_pattern` | Auto-detect repeated content (cards, listings) and suggest CSS selectors. **Run this before `extract_structured`.** |\n| `extract_structured` | Extract data from repeated elements as clean JSON. Auto-deduplicates, filters empties, `direct_text_only` prevents field mixing. |\n| `extract_table` | Extract HTML table as JSON array with auto-detected headers |\n| `scrape_page` | Smart scraper: auto-extract main content (strips nav/footer), links, meta, headings. Smart truncation at paragraph boundary. |\n\n### Browserless HTTP (4)\n\nThe browser is the expensive path. `impit` (already shipped with camoufox-js) speaks a real **Firefox** TLS/HTTP2 fingerprint, so these tools fetch without launching anything — and the fingerprint matches the browser this server actually drives. Verified against a Cloudflare-protected site that these tools cleared **without opening a browser at all**.\n\n> No `web_search`/`deep_research` here by design: scraping a SERP without an API key returns confidently wrong results for whole classes of query (Bing answers any \"how does …\" question with dictionary pages) and one major engine is TLS-blocked by some ISPs. A search tool that fails silently is worse than none — use your client's own search (WebSearch/Exa/Tavily) and feed the URLs to `scrape_markdown`.\n\n| Tool | Description |\n|------|-------------|\n| `http_request` | HTTP with a real Firefox TLS fingerprint, reusing the live browser's cookies by default — log in with the browser, then hit the site's API cheaply |\n| `http_session_cookies` | Show which browser cookies would be sent to a URL (verify session sharing before relying on it) |\n| `scrape_markdown` | One URL → clean LLM-ready markdown (headings/links/lists kept, nav/footer/scripts stripped). Browserless by default, `use_browser=true` for JS-heavy pages |\n| `smart_fetch` | Tries HTTP first, escalates to the stealth browser **only** when the response looks anti-bot blocked. The efficiency core |\n\n### Storage Inspection (4)\n\n| Tool | Description |\n|------|-------------|\n| `storage_snapshot` | Capture cookies + localStorage + sessionStorage into a named slot |\n| `storage_diff` | Diff current state against that slot — the fastest way to find which key holds a session token |\n| `indexeddb_list` | List IndexedDB databases for the origin (where many SPAs hide auth state) |\n| `indexeddb_delete` | Delete an IndexedDB database by name |\n\n### Debug (5)\n\n| Tool | Description |\n|------|-------------|\n| `server_status` | Health check: browser status, tabs, URL |\n| `get_page_errors` | Uncaught JS errors + unhandled promise rejections, captured by a hook installed at `browser_launch`. Buffer resets on every navigation — read it before navigating away. |\n| `export_har` | Export captured traffic as a valid **HAR 1.2** file (opens in DevTools). Needs `network_start` first; headers/bodies included only with `capture_bodies=true`. |\n| `page_stats` | Element count, page size, load metrics + extraction strategy recommendation |\n| `performance_timeline` | TTFB, DOMContentLoaded, load, FCP, LCP + the 5 slowest resources (CLS is unavailable — Firefox has no layout-shift API) |\n\n### Site Automation (2)\n\n| Tool | Description |\n|------|-------------|\n| `chatgpt_generate_image` | End-to-end image generation/edit on chatgpt.com in one call: fresh chat → optional reference-image upload → prompt → wait for the finished image → save PNG to `output_path`. Requires an authenticated chatgpt.com session. |\n| `chatgpt_generate_batch` | Many images in parallel (one tab per job, submit-all-then-collect). `shared_image_paths` + `style_suffix` keep a set visually consistent. |\n\n## Examples\n\n### Login to a website\n\n```\nbrowser_launch(url=\"https://accounts.google.com\", headless=false)\nbrowser_snapshot()                              # see email input\nfill(ref=\"e1\", value=\"user@gmail.com\")          # fill email\nclick(ref=\"e4\")                                 # click Next\nwait_for(selector='input[type=\"password\"]')     # wait for password page\nbrowser_snapshot()\nfill(ref=\"e2\", value=\"mypassword\")              # fill password\nclick(ref=\"e4\")                                 # click Next\n```\n\n### Fill a form in one call\n\n```\nfill_form(\n  fields=[\n    {ref: \"e3\", value: \"John Doe\"},\n    {ref: \"e5\", value: \"john@example.com\"},\n    {ref: \"e7\", value: \"Hello world\"}\n  ],\n  submit_ref=\"e10\"\n)\n```\n\n### Batch multiple actions\n\n```\nbatch_actions(actions=[\n  {type: \"click\", ref: \"e5\"},\n  {type: \"wait\", timeout: 1000},\n  {type: \"fill\", ref: \"e8\", value: \"search query\"},\n  {type: \"press\", key: \"Enter\"}\n])\n```\n\n### Search Google\n\n```\nbrowser_launch(url=\"https://google.com\")\nbrowser_snapshot()\nclick(ref=\"e5\")                               # search box\ntype_text(text=\"mcp-camoufox npm\")\npress_key(key=\"Enter\")\n```\n\n### Multi-tab research\n\n```\nbrowser_launch(url=\"https://github.com\")\ntab_new(url=\"https://stackoverflow.com\")\ntab_list()\ntab_select(index=0)\n```\n\n### Wait for API response\n\n```\nclick(ref=\"e10\")\nwait_for_response(url_pattern=\"/api/data\")\nbrowser_snapshot()\n```\n\n### Inspect elements\n\n```\ninspect_element(ref=\"e5\")\nget_links(filter=\"github.com\")\nquery_selector_all(selector=\".product-card\")\n```\n\n### Work with iframes\n\n```\nlist_frames()\nframe_evaluate(frame_index=1, expression=\"document.title\")\n```\n\n### Scrape job listings (structured)\n\n```\nbrowser_launch(url=\"https://glints.com/id/opportunities/jobs/explore\")\ndetect_content_pattern()                      # auto-suggest selectors\nextract_structured(\n  container_selector=\".job-card\",             # from detect_content_pattern\n  fields=[\n    {name: \"title\", selector: \"h3\"},\n    {name: \"company\", selector: \".company-name\"},\n    {name: \"location\", selector: \".location\"},\n    {name: \"url\", selector: \"a\", attribute: \"href\"}\n  ]\n)\n```\n\n### Scrape page content (smart)\n\n```\nscrape_page(only_main_content=true, max_text_length=8000)\n# Returns: title, url, meta, text (truncated at paragraph boundary),\n#          links, headings, truncated flag, total_text_length\n```\n\n### Manage storage\n\n```\nlocalstorage_get()\nlocalstorage_set(key=\"token\", value=\"abc123\")\ncookie_list(domain=\"example.com\")\n```\n\n## How It Works\n\n```\nAI Agent (Claude, Cursor, Windsurf, VS Code)\n    |\n    |  MCP Protocol (stdio JSON-RPC)\n    v\nmcp-camoufox (Node.js)\n    |\n    |  Playwright API (Juggler protocol, NOT CDP)\n    v\nCamoufox (Patched Firefox binary)\n    |\n    |  C++ anti-fingerprint patches\n    v\nWebsite (Cloudflare, bot detection — bypassed)\n```\n\n### Why stealth works\n\n- **Juggler protocol** instead of CDP — sites detecting Chrome DevTools Protocol cannot detect Camoufox\n- **C++ level patches** — fingerprint spoofing at browser engine level, not JavaScript injection\n- **GeoIP auto-detection** — timezone, locale, geolocation match your real IP\n- **Human-like behavior** — optional `humanize` mode for realistic mouse movements\n\n### Why sessions persist\n\nBrowser profile stored at `~/.camoufox-mcp/profile/`. Cookies, localStorage, IndexedDB survive across sessions. Login once, stay logged in.\n\n### Why refs work better\n\n`browser_snapshot` tags elements with `data-mcp-ref` attributes. This is:\n- More **token-efficient** than sending full HTML\n- More **reliable** than CSS selectors that break when sites update\n- **Clickable** via `click(ref=\"e5\")` — no selector gymnastics\n\n## Data Storage\n\n| Path | Contents |\n|------|----------|\n| `~/.camoufox-mcp/profile/` | Browser profile (cookies, localStorage, cache) |\n| `~/.camoufox-mcp/screenshots/` | Screenshots, PDFs, HAR exports |\n\nReset everything: `rm -rf ~/.camoufox-mcp/` — or call the `reset_profile` tool (browser must be closed first).\n\n### Switching between accounts on the same domain\n\nThe default profile persists across `browser_close` calls, so the next login on the same domain inherits cookies + session — sometimes redirecting to the wrong account. Two options:\n\n- **`browser_launch(fresh_profile=true)`** — uses a temp profile dir that's removed on `browser_close`. Best for one-off logins.\n- **`reset_profile`** (browser must be closed) — wipes the shared profile entirely.\n\n## Troubleshooting\n\n| Problem | Fix |\n|---------|-----|\n| \"Browser not running\" | Call `browser_launch` first |\n| Click blocked by overlay | A synthetic pointer-event fallback fires and the response warns you (`⚠`). If the widget still ignores it, dismiss the blocker (`press_key(\"Escape\")`) or use `mouse_click_xy`. |\n| Clicked the wrong \"Cancel\"/\"Save\" | `click_text` now fails with a candidate list instead of guessing. Use `within=\"@dialog\"` to stay inside the open modal, or `index=N`. |\n| Click on a Radix/Headless UI/MUI option did nothing | The real click was blocked and the old fallback used a bare `el.click()`, which those libraries ignore. Fixed — the fallback now replays the full pointer sequence. Upgrade if you're on ≤0.7.2. |\n| Login gone after `browser_close` | `cookie_set` without `expires_days` creates a session cookie, which no browser writes to disk. Pass `expires_days=30`, or use `storage_state_save`/`auth_capture`. `browser_close` now tells you how many cookies were dropped. |\n| Stale refs after navigation | Call `browser_snapshot` again — refs regenerate each time |\n| Window too large | `browser_launch(width=1024, height=768)` |\n| First launch slow | Downloading Camoufox binary (~80MB). Happens once. |\n| Huge snapshot output | Normal for big pages. Use `get_text` or `evaluate` instead. |\n| iframe not accessible | Use `list_frames` + `frame_evaluate` |\n| CAPTCHA appears | Cannot auto-solve. Use `headless=false` and solve manually. |\n| Login lands on wrong account | Profile carry-over. Use `fresh_profile=true` on launch or `reset_profile`. |\n| Need a PDF | `save_pdf` can't work on Firefox/Camoufox. Use `screenshot(full_page=true)`. |\n| Field value looks concatenated | Fixed — `fill`/`fill_form`/`batch_actions`/`login_classic` now clear `email`/`number` inputs before typing. Upgrade if you're on ≤0.7.2. |\n| `humanize_click` did nothing | Fixed — it now scrolls the element into view and errors if the element is outside the viewport. |\n| MCP server silently dies | If you ran `pkill -f camoufox`, you killed the MCP node process too (its argv contains \"camoufox\"). Target the binary specifically — e.g. `pkill -f \"Camoufox.app/Contents/MacOS\"` — or use `pkill -f camoufox-js`. |\n\n## License\n\nMIT\n\n---\n\nBuilt by [RobithYusuf](https://github.com/RobithYusuf)\n","readmeFilename":"README.md"}