What it is
Fortress is an open-source stealth Chromium engine. It is a recompiled fork that corrects the browser fingerprint from inside the engine: the surfaces bot detectors read, canvas, WebGL, audio, fonts, navigator, and about thirty more, are patched in Chromium's C++, with no JavaScript layer sitting on top for a page to catch.
It ships as an ordinary browser binary that exposes a CDP endpoint. A page inspecting itself sees stock Chromium: navigator.vendor resolves to the real C++ getter, reports [native code], and reads the same from the main frame, every iframe, and every Web Worker.
Why the engine
Patching the engine beats patching the page because a JavaScript spoof is a function standing where a native one belongs. The usual approach overrides navigator.webdriver, spoofs the WebGL vendor, and rewrites navigator.plugins from script. Detectors set the returned value aside and ask whether the thing returning it is native.
| The tell | Why it catches a JS spoof |
|---|---|
| toString self-reveal | A native getter stringifies to [native code]; an override stringifies to its own source. |
| Descriptor / hasOwnProperty | getOwnPropertyDescriptor exposes redefined props; hasOwnProperty('toString') is true on a tampered function. |
| Wrong-this TypeError | Native getters throw on the wrong this; a naive shim stays quiet, and the silence is the signal. |
Realm re-acquisition defeats every main-world patch. A detector grabs a pristine primitive from another realm and turns it on your function:
const iframe = document.createElement('iframe');
document.body.appendChild(iframe);
const realToString = iframe.contentWindow.Function.prototype.toString;
realToString.call(navigator.__lookupGetter__('vendor'));
// A JS spoof returns its own source here, and it is caught.
// Fortress returns [native code], because it is native code.The getter for navigator.vendor is the C++ getter, identical across every realm. There is no injection layer to detect because there is no injection. The same holds one layer down: because the binary uses BoringSSL like real Chrome, its JA3/JA4 TLS handshake matches a genuine Chrome install rather than an OpenSSL client a detector can correlate against the user-agent.
Proof
Fortress clears the standard client-side detectors, verified against live suites and reproduced with the engine's gauntlet. These are client-side checks: passing them is necessary, not sufficient. Numbers move with detector and site changes, so read them as representative, not guaranteed.
| Suite | Stock Chromium | Fortress |
|---|---|---|
| CreepJS | flagged headless | 0% headless |
| bot.sannysoft.com | red rows | all green |
| browserscan.net | bot detected | no bots detected |
| Cloudflare Turnstile | blocked | cleared |
Honest residual tells: on CreepJS, Fortress shows a fuzzy similarity signature and a small canvas-noise fingerprint, and the shipped UA can run slightly ahead of stable. These are tracked in the open, not hidden. Fortress does not claim to be undetectable.
Comparison
Stealth tools fall on a line from page-patch to library-patch to engine-recompile, with detectability dropping at each step. Fortress sits at the far end, and unlike the other engine-level fork it is Chromium rather than Firefox.
| Tool | Approach | [native code] | Realm-safe | Engine |
|---|---|---|---|---|
| puppeteer-stealth | JS patch | no | no | Chromium |
| undetected-chromedriver | driver patch | no | no | Chromium |
| playwright / patchright | library patch | no | partial | Chromium |
| nodriver | CDP-less driver | host's | host's | Chromium |
| Camoufox | recompiled engine | yes | yes | Firefox |
| Fortress | recompiled engine | yes | yes | Chromium |
Driver-level tools like nodriver avoid the CDP tells but leave the fingerprint as the host machine's. Fortress corrects the fingerprint itself, in the engine, on the majority browser.
What you can do
Fortress matters wherever a real browser is the only thing a site will accept. Common jobs:
- AI web agents that get blocked mid-task and need the rendered page anyway.
- Price and market-data collection behind DataDome or Akamai.
- Search-results scraping without a SERP API key.
- QA and regression testing against sites protected by anti-bot.
- Research and academic data gathering at scale.
- Competitive intelligence: catalog, pricing, and content monitoring.
Use it for automation you are permitted to run, and respect each site's terms, rate limits, and the law in your jurisdiction.
Persona
The binary carries no brand strings; the launcher applies a coherent default Windows identity. Override any surface with --uxr-* switches, or set TILION_NO_DEFAULTS=1 for a bare launch.
--uxr-timezone=America/New_York
--uxr-hw-concurrency=16
--uxr-languages=en-US,en
--uxr-webgl-vendor / --uxr-webgl-renderer
--uxr-canvas-seed / --uxr-audio-seedThe engine keeps user-agent, Client-Hints, and JA3/JA4 TLS shape in agreement, so a Windows persona rides on a matching stack rather than a stack that contradicts it.
Using it
You reach Fortress through Tilion. One install pulls the engine binary and gives you a Python API that boots it locally and drives it over CDP.
pip install tilion
from tilion import Tilion
async with Tilion() as t: # launches the Fortress engine
page = await t.fetch("https://protected.example") # past Cloudflare / 403
print(page["title"])Any CDP-speaking stack, browser-use, Playwright, Puppeteer, connects the same way through t.cdp_url. For AI agents, use the Fortress MCP server below.
Open source
Fortress is BSD-3. The fork is a set of small, single-purpose C++ patches you can read in a minute each, and the whole engine rebuilds from Chromium source with one script, so you can diff what you built against what ships.
- Read every surface correction as an individual patch.
- Rebuild the binary from source and verify it against the release.
- Send a detector that flags the engine; it becomes the next patch.
Source, patches, releases, and the reproducible gauntlet: github.com/tiliondev/fortress.
MCP
The Fortress MCP server hands any AI agent the stealth engine the moment it gets blocked. When a fetch hits Cloudflare, DataDome, PerimeterX, a 403, or a CAPTCHA, the agent calls a tool and gets the page, driving a real recompiled Chromium on your own machine and IP.
Install
pip install "tilion[mcp]" # pulls the Fortress engine automatically
tilion-mcp # or: python -m tilion.mcp (stdio transport)The server is a thin, open wrapper over the Tilion framework, which drives the engine. The stealth Chromium downloads on first run and is cached locally.
Add to your client
Claude Desktop or Cursor, in the MCP config:
{ "mcpServers": { "fortress": { "command": "tilion-mcp" } } }Cline and Windsurf use the same command under their MCP settings. If tilion-mcp is not on your PATH, run python with args -m tilion.mcp.
The 26 tools
| Tool | What the agent uses it for |
|---|---|
fetch_protected_page | get a page behind Cloudflare / DataDome / 403 / CAPTCHA |
read_page | clean reader-mode markdown of any page, plus tables |
extract_page | markdown, tables, metadata, or a schema-shaped record |
extract_document | extract a PDF / DOCX / XLSX / CSV / HTML file to markdown |
page_elements | the page's buttons, links, fields, and headings |
click_button · fill_field · press_key | drive a form by text, selector, or key |
current_page · get_page_html · evaluate_js · wait_for | inspect, script, or wait on the working page |
crawl_site | crawl a whole site, auto-handling SPA/JS, to pages plus sitemap |
recon_site_apis | reverse-engineer a site's private XHR/JSON API, secret-scrubbed |
run_browser_task · list_browser_tasks | 20 multi-step flows: login, paginate, checkout |
search_web | web search through the stealth browser, no SERP API |
screenshot_page · save_page · download_file | capture PNG, export pdf/html/text, download a file |
get_cookies · save_profile · load_profile | read cookies, persist or restore an authenticated session |
list_tabs · close_tab | manage open tabs |
get_stealth_cdp_endpoint | a CDP url for your own browser-use / Playwright / Puppeteer |
Tools are annotated readOnlyHint or destructiveHint, so clients auto-approve reads and gate writes. Every tool is timeout- and SSRF-guarded, caps its output, and returns a structured error instead of hanging. The browser is pre-warmed at startup, so the first call is about 100 ms.
Why reach for it
An agent with only its built-in web fetch, versus the same task through the Fortress MCP:
| Task | Built-in fetch | Fortress MCP |
|---|---|---|
| Reddit r/programming titles | 0 items | 26 titles |
| JS-rendered quotes page | 0 quotes | 10 quotes |
| Wikipedia article | 403 to bots | 52k markdown |
| Hacker News top stories | 30 in 24s | 30 in 2s |
Fingerprint suites read clean: Sannysoft all green, CreepJS 0% headless, BrowserScan normal. A datacenter IP can still be blocked on the hardest targets regardless of fingerprint.
Configuration
| Env var | Default | Effect |
|---|---|---|
TILION_MCP_PREWARM | 1 | boot the browser at startup; 0 is lazy |
TILION_MCP_HEADLESS | 1 | 0 shows a visible window |
TILION_ALLOW_PRIVATE_EGRESS | 0 | 1 allows localhost / private IPs (SSRF guard off) |
TILION_MCP_TOOL_TIMEOUT | 120 | per-tool wall-clock cap, in seconds |
TILION_BASE_URL / TILION_API_KEY | — | hosted mode (coming soon) |
How it works
tilion-mcpruns the Tilion framework in local mode and attaches over CDP to the Fortress engine. Stealth is applied natively in the C++ engine, so there is no detectable JS injection, and one warm browser backs every tool for the server's lifetime.
FAQ
Is Fortress undetectable?
No, and it does not claim to be. The fingerprint is native and coherent, and it clears the common client-side detectors in testing. Anti-bot systems also weigh the egress IP and behavior, so a datacenter IP still gets blocked on the hardest targets regardless of fingerprint.
How is it different from puppeteer-stealth or undetected-chromedriver?
Those patch a stock browser in JavaScript or at the driver, and the patch is itself detectable through toString, property descriptors, and pristine copies re-acquired from an iframe or worker. Fortress corrects the fingerprint in Chromium's C++, so there is no injection layer for a page to find.
How is it different from Camoufox?
Same engine-level idea. Camoufox forks Firefox, a small slice of real traffic; Fortress forks Chromium and V8, the majority engine, so a Chrome persona is coherent by construction, including its TLS shape.
Does it get past Cloudflare and DataDome?
It clears their client-side checks in testing, including a live Turnstile challenge. Production outcomes also depend on IP reputation and behavior, so route the hardest sites through a residential or mobile IP.
Do I still need proxies?
For easy targets, no. For the biggest sites, yes: a clean fingerprint on a datacenter IP is flagged at the network layer before a page script runs. Route through a residential or mobile IP and retry.
Is it open source?
Yes. The Fortress engine is BSD-3. The patch series is published, so you can read each surface correction and rebuild the engine from Chromium source yourself.
