Skip to content

Latest commit

 

History

History
134 lines (109 loc) · 5.22 KB

File metadata and controls

134 lines (109 loc) · 5.22 KB

Fortress — agent setup guide

Paste this whole file into your AI agent (Claude, ChatGPT, Gemini, Cursor, Copilot, …) and it has everything it needs to set Fortress up and drive it.

Fortress is an open-source stealth Chromium engine that exposes raw CDP on http://localhost:9222. Any tool that drives a browser through Playwright, Puppeteer, or the Chrome DevTools Protocol uses it as a drop-in — swap the browser, keep the automation code. The fingerprint is corrected in the engine's C++, so you do NOT add puppeteer-stealth, undetected-chromedriver, or any JavaScript patching (those self-reveal and undo it).


1. Launch it — pick ONE (all expose CDP on http://localhost:9222)

Docker (any OS, nothing to build):

docker run -d --rm -p 9222:9222 tilion/fortress:latest

Python:

pip install tilion-fortress
from tilion_fortress import Fortress
f = Fortress()          # headless by default; native binary on Linux/Windows, Docker fallback on macOS
f.start()
print(f.cdp_url)        # -> http://127.0.0.1:9222
# ... drive it (section 2) ...
f.close()

Node:

npm install tilion-fortress
import { Fortress } from "tilion-fortress";
const f = await Fortress.launch();
console.log(f.cdpUrl);
await f.close();

Portable bundle (Linux x64 / Windows x64) — no install:

tar xzf tilion-fortress-linux-x64.tar.gz
./tilion-fortress/tilion --headless=new --remote-debugging-port=9222 --user-data-dir=/tmp/p
# Windows:  tilion-fortress\tilion.cmd --headless=new --remote-debugging-port=9222 --user-data-dir=C:\tmp\p

2. Connect over CDP (:9222) — keep your existing automation code

Playwright (Python):

from playwright.sync_api import sync_playwright
with sync_playwright() as p:
    browser = p.chromium.connect_over_cdp("http://localhost:9222")   # Fortress under the hood
    page = browser.new_page()
    page.goto("https://bot.sannysoft.com")
    page.screenshot(path="all-green.png")

Playwright (Node):

import { chromium } from "playwright";
const browser = await chromium.connectOverCDP("http://localhost:9222");
const page = await browser.newPage();
await page.goto("https://browserscan.net");

Puppeteer (Node):

import puppeteer from "puppeteer-core";
const browser = await puppeteer.connect({ browserURL: "http://localhost:9222" });
const page = await browser.newPage();

Agent frameworks — just point them at the endpoint:

  • browser-use: cdp_url="http://localhost:9222"
  • Crawl4AI: set the CDP endpoint to http://localhost:9222
  • Stagehand: connectOverCDP("http://localhost:9222")
  • LangChain Playwright toolkit: connect the Playwright browser over CDP as above

3. Persona (optional) — override any fingerprint surface

The default is a coherent Windows persona. Override with --uxr-* launch flags, or the SDK persona= arg:

--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-canvas-seed  --uxr-audio-seed  --uxr-timezone  --uxr-languages
--uxr-screen-width  --uxr-screen-height  --uxr-webrtc-policy=disable_non_proxied_udp

Env vars: TILION_NO_DEFAULTS=1 (bare launch, no persona), TILION_TZ, TILION_LANG.

Python SDK example:

f = Fortress(persona={
    "timezone": "America/New_York",
    "hw_concurrency": 16,
    "webgl_renderer": "ANGLE (NVIDIA, NVIDIA GeForce RTX 3060 Direct3D11 vs_5_0 ps_5_0, D3D11)",
})

Docker: append the same flags after the image name, e.g. docker run -d --rm -p 9222:9222 tilion/fortress:latest --uxr-timezone=America/New_York --uxr-hw-concurrency=16


Rules an agent MUST follow

  1. Drive it over raw CDP (connect to http://localhost:9222). Do NOT spawn chromedriver.
  2. Never pass --user-agent. It desyncs the UA string from UA Client Hints — a detectable tell. Use --uxr-ua-* instead.
  3. Do NOT add puppeteer-stealth, undetected-chromedriver, or JS fingerprint patches. They self-reveal (via toString / realm re-acquisition) and undo Fortress. The spoof is already native C++.
  4. Blocked ≠ fingerprint. ~90% of the time it's the IP (a datacenter range flagged before any page script runs). Route egress through a residential or mobile proxy, then retry. If it clears, the fingerprint was fine.
  5. Match the persona to your egress. A Windows persona over a Linux/again mismatched host is fine for JS surfaces, but keep timezone/locale coherent with the proxy geo.
  6. Verify with tools/gauntlet.py (CreepJS / Sannysoft / BrowserScan) before trusting a production run.

Verify authenticity

Every release ships a SHA256SUMS; the pip/npm SDKs verify downloads automatically. Official sources only — anything else is not us:

Full docs, patches, and the reproducible build: https://github.com/tiliondev/fortress