Stealth Engine
Nginjen's stealth system uses a Fingerprint Consistency Engine: a single FingerprintContext generates all 21 stealth vectors so every signal matches the same fake identity.
Why Consistency Matters
Browser fingerprinting works by cross-referencing signals. If your navigator.platform says "Windows" but your WebGL renderer says "Apple GPU", the mismatch itself is a red flag. Nginjen solves this by generating a coherent profile first, then deriving all vectors from it.
21 Stealth Vectors
Navigator Layer
| # | Vector | What It Does |
|---|---|---|
| 1 | Navigator overrides | webdriver=false, platform, languages, hardware concurrency |
| 2 | navigator.vendor | Matches browser profile (Google Inc. for Chrome) |
| 3 | navigator.plugins | Realistic plugin list for the browser/OS |
| 4 | navigator.connection | RTT, downlink, effectiveType spoofing |
| 5 | navigator.permissions.query | Returns realistic permission states |
Graphics Layer
| # | Vector | What It Does |
|---|---|---|
| 6 | WebGL vendor/renderer | Matches GPU string to OS profile |
| 7 | Canvas fingerprint noise | Deterministic noise seeded by profile |
| 8 | AudioContext fingerprint | Noise injected into audio sample data |
Browser Globals
| # | Vector | What It Does |
|---|---|---|
| 9 | Chrome globals | chrome.app, chrome.runtime, chrome.csi present |
| 10 | Function.prototype.toString | Native code wrapping for all overrides |
| 11 | Notification.permission | Spoofed to default |
| 12 | Battery API | Blocked (returns null) |
| 13 | MediaDevices enumeration | Controlled device list |
Window & Screen
| # | Vector | What It Does |
|---|---|---|
| 14 | Window size consistency | outerWidth/Height matches innerWidth/Height |
| 15 | Screen resolution | Matches OS profile |
| 16 | Iframe contentWindow | Detection evasion for cross-origin frames |
Privacy & Hardening
| # | Vector | What It Does |
|---|---|---|
| 17 | WebRTC IP leak prevention | Blocks STUN requests that leak real IP |
| 18 | Timezone/locale override | Intl.DateTimeFormat matches profile timezone |
| 19 | Console protection | debug, info, table methods preserved |
| 20 | Error.stack sanitization | CDP frame references removed from stack traces |
| 21 | Property descriptor hardening | configurable: false on all overrides |
Fingerprint Profiles
Nginjen ships with built-in profiles:
| Profile | OS | Platform | Max Touch Points |
|---|---|---|---|
windows | Windows 10 | Win32 | 0 |
macos | macOS | MacIntel | 0 |
linux | Linux | Linux x86_64 | 0 |
android | Android | Linux armv8l | 5 |
ios | iOS | iPhone | 5 |
Each profile generates a coherent FingerprintContext that drives all 21 vectors.
Injection Timing
Nginjen uses pre-load injection: stealth scripts run before any page JavaScript executes. This is done via CDP's Page.addScriptToEvaluateOnNewDocument, which ensures the overrides are in place before the page's own scripts can read the original values.
Headless Modes
| Mode | How It Works | Detection Resistance |
|---|---|---|
"new" | Chrome's new headless mode | Good. Some advanced tests can still detect. |
"shell" | Chrome 131+ headless shell | Better. Strips more indicators. |
"virtual-display" | Real browser inside Xvfb | Best. Renders exactly like headed mode. |
For maximum stealth, use virtual-display mode. This requires Xvfb installed:
sudo apt install xvfbThen in your config:
[stealth]
headless_mode = "virtual-display"