AgentStack
MCP verified MIT Self-run

Veilbrowser

mcp-acunningham-ship-it-veilbrowser · by acunningham-ship-it

Stealth browser for AI agents — real Chrome over raw CDP, no Playwright/Puppeteer. TypeScript + MCP-native. Passes sannysoft 57/57, bypasses Cloudflare.

No reviews yet
0 installs
21 views
0.0% view→install

Install

$ agentstack add mcp-acunningham-ship-it-veilbrowser

✓ scanned · ✓ verified — works with Claude Code, Cursor, and more.

Security review

✓ Passed

No issues found. Passed automated security review. · v0.1.0 How review works →

  • Prompt-injection patterns
  • Secret / credential exfiltration
  • Dangerous shell & filesystem operations
  • Untrusted network calls
  • Known-malicious package signatures

What it can access

  • Network access Used
  • Filesystem access No
  • Shell / process execution No
  • Environment & secrets No
  • Dynamic code execution No

From automated source analysis of v0.1.0. “Used” means the capability is present in the source — more access means more to trust, not that it’s unsafe.

View the full security report →

Verified badge

Passed review? Show it. Paste this badge into your README — it links to the public security report.

AgentStack Verified badge Links to your public security report.
[![AgentStack Verified](https://agentstack.voostack.com/badges/verified.svg)](https://agentstack.voostack.com/security/report/mcp-acunningham-ship-it-veilbrowser)

Reliability & compatibility

Security review passed
0 installs to date
no reviews yet
1mo ago

Declared compatibility

Claude CodeClaude DesktopCursorWindsurf

Compatibility is declared by the source manifest. End-to-end runtime verification is coming — see below.

Preview Execution monitoring

We're building live execution health for every listing: tool-call success rate, median latency, uptime, and last-checked timestamps — measured, not self-reported. It isn't live yet, so we don't show numbers we can't stand behind.

How agent discovery & health will work →
Are you the author of Veilbrowser? Claim this listing to set pricing, connect Stripe payouts, and keep 70% of every sale.
Sign up to claim

About

Veil

A stealth automation runtime for AI agents. Drives real Chrome over raw CDP — no Playwright, no Puppeteer, no WebDriver, zero runtime dependencies.

Veil driving real Chrome: bot.sannysoft.com all-green, then straight through Cloudflare's JS challenge — no patches, no plugins.

To Instagram, Google, Reddit, Datadome, Akamai — Veil is Chrome. Same binary, same TLS, same JS engine, same canvas/WebGL/font fingerprint a human's browser has. We don't reimplement the browser (that's Chromium's 20-year, 1000-engineer job, and a hand-rolled engine is easier to fingerprint, not harder). We replace the part that gets you caught: the automation layer.


Why not Playwright / Puppeteer?

They're powerful and great for scripted QA. For agents on hostile sites they have three structural problems:

| Problem | Playwright/Puppeteer | Veil | |---|---|---| | Detectable | navigator.webdriver=true, --enable-automation, the Runtime.enable CDP tell, HeadlessChrome UA | webdriver scrubbed, no automation switches, no Runtime.enable, UA + client-hints normalized | | Robotic input | instant teleport clicks, fixed-cadence typing → behavioural detection | curved Bézier mouse paths, eased timing, human keystroke cadence | | Brittle for agents | CSS/XPath selectors that break constantly | accessibility-tree snapshot → stable integer refs; agents never write a selector |

Veil is dependency-free — Node 24 / Bun ship a global WebSocket, so the entire CDP transport is ~120 lines we own. Nothing to patch, nothing to leak.

How Veil compares (honest)

The "real Chrome over raw CDP" idea isn't new — Python's nodriver pioneered it, and Camoufox (a C++-patched Firefox) scores even better on pure stealth. Veil isn't claiming to out-stealth them. Its wedge is where it lives and how agents use it:

  • TypeScript-native. The JS/TS agent ecosystem (Vercel AI SDK, LangChain.js, MCP) has

no strong raw-CDP stealth driver — it's stuck on Playwright + stealth plugins, or shelling out to Python nodriver. Veil is that missing piece.

  • MCP-native. Ships an MCP server, so any agent gets stealth browsing as tools with

zero glue.

  • Agent-first, not scraper-first. Accessibility-tree refs and human input are built for

an LLM driving the browser, not for a scraping script.

If you're in Python and just want raw stealth, use nodriver or Camoufox — they're great. Veil is for TypeScript agents and MCP hosts.

Quick start

Prerequisites: Chrome/Chromium on PATH (or VEIL_CHROME=/path/to/chrome), and Bun.

bun install
bun run examples/selftest.ts   # launches real Chrome, runs the full chain

In your code:

import { Browser } from "veilbrowser";

const browser = await Browser.launch({ headless: false });   // headful = stealthiest
const page = await browser.newPage();
await page.goto("https://example.com");

// Accessibility-tree snapshot → stable integer refs (no selectors).
const snap = await page.snapshot();
console.log(snap.text);
//  [1] textbox "Search"
//  [2] button "Sign in"

await page.fill(1, "hello");          // act by ref — human typing, jittered timing
await page.click(2);                  // curved Bézier mouse path, real CDP input
const png = await page.screenshot();  // PNG buffer for a vision model

await browser.close();

How the stealth works

  1. Launch (launcher.ts) — a real Chrome with the flags a normal profile uses,

minus the automation switches Playwright adds. --disable-blink-features=AutomationControlled flips navigator.webdriver to false at the engine level. Persistent userDataDir so the profile looks used (history, cookies), not freshly minted.

  1. Transport (cdp.ts) — raw WebSocket, flat session mode. **We never call

Runtime.enable** — that command is a primary CDP detection vector. Runtime.evaluate works without it.

  1. Page patch (stealth.ts) — injected via addScriptToEvaluateOnNewDocument

before any site code, on every frame: normalizes webdriver, window.chrome, plugins, languages, permissions.query, WebGL vendor — and makes the patched functions' toString() look native so the patch itself can't be detected. Kept deliberately small; over-patching is its own fingerprint.

  1. UA / client hints (page.ts) — strips the HeadlessChrome token from the UA

and the Sec-CH-UA brand headers.

  1. Human input (human.ts) — seedable PRNG drives curved mouse paths and

jittered keystroke timing.

Agent tooling (the other half of the product)

The selling point isn't only stealth — it's that agents drive it well:

  • snapshot() returns the page as a flat numbered index from the accessibility

tree (the semantic layer screen readers use). The #1 cause of agent breakage — guessed CSS/XPath selectors — is gone. The agent acts on a stable ref.

  • screenshot() returns a PNG buffer, ready for vision grounding.
  • click / fill / type drive real CDP input with human dynamics.
  • waitFor(expr) replaces flaky fixed sleeps.

Detection scorecard (measured, Chrome 148)

Run it yourself: bun run examples/detect.ts (headless) or VEIL_HEADFUL=1 bun run examples/detect.ts (headful — Veil auto-starts its own Xvfb, no wrapper needed).

Measured on an AMD Radeon (Renoir APU) host, real hardware GL via ANGLE/EGL:

| Detector | Mode | sannysoft | CreepJS "headless" | CreepJS "stealth" | |---|---|---|---|---| | Veil — headful + auto-Xvfb + real GPU | recommended | 57/57 | 0% | 0% | | Veil — headless + real GPU | server/fast | 57/57 | 33% | 0% | | (earlier: SwiftShader + heavy stealth) | superseded | 57/57 | 67% | 20% |

Live targets (bun run examples/hardtargets.ts, residential IP):

| Target | Result | |---|---| | Cloudflare JS challenge (scrapingcourse) | Bypassed | | Antibot challenge (scrapingcourse) | Bypassed | | Reddit — incl. its JS challenge | served clean (challenge auto-solved) | | Instagram — public profile | served clean |

Honest gaps we do not yet claim: interactive Turnstile/reCAPTCHA, enterprise DataDome/Kasada, logged-in sessions, high-volume behavioural trust. We test before we claim.

What moved the needle (each verified by re-running the suite):

  1. Real GPU, not SwiftShader. --use-gl=angle --use-angle=gl-egl drives the actual

AMD GPU → an authentic, self-consistent WebGL fingerprint. No vendor spoof = no lie for CreepJS's pixel-hash to catch.

  1. Headful on a server. Veil manages its own Xvfb display, so "headful" needs no

desktop. Eliminates the headless render quirks + tiny-screen tell (33% → 0%).

  1. Slim, self-gating stealth. The biggest surprise: the stealth patches themselves

were the "20% stealth" signal. A correctly-launched Chrome already reports webdriver === false (the right human value — forcing undefined is worse), 5 plugins, a real chrome object. So each patch now fires only when the value is genuinely anomalous; on healthy Chrome it's a no-op. Smaller surface = nothing to detect.

Use from an AI agent (MCP)

Veil ships an MCP server (src/mcp.ts) — already wired into persoje (~/.config/persoje/mcp.json), exposing 8 tools: goto, snapshot, click, fill, type, screenshot, eval, close. Verified end-to-end through persoje's own MCP client (discover → goto → snapshot). Any MCP host works:

{ "servers": { "veil": {
  "command": "/home/armani/.bun/bin/bun",
  "args": ["run", "/home/armani/projects/veil/src/mcp.ts"],
  "env": {}                          // headful + auto-Xvfb + real GPU (0% CreepJS).
                                     // Set VEIL_HEADLESS=1 for the faster server mode.
} } }

Testing

bun run examples/selftest.ts   # end-to-end: launch, stealth, snapshot, interact
bun run examples/detect.ts     # bot-detection scorecard (bot.sannysoft.com, etc.)
deno test tests/*.test.ts      # unit tests: PRNG, mouse paths, ref numbering

Unit tests cover:

  • PRNG (human.test.ts): xorshift32 determinism, range/int bounds, keystroke cadence, mouse timing
  • Snapshot refs (snapshot.test.ts): ref numbering (1-based, sequential, no gaps), AX-tree filtering
  • CDP framing (cdp-messages.test.ts): JSON-RPC structure, sessionId routing, command/response correlation

Status

Working today (verified against Chrome 148):

  • Zero-dep CDP runtime (raw WebSocket, flat session mode)
  • Stealth launch + page-script injection (--disable-blink-features=AutomationControlled)
  • UA/client-hint scrub (no "HeadlessChrome" token)
  • WebGL backend selection (hardware GPU via ANGLE/EGL, or SwiftShader + vendor masking)
  • AX-tree snapshot → stable integer refs for agent-friendly interaction
  • Human-like input: curved Bézier mouse paths, jittered keystroke timing, real CDP input
  • PNG screenshots (vision-model ready)
  • MCP server (src/mcp.ts) — stdio JSON-RPC; persoje, Claude, any MCP host drives Veil natively

Roadmap toward production:

  • [ ] Adversarial fingerprint suite — continuous scoring (CreepJS, sannysoft, Datadome demo)
  • [ ] Runtime.enable-leak hardening via isolated worlds for all eval
  • [ ] Headful-on-server via managed Xvfb; profile + proxy pools
  • [ ] Vision-based element grounding fallback (sparse AX-trees, canvas apps)
  • [ ] Network interception; response capture; session persistence & profile warm-up
  • [ ] Per-tab concurrency (many tabs, one socket — transport already supports it)

License

MIT.

Source & license

This open-source MCP server is cataloged on AgentStack and links to its original source — we do not rehost the code.

Install and usage instructions live in the source repository linked above.

Reviews

No reviews yet — be the first.

Versions

  • v0.1.0 Imported from the upstream source.