Fortress

io.github.tiliondevPublished by GitHub account tiliondevv0.1.3Updated Oct 27, 2026

Stealth browser for AI agents: fetch pages behind Cloudflare/DataDome/CAPTCHA, extract clean data.

Overview

AI-generated overview

Fortress gives an assistant a stealth Chromium browser as MCP tools, so it can load pages that block ordinary automation and extract their data.

What you can do
  • Fetch and read pages that sit behind Cloudflare, DataDome or CAPTCHA, and search the web
  • Extract structured data from pages and from PDF, DOCX and XLSX documents
  • Crawl whole sites and probe them for their private JSON APIs
  • Drive a page: list elements, click, fill fields, press keys, wait, run JavaScript
  • Run multi-step flows such as login, pagination, infinite scroll or checkout
  • Capture screenshots, save pages, download files, save and load browser profiles, and hand out a CDP endpoint for Playwright or Puppeteer
When to use it
Useful when an assistant needs to read or scrape sites that block plain fetches or stock headless browsers, or when you want agent-driven browsing with a consistent, non-flagged fingerprint. Also relevant for multi-step web tasks and site-wide crawling.
Requirements
Runs locally as a stdio process, installed from PyPI (tilion) and started with uvx or the tilion-mcp command; the SDK downloads a prebuilt binary for Linux x64 or Windows x64. Activation via tilion activate or a TILION_LICENSE_KEY is needed for the v3 engine; without it the public first-generation engine runs. Optional TILION_BASE_URL and TILION_API_KEY switch to a hosted server; TILION_MCP_HEADLESS, TILION_MCP_PREWARM and TILION_ALLOW_PRIVATE_EGRESS tune the browser. Desktop only.
Before you install
The browser is designed to evade bot detection, so use it only for legitimate automation, testing and scraping of public data and respect site terms and local law. TILION_ALLOW_PRIVATE_EGRESS=1 disables the SSRF guard and lets tools reach localhost and private IPs. TILION_API_KEY is a bearer secret for the hosted server. Tools can click, fill forms, run JavaScript, download files and save profiles, which can change remote state or capture credentials. Activation signs in with GitHub, Google or…

Installation

In SourceWeft

  1. Open Fortress in the dashboard and add it to a workspace.
  2. Enable the server for the chats that should use its tools.

Desktop only via STDIO. STDIO servers start a local process, so they need the SourceWeft desktop host.

Other MCP clients

Follow the launch instructions in the repository.

README

[Fortress]

One browser engine to rule them all

Stealth Chromium engine · v3 (Chromium 153)

[Chromium] [Docker pulls] [Discord]
[Copy for agent] [llms.txt] [MCP server] [npm tilion-mcp]

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 scans the browser fingerprint. Stock Chrome fails CreepJS, BrowserScan, rebrowser and WebGL checks and is blocked. Fortress passes all four and the page loads.]

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.

