Provides a stealth Chromium engine that allows AI agents to bypass bot detection and scrape data from protected websites.
Also known as tiliondev/fortress, tilion, tilion-mcp
- Stars
- 800
- Tools
- —
- Downloads, 30 days
- —
- Latest version
- 0.1.3
- Last commit
- Nov 3, 2026
- License
- —
What is Fortress MCP?
Fortress is an MCP server. Provides a stealth Chromium engine that allows AI agents to bypass bot detection and scrape data from protected websites.
Summary generated from the project's README
About Fortress MCP server
Developers needing to scrape data from protected websites can use Fortress to bypass bot detection. It provides a stealth Chromium engine that modifies browser fingerprints directly within the C++ code, making automated sessions appear as ordinary Chrome installations. This approach allows users to connect existing Playwright or Puppeteer automation via the Chrome DevTools Protocol without changing their core logic or adding external stealth plugins.
The server is available as a local tool that can be run via Docker, pip, or npm. It is free for developers and includes no limits on sessions or concurrency. To use the full v3 engine, users can activate a license using the tilion CLI. When integrated as an MCP server, it provides 29 tools to AI clients like Claude, Cursor, or Windsurf, enabling them to navigate sites that would otherwise block standard fetch requests or headless browsers.
What you can do with it
- 1Automated web scrapingA developer can instruct an AI client to extract structured data from paginated web pages.
- 2Generating unique browser identitiesUsers can launch multiple sessions where every instance presents a completely distinct hardware and software fingerprint.
Written from the project's README. Every use case is checked against a quote from it.
How to install Fortress MCP
Formats verified 10 Nov 2026Install Fortress MCP in Claude Code
$ claude mcp add --env TILION_API_KEY=<YOUR_TILION_API_KEY> fortress -- uvx tilionInstall Fortress MCP in Cursor
~/.cursor/mcp.json
{
"mcpServers": {
"fortress": {
"command": "uvx",
"args": [
"tilion"
],
"env": {
"TILION_API_KEY": "<YOUR_TILION_API_KEY>"
}
}
}
}Install Fortress MCP in VS Code
.vscode/mcp.json
{
"servers": {
"fortress": {
"type": "stdio",
"command": "uvx",
"args": [
"tilion"
],
"env": {
"TILION_API_KEY": "<YOUR_TILION_API_KEY>"
}
}
}
}Install Fortress MCP in Claude Desktop
claude_desktop_config.json
{
"mcpServers": {
"fortress": {
"command": "uvx",
"args": [
"tilion"
],
"env": {
"TILION_API_KEY": "<YOUR_TILION_API_KEY>"
}
}
}
}Install Fortress MCP in Codex
~/.codex/config.toml
[mcp_servers.fortress] command = "uvx" args = ["tilion"] [mcp_servers.fortress.env] TILION_API_KEY = "<YOUR_TILION_API_KEY>"
Install Fortress MCP in Gemini CLI
~/.gemini/settings.json
{
"mcpServers": {
"fortress": {
"command": "uvx",
"args": [
"tilion"
],
"env": {
"TILION_API_KEY": "<YOUR_TILION_API_KEY>"
}
}
}
}Configuration
TILION_API_KEYSecretBearer key for the hosted Tilion server (cloud mode only).
CHROMIUM_VERSIONTILION_ALLOW_PRIVATE_EGRESSSet 1 to allow tools to reach localhost / private IPs (SSRF guard off).
TILION_BASE_URLRun browsers on a hosted Tilion server instead of locally.
TILION_MCP_HEADLESSSet 0 to show a visible browser window (default 1).
TILION_MCP_PREWARMBoot the browser at startup so the first tool call is instant (default 1).
| Name | Description | |
|---|---|---|
| TILION_API_KEY | Bearer key for the hosted Tilion server (cloud mode only). | Secret |
| CHROMIUM_VERSION | — | |
| TILION_ALLOW_PRIVATE_EGRESS | Set 1 to allow tools to reach localhost / private IPs (SSRF guard off). | |
| TILION_BASE_URL | Run browsers on a hosted Tilion server instead of locally. | |
| TILION_MCP_HEADLESS | Set 0 to show a visible browser window (default 1). | |
| TILION_MCP_PREWARM | Boot the browser at startup so the first tool call is instant (default 1). |
Automated checks
Ran Nov 12, 2026Full report →Passed our automated checks. That is not a security audit: read the code and give the server the narrowest access it needs. How checks work
- Source repository linked and reachablePass
- Open source license (OSI)No licenseFinding
- Commit or release in the last yearPass
- Package name not close to a popular packagePass
- Remote endpoint uses HTTPSNot checked
- Destructive tools are labelledNot checked
- No hidden instructions to the modelPass
- No critical advisory in the package or its dependenciesPass
README
View on GitHubOne browser engine to rule them all
Stealth Chromium engine · v3 (Chromium 153)
Fortress is a Chromium fork that stops scrapers and browser agents from getting blocked. Bot detectors flag automation by reading the browser fingerprint. Fortress corrects that fingerprint inside Chromium's C++, so the browser reads as an ordinary Chrome install. Point your existing Playwright or Puppeteer at it over CDP; nothing else in your code changes.
Headless, on datacenter IPs, with no proxies, Fortress loaded 86.4% of 92 protected sites. The next best stack (Camoufox) loaded 74.5%.
A site reads the fingerprint. Stock Chrome driven by a script fails CreepJS, BrowserScan, rebrowser and the WebGL check and is blocked; Fortress passes all four.
Real runs, fully headless
Unedited captures over CDP, with no stealth plugins. Reproduce with examples/scrape_demos.py.
Akamai, before and after, on aa.com from the same residential IP: a stock browser gets Access Denied, Fortress loads the page and Akamai issues its _abck sensor cookie. Same result on lowes.com, macys.com and kohls.com.
Contents
Quick start · Every session a distinct machine · The Fortress MCP · Works with your stack · Why patch the engine · How Fortress compares · Results · Configure the persona · Build & verify · Reference
Quick start
pip install tilion-fortress # or: npm install tilion-fortress
docker run --rm -p 9222:9222 tilion/fortress:latest # any OS, raw CDP on :9222
from tilion_fortress import Fortress
from playwright.sync_api import sync_playwright
with Fortress() as f: # launches the engine on a CDP endpoint
with sync_playwright() as p:
browser = p.chromium.connect_over_cdp(f.cdp_url)
page = browser.new_page()
page.goto("https://bot.sannysoft.com")
import { Fortress } from "tilion-fortress";
import { chromium } from "playwright";
const f = await Fortress.launch();
const browser = await chromium.connectOverCDP(f.cdpUrl);
const page = await browser.newPage();
await page.goto("https://browserscan.net");
The pip and npm SDKs download a prebuilt, SHA-256-verified binary (Linux x64, Windows x64). Portable tarballs, a .deb and the Windows .zip are on Releases.
Free for developers
v3 is free for developers, with no machine, session or concurrency caps. Activate once:
tilion activate # sign in with GitHub, Google or email; key saved to ~/.tilion/license.jwt
The key is checked offline and Fortress never reports usage. Without activation it still runs, on the public first-generation engine. For CI, Docker and agents, set TILION_LICENSE_KEY=<key> or run tilion activate --token <key>; one key covers a fleet. Production keys for larger organizations are at fortress.tilion.com/pricing.
| Command | What it does |
|---|---|
tilion activate |
Unlock v3 with a one-click device flow (browser sign-in) |
tilion activate --headless |
Same flow, prints the URL and code (SSH or remote hosts) |
tilion activate --token <jwt> |
Save a key with no browser (CI, agents) |
tilion license status [--json] |
Show the saved key's tier and expiry (--json for scripts) |
tilion license refresh |
Re-issue the key before it expires |
tilion license logout |
Remove the saved key and drop back to v1 |
tilion get [platform] |
Download the build for this host. tilion get list shows all: linux-x64, arm64, armhf, x86, win-x64, mac-arm64, mac-x64 |
tilion mcp |
Run the Fortress MCP server, stealth browsing as agent tools |
tilion [--port N] |
Launch the engine and print the CDP endpoint |
Platforms
| Platform | Package | Widevine | Status |
|---|---|---|---|
| Linux x64 | portable tarball · Docker · pip / npm | shipping | |
| Windows x64 | portable .zip + tillion.cmd launcher |
shipping | |
| Linux arm64 | portable tarball (Graviton, dense cloud fleets) | no | shipping |
| Linux x86 · armhf | portable tarball (32-bit x86 / ARM) | no | shipping |
| macOS (arm64 / x64) | .app, built from source |
build from source |
The arm64, x86 and armhf builds ship without the bundled Widevine CDM.
Set it up with an AI assistant
Every session a distinct machine
Each launch mints a fresh, internally coherent machine: GPU, screen, cores, timezone, language and fonts all agree. The persona reaches the renderer over IPC, so nothing shows on the command line and every BrowserContext can hold its own identity. Across 40 back-to-back launches of the same binary:
| Across 40 launches | Distinct |
|---|---|
| Canvas fingerprint | 40 / 40 |
| Audio fingerprint | 40 / 40 |
| GPU (WebGL renderer) | 25 |
| Screen resolution | 14 |
| Timezone (geo-coherent with language) | 23 |
| Platform mix | 31 Windows · 9 macOS |
Reproduce with tools/gauntlet.py --runs 40. A 64-clone fleet resumed from one snapshot comes up 48/48 distinct, because on_restore re-keys the whole persona with no relaunch.
The Fortress MCP
A Model Context Protocol server that gives Claude, Codex, Cursor, Windsurf, Cline or any MCP client a stealth browser as 29 tools, local and free. When a plain fetch is blocked, the agent calls a tool and gets the page.
pip install "tilion[mcp]" # or zero-install: npx -y tilion-mcp
claude mcp add fortress -- tilion-mcp # Claude Code
For Claude Desktop, Cursor (~/.cursor/mcp.json), Cline and Windsurf, add the same block to the client's MCP config:
{ "mcpServers": { "fortress": { "command": "tilion-mcp" } } }
| tools | |
|---|---|
| Get blocked pages | fetch_protected_page · read_page · get_page_html · search_web |
| Structured data | extract_page (schema-aware) · extract_document (PDF/DOCX/XLSX) |
| Whole sites | crawl_site (auto-SPA) · recon_site_apis (find the private JSON API) |
| Drive a page | page_elements · click_button · fill_field · press_key · wait_for · evaluate_js |
| Multi-step flows | run_browser_task (login, paginate, infinite-scroll, checkout, …) |
| Capture / auth | screenshot_page · save_page · download_file · save_profile / load_profile |
| Bring your own | get_stealth_cdp_endpoint: a CDP url for Playwright / Puppeteer / browser-use |
The full tool reference, benchmarks and agent skill are in mcp/.
Works with your stack
With Fortress running (Docker or the tilion command), one line changes: launch() becomes connect_over_cdp("http://localhost:9222").
| Framework | Connect via |
|---|---|
| browser-use (~70k stars) | cdp_url="http://localhost:9222" |
| Crawl4AI (~58k stars) | CDP endpoint |
| Stagehand (~21k stars) | connectOverCDP |
| LangChain Playwright toolkit | Playwright CDP |
| Playwright / Puppeteer (Python & JS) | connect_over_cdp / connect |
Fortress MCP + pip install tilion facade |
tools for agents, raw CDP underneath |
Why patch the engine, not the page
A JavaScript stealth patch is a function standing where a native one belongs, and detectors check for exactly that:
| The tell | Why it catches a JS spoof |
|---|---|
toString self-reveal |
A native method stringifies to function get vendor() { [native code] }; an override stringifies to its own source, so one .toString() catches it. |
Descriptor and hasOwnProperty |
getOwnPropertyDescriptor exposes redefined props, and hasOwnProperty('toString') returns true on a tampered function where a native one returns false. |
failsTypeError |
Native getters throw a specific TypeError 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 takes 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')); // returns your source code. Caught.
In Fortress the getter for navigator.vendor is the C++ getter. It reports [native code] because it is native code, the same in every frame and worker. Fortress applies the Camoufox idea to V8 and Blink, so the fingerprint matches a Chrome user agent by construction.
The four layers of bot detection
| Layer | The tells | Where the fix lives | Fortress |
|---|---|---|---|
| A: driver / binary artifacts | cdc_ ChromeDriver vars, WebDriver protocol surface |
Drive raw CDP, skip chromedriver | built to be driven this way |
| B: CDP side-effects | Runtime.enable leaks via sourceURL + init-script footprints, however clean the binary is |
The control / CDP-client layer: hold back Runtime.enable, use Runtime.addBinding + isolated worlds |
no leak (verified on rebrowser) |
| C: fingerprint surface | canvas, WebGL, WebGPU, audio, fonts, navigator, across main frame, iframes, workers | The engine (C++), because JS overrides self-reveal | this is Fortress |
| D: network / IP egress | datacenter ASN, IP reputation, geo-vs-persona mismatch | Your proxies (residential / mobile), or the Tilion hosted version | bring your own with the self-hosted engine; available on the Tilion hosted version, waitlist at tilion.com |
Fortress is the Layer C engine, built to be driven so A and B hold too, and to stay geo-coherent (timezone, locale, WebRTC) once you bring a Layer D IP.
How Fortress compares
| Stock Playwright | puppeteer-extra-stealth | undetected-chromedriver | Camoufox | Antidetect apps¹ | Fortress v3 | |
|---|---|---|---|---|---|---|
| Spoof layer | none | JS injection | CDP/config patch | C++ engine (Firefox) | C++ engine | C++ engine (Chromium) |
toString yields [native code] |
n/a | n/a | ||||
| Survives realm re-acquisition (iframe/worker) | ||||||
No Runtime.enable leak |
||||||
| Engine = Chrome / V8 (majority traffic) | Firefox | |||||
| Coherent Chromium TLS shape | Firefox | |||||
| Parameter-level WebGL + WebGPU coherence | n/a | no WebGPU | varies | |||
| Per-launch fleet dynamism (distinct machine) | persistent by design | 48/48 | ||||
| Full-persona re-key on snapshot resume | on_restore |
|||||
| Native single-surface C++ patch engine | n/a | n/a | n/a | closed | 81 patches | |
| States its own limits | n/a | n/a | n/a |
¹ Multilogin / GoLogin / Dolphin / Nstbrowser: closed-source engine patches, persistent identity by design, bundled residential egress (their Layer-D advantage over Fortress).
Fortress builds on prior art: fingerprint-chromium, ChromiumFish and CloakBrowser came first, and Camoufox, Multilogin, GoLogin and Dolphin also patch engine C++. Fortress's edge is the combination: the broadest native surface set on a Chromium base, fleet dynamism with on_restore, and parameter-level coherence. Where it is behind: IP egress (bring your own) and behavioral humanization beyond mouse motion.
| Axis | v2 | v3 |
|---|---|---|
| Chromium base | 151 / 152 | 153.0.8010.36 |
| Single-surface C++ patches | ~34 | 81 |
| Persona transport | command line, per launch, host-readable | IPC-delivered, in-process, per-context isolated |
| Multi-identity in one binary | one persona per process | per-BrowserContext isolation |
| Snapshot resume | relaunch to change identity | on_restore full-persona re-key, no relaunch |
| Fleet distinctness | not measured | 48/48 across 64 clones (500-clone stress-gated) |
| Canvas noise | seeded | idempotent, byte-exact cross-path, 64-bit seeds, fail-closed |
| WebGL | renderer string only (incoherent numbers) | parameter-level limits + extensions + string, per backend |
| WebGPU | absent / software-backend tell | coherent with the persona GPU + per-clone variation |
| Fonts | metric substitutes (~33) | 154-family substrate, enumeration gated to the persona |
| Client-Hints | UA basics | full Sec-CH-UA + Device-Memory on the navigation path |
prefers-color-scheme |
fleet-uniform | per persona (about a third dark) |
| Mouse motion | raw driver | recorded-human trajectories (~10k paths, ~16× more human) |
| DRM | no Widevine | real Widevine CDM bundled, EME verified |
Results
Fortress MCP questions
How do I add Fortress MCP to Claude Code?
Run claude mcp add --env TILION_API_KEY=<YOUR_TILION_API_KEY> fortress -- uvx tilion in your terminal. Add --scope user to make it available in every project.
How do I add Fortress MCP to Cursor?
Open ~/.cursor/mcp.json and add the server under mcpServers, using the Cursor config shown in the install section above.
How does Fortress prevent being blocked by bot detectors?
Fortress corrects the browser fingerprint inside Chromium's C++, making the browser appear as an ordinary Chrome installation.
Can I use Fortress with my existing automation tools?
Yes, you can point existing Playwright or Puppeteer setups at Fortress using the Chrome DevTools Protocol (CDP).
Is there a cost for developers to use Fortress?
Version 3 is free for developers with no limits on machines, sessions, or concurrency.