Self-hosted MCP server for stealth browser automation with human-like OS-level input.
Copy the AI prompt to install this server into Claude Code, Cursor, or another agent — or use 1-click editor setup below.
💡 Paste the JSON block into your client's configuration file under mcpServers, then restart the application.
Stealth browser automation that actually works. Runs Camoufox (custom Firefox) in Docker with zero Chrome DevTools Protocol exposure, real OS-level mouse and keyboard input via PyAutoGUI, and a JSON HTTP API + MCP server to control it all remotely. Watch it live via noVNC. Run a single instance or spin up a cluster behind HAProxy with Redis cookie sync, request queuing, and sticky sessions. Drive it with curl, pipe YAML scripts through stdin, send multi-step scripts via the API, use page loaders to auto-handle popups and paywalls, or connect AI agents directly via MCP. Optional Bearer token auth via AUTH_TOKEN.
Passes Cloudflare, CreepJS, BrowserScan, Pixelscan, and every other bot detector we've thrown at it. While Chromium-based tools are getting caught by the first line of defense, this thing walks through the front door unnoticed.
| Component | What It Does |
|---|---|
| Camoufox | A custom build of Firefox with zero Chrome DevTools Protocol exposure. Bot detectors look for CDP signals — this browser simply doesn't have any. |
| Xvfb | Virtual framebuffer that lets the browser run with a full graphical display inside a container, no physical monitor needed. This matters because headless mode is another detection signal. |
| PyAutoGUI | Generates real OS-level mouse movements and keystrokes. The browser receives these as genuine user input — it has no idea it's being automated. |
| noVNC | Web-based VNC client so you can watch the browser in real time from your own browser. Great for debugging and seeing exactly what's happening. |
| Openbox | Lightweight window manager — adds title bars and resize handles to popup windows (OAuth dialogs, etc.) that would otherwise be too small to interact with. Zero stealth impact. |
| HTTP API | A JSON API on port 8080 that lets you control everything — navigate pages, click elements, type text, take screenshots, manage tabs, handle cookies, and more. |
| MCP Server | Model Context Protocol server at /mcp on the same port. AI agents (Claude, etc.) can drive the browser directly over MCP using Streamable HTTP. |
| ffmpeg | x11grab against Xvfb for screen recording. Captures actual rendered pixels including the OS-level mouse cursor — see Screen Recording. |
Pre-installed extensions: uBlock Origin (ads/trackers), LocalCDN (prevents CDN tracking), ClearURLs (strips tracking params), Consent-O-Matic (auto-handles cookie popups).
Port 8080 is the HTTP API, port 5900 is the VNC viewer (http://localhost:5900/).
Run multi-step scripts in one request:
Also accepts "yaml": "..." with the same YAML format used in script mode. In single-instance mode, requests are serialized automatically — send multiple scripts in parallel and they queue up.
See docs/api.md for all actions and the full API reference.
Navigation uses app-owned controls, not a hidden browser-library timeout: each attempt gets 30 seconds by default, one timeout retry, and a one-second retry delay. Pass timeout, retry_count, and retry_delay with goto, refresh, or new_tab when a workflow needs different bounds. retry_count: 0 disables retries. See navigation controls for the limits and retry behavior.
There are two ways to interact with pages. System input uses PyAutoGUI to generate real OS-level mouse and keyboard events — the browser cannot tell these apart from a real human. Playwright input uses CSS selectors and DOM event injection — easier, but theoretically detectable by behavioral analysis. Use system input on any site with bot protection.
Full breakdown and usage guide: docs/stealth.md
Mount test media read-only at /media and set VIRTUAL_CAMERA_FILE and/or VIRTUAL_MICROPHONE_FILE. Pages that call navigator.mediaDevices.getUserMedia() receive tracks captured from those files, so camera and microphone checks can run without host hardware.
Sources must remain inside /media; restart the browser after changing them. A request for a kind without a configured virtual source fails with NotFoundError rather than falling back to hardware. Virtual tracks use the source file's native format, so pages must not require incompatible exact media constraints. This virtualizes getUserMedia() only, not enumerateDevices().
To switch sources during an authorized test without replacing an already acquired camera or microphone track, enable VIRTUAL_MEDIA_DYNAMIC=true. Dynamic mode is disabled by default. Use set_virtual_media_source to choose an existing relative file name under VIRTUAL_MEDIA_DIR, or upload_virtual_media to add bounded base64 content and optionally activate it. An upload filename is only a safe, type-matching media name; the service generates a collision-safe stored basename, returns it, and never overwrites an existing named source. Before storage or activation, the decoded upload is checked with ffprobe for a stream matching the requested camera or microphone kind. The media directory must be writable for uploads; VIRTUAL_MEDIA_UPLOAD_MAX_BYTES defaults to 50 MiB. Existing page streams keep their track identities while the source changes.
Dynamic mode accepts files from the configured media directory only. It does not accept arbitrary host paths, remote URLs, WebSocket streams, or other live ingress. Both actions use the normal API authentication: when AUTH_TOKEN is set, send the usual Authorization: Bearer <token> header. See docs/api.md#virtual-camera-and-microphone and docs/configuration.md for the action contract and writable-volume setup.
AI agents can control the browser over the Model Context Protocol via Streamable HTTP at /mcp on the same port 8080. All browser actions are exposed as MCP tools — navigation, screenshots, clicking, typing, JavaScript evaluation, cookies, and more.
For authorised test flows that need a human review when a verification widget appears, use detect_challenge. It is read-only: it reports a best-effort absent, present, or unknown status with bounded vendor/location evidence, but never clicks, enters a frame, or solves a challenge. Pass scroll_into_view: true to bring the first visible detected frame or widget into the viewport for VNC handoff; it still never clicks or focuses it. In cluster mode, include it as a run_script step. See the API reference.
No reviews yet — be the first to share how this listing worked for you.
Showcase your server listing on GitHub or your project documentation. Embed this dynamic SVG badge to highlight official listing status and live engagement.
[](https://allmcps.com/mcp/stealthy-auto-browse)<a href="https://allmcps.com/mcp/stealthy-auto-browse"><img src="https://allmcps.com/api/badge/stealthy-auto-browse?style=directory" alt="Stealthy Auto Browse on AllMCPs" /></a>