[Fortress extracting books.toscrape.com into typed JSON records live over CDP]
[Fortress auto-paginating across pages of quotes.toscrape.com]
Auto-pagination: 30 quotes across 3 pages.
[Fortress deep-crawling a product detail page]
Deep detail crawl: UPC · price · tax · stock · reviews.
[Before: a stock browser is blocked by Akamai on aa.com with Access Denied. After: Fortress loads the real page and Akamai's sensor accepts it.]

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

bash
pip install tilion-fortress                       # or: npm install tilion-fortressdocker run --rm -p 9222:9222 tilion/fortress:latest   # any OS, raw CDP on :9222
python
from tilion_fortress import Fortressfrom 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")
js
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:

bash
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.

The tilion CLI
CommandWhat it does
tilion activateUnlock v3 with a one-click device flow (browser sign-in)
tilion activate --headlessSame 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 refreshRe-issue the key before it expires
tilion license logoutRemove 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 mcpRun the Fortress MCP server, stealth browsing as agent tools
tilion [--port N]Launch the engine and print the CDP endpoint

Platforms

PlatformPackageWidevineStatus
Linux x64portable tarball · Docker · pip / npm[yes][yes] shipping
Windows x64portable .zip + tillion.cmd launcher[yes][yes] shipping
Linux arm64portable tarball (Graviton, dense cloud fleets)no[yes] shipping
Linux x86 · armhfportable tarball (32-bit x86 / ARM)no[yes] shipping
macOS (arm64 / x64).app, built from source[yes]build from source

The arm64, x86 and armhf builds ship without the bundled Widevine CDM.

Set it up with an AI assistant

[Ask ChatGPT] [Ask Claude] [Ask Gemini] [Copy for agent]

Every session a distinct machine

[Twelve identical browser windows, tagged same machine times twelve, turn one by one into twelve different machines, each with its own screen and clock.]

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 launchesDistinct
Canvas fingerprint40 / 40
Audio fingerprint40 / 40
GPU (WebGL renderer)25
Screen resolution14
Timezone (geo-coherent with language)23
Platform mix31 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

[Beta]

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.

[Requests from coding agents hit a verify-you-are-human check and are blocked, then route through Fortress, pass the check and reach the website.]

bash
pip install "tilion[mcp]"                  # or zero-install: npx -y tilion-mcpclaude 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:

json
{ "mcpServers": { "fortress": { "command": "tilion-mcp" } } }
tools
Get blocked pagesfetch_protected_page · read_page · get_page_html · search_web
Structured dataextract_page (schema-aware) · extract_document (PDF/DOCX/XLSX)
Whole sitescrawl_site (auto-SPA) · recon_site_apis (find the private JSON API)
Drive a pagepage_elements · click_button · fill_field · press_key · wait_for · evaluate_js
Multi-step flowsrun_browser_task (login, paginate, infinite-scroll, checkout, …)
Capture / authscreenshot_page · save_page · download_file · save_profile / load_profile
Bring your ownget_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

[A Playwright script where one line changes from p.chromium.launch() to p.chromium.connect_over_cdp on localhost:9222. The rest of the script stays the same.]

With Fortress running (Docker or the tilion command), one line changes: launch() becomes connect_over_cdp("http://localhost:9222").

FrameworkConnect via
browser-use (~70k stars)cdp_url="http://localhost:9222"
Crawl4AI (~58k stars)CDP endpoint
Stagehand (~21k stars)connectOverCDP
LangChain Playwright toolkitPlaywright CDP
Playwright / Puppeteer (Python & JS)connect_over_cdp / connect
Fortress MCP + pip install tilion facadetools 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 tellWhy it catches a JS spoof
toString self-revealA native method stringifies to function get vendor() { [native code] }; an override stringifies to its own source, so one .toString() catches it.
Descriptor and hasOwnPropertygetOwnPropertyDescriptor exposes redefined props, and hasOwnProperty('toString') returns true on a tampered function where a native one returns false.
failsTypeErrorNative 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:

js
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

LayerThe tellsWhere the fix livesFortress
A: driver / binary artifactscdc_ ChromeDriver vars, WebDriver protocol surfaceDrive raw CDP, skip chromedriver[yes] built to be driven this way
B: CDP side-effectsRuntime.enable leaks via sourceURL + init-script footprints, however clean the binary isThe control / CDP-client layer: hold back Runtime.enable, use Runtime.addBinding + isolated worlds[yes] no leak (verified on rebrowser)
C: fingerprint surfacecanvas, WebGL, WebGPU, audio, fonts, navigator, across main frame, iframes, workersThe engine (C++), because JS overrides self-reveal[yes] this is Fortress
D: network / IP egressdatacenter ASN, IP reputation, geo-vs-persona mismatchYour proxies (residential / mobile), or the Tilion hosted version[partial] 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 Playwrightpuppeteer-extra-stealthundetected-chromedriverCamoufoxAntidetect apps¹Fortress v3
Spoof layernoneJS injectionCDP/config patchC++ engine (Firefox)C++ engineC++ engine (Chromium)
toString yields [native code]n/a[no]n/a[yes][yes][yes]
Survives realm re-acquisition (iframe/worker)[no][no][no][yes][yes][yes]
No Runtime.enable leak[no][no][partial][yes][yes][yes]
Engine = Chrome / V8 (majority traffic)[yes][yes][yes][no] Firefox[yes][yes]
Coherent Chromium TLS shape[yes][yes][yes][no] Firefox[yes][yes]
Parameter-level WebGL + WebGPU coherencen/a[no][no][partial] no WebGPUvaries[yes]
Per-launch fleet dynamism (distinct machine)[no][no][no][yes][no] persistent by design[yes] 48/48
Full-persona re-key on snapshot resume[no][no][no][no][no][yes] on_restore
Native single-surface C++ patch enginen/an/an/a[yes][no] closed[yes] 81 patches
States its own limitsn/an/an/a[yes][no][yes]

¹ 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.

What changed from v2 to v3
Axisv2v3
Chromium base151 / 152153.0.8010.36
Single-surface C++ patches~3481
Persona transportcommand line, per launch, host-readableIPC-delivered, in-process, per-context isolated
Multi-identity in one binaryone persona per processper-BrowserContext isolation
Snapshot resumerelaunch to change identityon_restore full-persona re-key, no relaunch
Fleet distinctnessnot measured48/48 across 64 clones (500-clone stress-gated)
Canvas noiseseededidempotent, byte-exact cross-path, 64-bit seeds, fail-closed
WebGLrenderer string only (incoherent numbers)parameter-level limits + extensions + string, per backend
WebGPUabsent / software-backend tellcoherent with the persona GPU + per-clone variation
Fontsmetric substitutes (~33)154-family substrate, enumeration gated to the persona
Client-HintsUA basicsfull Sec-CH-UA + Device-Memory on the navigation path
prefers-color-schemefleet-uniformper persona (about a third dark)
Mouse motionraw driverrecorded-human trajectories (~10k paths, ~16× more human)
DRMno Widevinereal Widevine CDM bundled, EME verified

Full release notes

Results

Benchmark: 92 protected sites, eight stacks

Run on 2026-09-28 from US-East cloud machines, headless, on datacenter IPs with no proxies. Every tool loaded every target twice, each time on a fresh machine destroyed afterwards (1,584 machines). A run counts only if the real page loaded with no challenge or deny page. Method and target list: docs/BENCHMARK.md.

StackServedn95% range
Fortress86.4%159/18481 to 91
Camoufox74.5%137/18468 to 80
puppeteer-extra + stealth72.3%133/18465 to 78
Brave36.4%67/18430 to 44
nodriver35.9%66/18429 to 43
stock Chrome34.2%63/18428 to 41
patchright34.2%63/18428 to 41
undetected-chromedriver33.7%62/18427 to 41

95% Wilson intervals; Fortress's does not overlap the next stack's. Fortress got 2/2 on ten sites where neither Camoufox nor puppeteer-stealth got more than 1/2, and there is no site where it got 0/2 while either of them got 2/2. A repeat run the same day scored 85.3%.

Live detectors

Headless, from a datacenter IP, on the v3 binary. Reproduce with tools/gauntlet.py --bundle ./fortress-v153; dated re-runs are in docs/GAUNTLET_RESULTS.md.

SuiteStock ChromiumFortress v3
CreepJSflagged headless0% headless · 0% stealth, worker signals coherent
bot.sannysoft.comred rows0 failed · every intoli + PHANTOM_/HEADCHR_ check green · navigator.webdriver undefined
browserscan.netbot detected“Normal: No bots detected, could be a human” · WebDriver / Selenium / PhantomJS / Headless / CDP / DevTool all Normal
BrowserLeaks · WebGLSwiftShader leakUnmasked ANGLE (Intel HD Graphics, Direct3D11) with fully coherent D3D11 parameters
WebGPU (secure context)software-backend tellnavigator.gpu coherent with the persona GPU: adapter identity, limits, subgroup sizes (verified)
AmIUnique · pixelscan · ipheyautomation flagsconsistent, no automation flags
rebrowser bot-detectorRuntime.enable LEAKno leak · webdriver=false · clean init-scripts (raw CDP)
64-clone fleetone shared identity48/48 distinct canvas / audio / Math.random (fleet gate)
Cloudflare Turnstileblockedcleared: a human click cleared a live challenge (headed, datacenter IP)

[Fortress clearing a live Cloudflare challenge, then passing sannysoft and BrowserScan]

Unedited capture in a real window: Fortress clears a live Cloudflare challenge, turns bot.sannysoft.com all green and reads BrowserScan "Normal".

Configure the persona

The default is a fresh coherent persona per launch, delivered over IPC. Pin or override any surface with --uxr-* switches:

--uxr-platform / --uxr-ua-platform / --uxr-ua-os / --uxr-ua-arch / --uxr-ua-bitness--uxr-ua-platform-version / --uxr-ua-brand / --uxr-hw-concurrency / --uxr-device-memory--uxr-webgl-vendor / --uxr-webgl-renderer / --uxr-webgl-fullparams / --uxr-webgpu-vendor--uxr-canvas-seed / --uxr-audio-seed / --uxr-timezone / --uxr-languages / --uxr-color-scheme--uxr-screen-width / --uxr-screen-height / --uxr-webrtc-policy=disable_non_proxied_udp
Env varPurpose
TILION_NO_DEFAULTS=1Skip the default persona (bare launch)
TILION_TZ / TILION_LANGQuick timezone / language override

Every flag, env var and coherence rule: docs/UXR_CONFIG.md.

Build & verify

bash
export CHROMIUM_VERSION=$(cat CHROMIUM_VERSION)   # 153.0.8010.36build/build.sh                         # depot_tools, sync the tag, apply patches, gn gen, ninjabuild/rebase-monthly.sh 154.0.XXXX.0   # bump + 3-way apply + rebuild + gauntlet-gate

Output: out/Fortress/chrome. The fork is 81 single-surface patches, and the gauntlet gates every release. The first-generation patch series is public and rebuilds with the same script.

Fortress ships only from these channels:

Every release ships SHA256SUMS (the SDKs check it on install). Verify the Docker image by digest against the release notes:

bash
BASE=https://github.com/tiliondev/fortress/releases/download/v153.0.8010.36curl -LO $BASE/fortress-v153-linux-x64.tar.gzcurl -Ls $BASE/SHA256SUMS | sha256sum -c --ignore-missing     # -> OKdocker inspect --format '{{index .RepoDigests 0}}' tilion/fortress:153.0.8010.36

Reference

Troubleshooting

Still blocked on Cloudflare, DataDome or Kasada. Usually the IP: datacenter ranges are flagged before any page script runs. Retry through a residential or mobile proxy; if it clears, the fingerprint was fine. Tilion Cloud runs Fortress on residential egress (waitlist at tilion.com).

The fingerprint looks off on a Linux host. The default persona is Windows, but TLS and some OS signals follow the host. Match the persona to your egress OS with --uxr-*, or run the native Windows build.

macOS. Run the Docker image or build the .app from source.

A detector flags something the gauntlet passes. Confirm you are on the current rebase, then email [email protected] with the test page.

FAQ

Does Fortress work with Selenium? Drive it over CDP. chromedriver adds the driver artifacts Fortress is built to avoid.

How is it different from puppeteer-stealth, undetected-chromedriver, nodriver and patchright? Those patch the JavaScript or CDP layer, which toString and realm re-acquisition reveal, and headless they send HeadlessChrome in the user agent. In the benchmark they loaded 34 to 36% (puppeteer-stealth 72.3%) against Fortress's 86.4%.

How is it different from Camoufox? Same engine-level idea. Camoufox forks Firefox; Fortress forks Chromium/V8, the majority engine, and adds WebGPU coherence and on_restore fleet re-identity. Benchmark: 86.4% vs 74.5%.

Is it an alternative to Multilogin, GoLogin, Kameleo, AdsPower or Dolphin? Those are closed-source builds sold as persistent profiles with bundled proxies. Fortress is an engine you run yourself, with a fresh identity per launch, published first-generation patches and no telemetry.

Does it run headless? Yes. The benchmark is headless, and headless and headed launches present the same fingerprint.

Do I still need proxies? For sites that block datacenter ranges, yes. Fortress keeps timezone, locale and WebRTC coherent with whatever exit you use.

Is it open source? What does it cost? Source-available under the Fortress Source Available License 1.1; see License.

Is this legal? Fortress is for legitimate automation, testing and scraping of public data. Respect each site's terms and your local law.

Will it pass everything forever? No. Detection moves, so Fortress rebases on Chromium monthly and publishes a dated, reproducible gauntlet.

Roadmap
  • First-party residential and mobile egress, wired to the existing geo-coherence
  • Keystroke and scroll variance (mouse motion has shipped)
  • TLS ClientHello (JA3/JA4) in the persona surface set
  • Linux arm64 / x86 / armhf tarballs (rolling out) and a macOS .app
  • Code-signed Windows .exe and macOS .app

Shipped in v3: the IPC persona with per-context isolation, on_restore, parameter-level WebGL and WebGPU, recorded-human mouse motion, the Widevine CDM, the native Windows build, the MCP server and the 92-site benchmark.

Repo layout
patches/     the first-generation C++ patch series (Fortress Source Available License 1.1)build/       args.gn, build.sh, apply-patches.sh, rebase-monthly.sh, windows/, macos/packaging/   tilion launcher, fonts.conf, Dockerfile, .deb + bundle buildersfonts/       222 metric-compatible OS-named font files (154 distinct families, incl. color emoji)sdk/         python + node (tilion-fortress) prebuilt-binary SDKsmcp/         the Fortress MCP server (29 tools) and the agent skilltools/       gauntlet.py, the CreepJS / Sannysoft / BrowserScan CI gatedocs/        UXR_CONFIG (the --uxr-* reference), GAUNTLET_RESULTS, BENCHMARK

Contributing

Fortress does not accept outside pull requests; see CONTRIBUTING.md. Found a detection vector or a leak? Email [email protected] with a reproducible test page.

License

Fortress Source Available License 1.1. Free to read, modify, rebuild and redistribute, and to use for development, testing and evaluation at any size. Production use is free for individuals and for organizations under US$500,000 in cumulative funding and US$300,000 or less in ARR; other organizations need one flat subscription (fortress.tilion.com/pricing, LICENSE, SUBSCRIPTION-TERMS.md). Earlier BSD-licensed releases keep their BSD permissions (LICENSE-BSD-LEGACY). Chromium and the bundled fonts keep their own licenses (NOTICE).

Source: README.md at commit 026da4d

Tools

0
SourceWeft has not started this package in its sandbox yet, so its tools are not known.

Version history

1
  1. v0.1.3LatestSep 16, 2026

Score

40% of the applicable checks met

How complete this listing is, computed from the registry entry, the endpoint and public sources. Not a rating of the server and not a statement that it is safe or working today: reachability is a dated check, and no installs or reviews go into the score.

  • Reached in the last 30 days25 pts

    Keep the endpoint answering the MCP handshake; SourceWeft probes it every 30 days.

  • Auth declared10 pts

    Declare the credential headers in the registry entry, or keep the endpoint answering the probe so its auth can be classified.

  • Tools listed15 pts

    Answer tools/list without a credential, or ship a package that starts in a sandbox without one.

  • DescriptionRequired15 pts
  • Logo10 pts
  • Documentation15 pts
  • License10 pts

    Declare a license in the repository or the registry entry.