Phantom Shield is a fingerprinting-defense toolkit for Brave/Chromium and the terminal. It does three things that work independently: it overrides 40 browser fingerprinting surfaces that Brave's built-in farbling leaves untouched, it drives upstream TLS/JA3 impersonation through a local mitmproxy bridge, and it ships a Python package that applies the same identity model to scripted HTTP for OSINT and research. Current status: v0.7.0.

Dev / authorized-use only. Every component binds 127.0.0.1 by policy. Do not run it against systems you don't own or aren't authorized to test. It exists for privacy research, locale control, and red-teaming your own infrastructure.

What it does

Four pieces in one repository. The three core halves are decoupled — turn the bridge off and the JavaScript phantoms still run; the Python client never touches mitmproxy.

1 — Browser extension (40 phantoms)

An MV3 extension that patches fingerprinting surfaces Brave's farbling doesn't cover, across four tiers: Canvas, WebGL, AudioContext, the navigator.* and screen state, Intl/timezone, font enumeration (FontFaceSet + canvas measureText noise), navigator.userAgentData, the Permissions API, a window.chrome shim, mediaDevices.enumerateDevices, navigator.connection, plus Function.prototype.toString stealth so the overrides don't look patched. Toggling a phantom propagates to every open tab in about 50ms via a MutationObserver, with no reload.

2 — TLS / JA3 bridge

A local mitmproxy addon re-issues outbound HTTPS through curl_cffi so the wire-level fingerprint (ciphers, groups, sig-algs, ALPN, HTTP/2 SETTINGS and pseudo-header order) matches the browser you're presenting as. The browser's JA3 stops contradicting its User-Agent.

3 — Python client / phantom CLI

The same identity model for scripted HTTP — useful for OSINT collection and research. Personas bundle a TLS profile, region, rotating upstreams, DoH and rate limits; the client surfaces detector signals (Cloudflare, Akamai, PerimeterX…) when one fires.

4 — Phantom Browser launcher

A one-step wrapper that starts your installed Brave as a separate, isolated instance (its own profile, proxy, and CA trust) with the extension preloaded and a session-scoped bridge that shuts down when you close the window. Your everyday Brave is left untouched.

Why it exists

The classic detection signal is incoherence — a Chrome JA3 with a Firefox User-Agent, or a desktop screen with a mobile profile. Phantom Shield keeps every layer aligned. Typical uses:

  • Anti-bot research / red-teaming your own systems — see exactly what a coherent client sends, with TLS, UA, Client Hints, navigator and screen state all consistent.
  • Population blending — present as a common cohort (Chrome 146 on Windows, Safari on iOS) without hand-maintaining UA strings, headers, and TLS profiles in three places.
  • Privacy research — flip individual fingerprint surfaces on and off and watch a probe react.
  • Locale / timezone control — appear from another region without the lie being obvious from getTimezoneOffset() or Intl.DateTimeFormat().resolvedOptions().
  • OSINT over hostile networks — the Python client pulls public data through rotating upstreams with a real-browser TLS fingerprint, while DoH keeps queries out of ISP logs.

If you only want “a bit less trackable,” Brave's farbling plus uBlock Origin is enough. Phantom Shield is for cases where additional OPSEC is a requirement. It blends into the general web population — the opposite of Tor Browser's uniform anonymity set — so don't load the extension into Tor Browser.

Getting started

Three entry points; pick the one that matches what you want.

A. Phantom Browser launcher (easiest, isolated)

git clone http://192.168.50.24:3000/nathan/phantom-shield-v2.git
cd phantom-shield-v2
./scripts/phantom-browser.sh          # or: npm run phantom

First run provisions the bridge and trusts the mitmproxy CA only inside the isolated Phantom profile. On Windows, run scripts\phantom-browser.cmd. Close all Brave windows first (or pass --force), since Chromium hands a second launch to the existing instance.

B. Bridge installer + your everyday Brave

./scripts/install.sh            # add --no-ca to skip system-wide CA trust
./scripts/uninstall.sh --purge # remove everything, including the data dir

TLS profiles

20 preconfigured profiles, each carrying a curl_cffi-supported fingerprint id, a matching User-Agent, a Sec-CH-UA brand list, platform/mobile flags, and navigator hints.

FamilyVersions
Chrome (Windows)120, 131, 136, 142, 145, 146
Chrome (Android)99, 131
Edge (Windows)99, 101
Firefox (Windows)133, 135, 144, 147
Safari (macOS)18.0, 18.4, 26
Safari (iOS)18.4, 26
Tor Browser14.5 (Firefox 128 ESR base)

Python client

from phantom_shield import Persona, Session

alice = Persona.load("alice")
with Session(alice, auto_rotate=True) as s:
    r = s.get("https://api.example.com/...")
    if s.last_signals:            # a detector fired (Cloudflare, Akamai, ...)
        print("blocked:", [sig.detector for sig in s.last_signals])
phantom get  https://target.com/api --persona alice
phantom rotate alice                 # advance the upstream pool, keep cookies
phantom personas new bob --profile firefox147 --region de --tor --doh --rate 30
phantom profiles list                # browse the 20 TLS profiles

Security & limitations

  • The mitmproxy CA is powerful. Installed system-wide, its key can decrypt any HTTPS on the machine. The installer makes consent explicit and lets you skip it (--no-ca); the launcher scopes trust to an isolated profile. The CA is generated locally and never leaves the machine.
  • TLS impersonation needs the bridge. Without mitmproxy as Brave's proxy and the CA trusted, the bridge does nothing — the JS phantoms still work.
  • Some vectors need engine changes the extension can't make — WebGL renderer variation beyond Brave's farbling, font detection via CSS local() measurement, and side channels that don't pass through a JS API.
  • Profiles are static curl_cffi presets and lag real-browser releases by weeks to months; a site checking a newer JA3 will see a mismatch.
  • A mismatched custom User-Agent is itself a fingerprint — the override is permissive on purpose, and the options page warns when it diverges from the profile.