Overview
This document catalogs all known browser fingerprint vectors discovered through analysis of FingerprintJS (27.7k stars, 44 sources), BrowserLeaks (15+ tools), EFF Cover Your Tracks, and other research. Each vector is classified by category, spoofability at the proxy level, and entropy contribution.
Classification Legend
| Icon | Meaning |
|---|---|
| Spoofable | Fully controllable at proxy level (header modification, DNS, TLS) |
| Partial | Can be partially modified/injected via JS, but not fully controlled |
| Unspoofable | Hardware-level or occurs before proxy can intercept |
| Detectable | Spoofing attempt can be detected by fingerprinting service |
Layer 1: Network & Protocol (13 vectors)
These are the lowest-level signals, visible before any HTTP or JS.
1.1 TCP/IP Stack Fingerprint (JA4T)
What it is: Passive TCP fingerprinting reads SYN packet parameters to identify OS.
Signals:
- Initial TTL (64=Linux/macOS, 128=Windows)
- Window size (64240=Chrome/Linux, 65535=macOS)
- MSS (Maximum Segment Size)
- TCP options (MSS, SACK_PERM, TIMESTAMP, WINDOW_SCALE, NOP order)
- IP DF (Don't Fragment) flag
- ECN support
Example JA4T: 64240_2-4-8-1-3_1452_10
Verdict: Partial The container's own TCP stack replaces the client's. Obscura's TCP stack will be seen, not the client's. This is unavoidable.
1.2 TLS Fingerprint (JA3/JA4)
What it is: TLS ClientHello parameters reveal browser identity.
Signals:
- Cipher suite list (order and selection)
- TLS extensions list (order and selection)
- Supported groups (curves)
- EC point formats
- ALPN protocols
- TLS version
- SNI presence
Example JA3: 6734f37431670b3ab4292b8f60f29984 (Chrome 120 Win11)
Verdict: Spoofable via utls library (Go) or custom TLS implementation (Rust).
Note: Since Obscura terminates TLS for MITM, the outer TLS handshake to the server can be fully controlled. This is a critical vector without spoofing, the server sees Go's/Chrome's TLS stack, instantly revealing a proxy.
1.3 HTTP/2 Fingerprint (Akamai format)
What it is: HTTP/2 connection preface and SETTINGS frames vary by browser.
Signals:
- SETTINGS frame parameters (MAX_CONCURRENT_STREAMS, INITIAL_WINDOW_SIZE, MAX_FRAME_SIZE, etc.)
- SETTINGS frame order
- PING frame behavior
- WINDOW_UPDATE timing
- PRIORITY frame structure
- Magic octets (PRI * HTTP/2.0)
Verdict: Partial Spoofable if Obscura implements custom HTTP/2, but complex. If using Go's net/http, the server sees Go's HTTP/2 fingerprint.
1.4 QUIC / HTTP/3 Fingerprint
What it is: QUIC (HTTP/3) uses UDP and is encrypted end-to-end cannot be intercepted.
Signals:
- QUIC transport parameters
- Connection ID length
- Version negotiation
- TLS 1.3 handshake on QUIC
Verdict: Unspoofable QUIC bypasses the proxy entirely. Obscura must block QUIC (UDP 443) to force HTTP/1.1 or HTTP/2 over TCP.
1.5 DNS Fingerprint
What it is: DNS query patterns and resolver choice.
Signals:
- DNS resolver IP (Cloudflare 1.1.1.1 vs Google 8.8.8.8 vs ISP)
- DNS over HTTPS vs DNS over TLS vs plain DNS
- EDNS0 options
- DNS query timing patterns
- DNSSEC support
Verdict: Spoofable Obscura controls DNS resolution entirely.
1.6 WebRTC IP Leak
What it is: WebRTC can reveal the real local and public IP even behind VPN/proxy.
Mechanism:
const pc = new RTCPeerConnection({ iceServers: [{ urls: 'stun:stun.l.google.com:19302' }] })
pc.createDataChannel('')
pc.createOffer().then(offer => pc.setLocalDescription(offer))
// ICE candidates reveal local and public IPs
Verdict: Partial Can be blocked via JS injection (RTCPeerConnection override), but blocking is detectable.
1.7 IP Geolocation
What it is: IP address reveals country, city, ISP, ASN, latitude/longitude.
Verdict: Spoofable Use a VPN/Tor upstream from Obscura, or route through an exit node.
1.8 Network Information API
What it is: navigator.connection exposes network type.
navigator.connection.effectiveType // "4g", "3g", "2g", "slow-2g"
navigator.connection.downlink // Mbps estimate
navigator.connection.rtt // Round-trip time (ms)
navigator.connection.saveData // Data saver mode
Verdict: Spoofable via JS injection.
1.9 Timing Attacks (Network Latency)
What it is: Measuring resource load times reveals network characteristics.
Mechanism: Use performance.now() before/after loading resources to measure latency.
Verdict: Partial performance.now() precision can be reduced, but coarse timing still works.
1.10 Proxy/VPN Detection
What it is: Servers detect proxies via:
- HTTP headers (
Via,X-Forwarded-For,X-Real-IP) - TLS fingerprint mismatch (Chrome UA + Go TLS)
- DNS resolver inconsistency
- IP in known proxy/VPN ranges
- Timezone vs IP geolocation mismatch
Verdict: Partial Requires consistent profile across all layers.
1.11 Content Filter Detection
What it is: Detecting ad blockers, privacy tools via:
- Blocked resource patterns (EasyList detection)
- CSS selector testing
- Timing of blocked resources
- DOM element presence/absence
Verdict: Detectable If Obscura blocks domains, it can be detected by testing known tracking domains.
1.12 HTTP/HTTPS Caching Behavior
What it is: Cache timing / ETag tracking across sites.
Verdict: Partial Can clear/disable cache headers via proxy.
1.13 OCSP/CRL Behavior
What it is: Certificate revocation check patterns.
Verdict: Unspoofable Hard to control at proxy level without breaking TLS.
Layer 2: HTTP & Headers (12 vectors)
2.1 User-Agent
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 ...
Verdict: Spoofable
2.2 Client Hints (Sec-CH-UA)
Sec-CH-UA: "Google Chrome";v="120", "Chromium";v="120", "Not?A_Brand";v="99"
Sec-CH-UA-Platform: "Windows"
Sec-CH-UA-Platform-Version: "15.0.0"
Sec-CH-UA-Model: "" (desktop) / "Pixel 7" (mobile)
Sec-CH-UA-Mobile: ?0
Sec-CH-UA-Arch: "x86"
Sec-CH-UA-Bitness: "64"
Sec-CH-UA-Full-Version-List: "..."
Sec-CH-UA-WoW64: ?0
Verdict: Spoofable
2.3 Accept Headers
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,*/*;q=0.8
Accept-Language: en-US,en;q=0.9
Accept-Encoding: gzip, deflate, br
Verdict: Spoofable
2.4 Content-Type / Content-Encoding
Verdict: Spoofable
2.5 Do Not Track / Global Privacy Control
DNT: 1
Sec-GPC: 1
Verdict: Spoofable
2.6 Upgrade-Insecure-Requests
Upgrade-Insecure-Requests: 1
Verdict: Spoofable
2.7 Referer / Origin
Verdict: Partial Can strip/modify, but breaks some sites.
2.8 Cookie Behavior
Signals: cookies enabled/disabled, third-party cookie blocking, cookie expiration preferences.
Verdict: Partial Can set cookies on proxy, but browser's own cookie settings leak via JS.
2.9 Cache Headers
ETag, If-None-Match, Cache-Control, Pragma
Verdict: Spoofable at proxy.
2.10 Connection Headers
Connection, Keep-Alive, Upgrade
Verdict: Spoofable
2.11 Proxy Headers
Via, X-Forwarded-For, X-Real-IP, Forwarded
Verdict: Spoofable Strip all proxy headers.
2.12 Priority / Loading Priority
Sec-Purpose, Sec-Fetch-*, Priority
Sec-Fetch-Dest: document
Sec-Fetch-Mode: navigate
Sec-Fetch-Site: none
Sec-Fetch-User: ?1
Verdict: Spoofable
Layer 3: JavaScript / DOM APIs (44 vectors from FingerprintJS)
These are all signals collected by FingerprintJS's open-source library. Each is a .ts source file.
| # | Source File | Signal Collected | Spoofable via JS Injection |
|---|---|---|---|
| 1 | userAgentData |
navigator.userAgentData (brands, platform, mobile, architecture, bitness, model, platformVersion, wow64, fullVersionList, formFactors) |
Yes |
| 2 | fonts |
Installed system fonts (via CSS @font-face + measurement) |
Partial can limit but not fake |
| 3 | domBlockers |
Detection of ad/content blockers via test resources | Partial |
| 4 | fontPreferences |
Font rendering preferences (letter spacing, font metrics) | Partial |
| 5 | audio |
AudioContext oscillator + DynamicsCompressor output hash | Partial can inject noise |
| 6 | screenFrame |
Screen frame dimensions (availTop, availLeft) | Yes |
| 7 | canvas |
Canvas 2D rendering hash (text + shapes) | Partial noise injection |
| 8 | osCpu |
navigator.oscpu (Firefox) |
Yes |
| 9 | languages |
navigator.languages, navigator.language |
Yes |
| 10 | colorDepth |
screen.colorDepth |
Yes |
| 11 | deviceMemory |
navigator.deviceMemory |
Yes |
| 12 | screenResolution |
screen.width, screen.height |
Yes |
| 13 | hardwareConcurrency |
navigator.hardwareConcurrency |
Yes |
| 14 | timezone |
Intl.DateTimeFormat().resolvedOptions().timeZone |
Yes |
| 15 | sessionStorage |
Whether sessionStorage is available |
Yes (override) |
| 16 | localStorage |
Whether localStorage is available |
Yes (override) |
| 17 | indexedDB |
Whether indexedDB is available |
Yes (override) |
| 18 | openDatabase |
Whether window.openDatabase exists |
Yes (override) |
| 19 | cpuClass |
navigator.cpuClass (legacy IE) |
Yes |
| 20 | platform |
navigator.platform |
Yes |
| 21 | plugins |
navigator.plugins (installed plugins list) |
Partial |
| 22 | touchSupport |
navigator.maxTouchPoints, touch events support |
Yes |
| 23 | vendor |
navigator.vendor |
Yes |
| 24 | vendorFlavors |
navigator.vendorSub, navigator.productSub |
Yes |
| 25 | cookiesEnabled |
navigator.cookieEnabled |
Yes |
| 26 | colorGamut |
Color gamut support (sRGB, P3, Rec2020) via media query | Yes |
| 27 | invertedColors |
OS inverted colors setting | Yes |
| 28 | forcedColors |
OS forced colors mode | Yes |
| 29 | monochrome |
Monochrome color depth via media query | Yes |
| 30 | contrast |
Contrast preference via media query | Yes |
| 31 | reducedMotion |
prefers-reduced-motion media query |
Yes |
| 32 | reducedTransparency |
prefers-reduced-transparency media query |
Yes |
| 33 | hdr |
HDR support via window.matchMedia |
Yes |
| 34 | math |
Floating-point math fingerprint (precision differences) | Unspoofable hardware FPU behavior |
| 35 | pdfViewerEnabled |
navigator.pdfViewerEnabled |
Yes |
| 36 | architecture |
navigator.userAgentData.architecture (x86, arm) |
Yes |
| 37 | applePay |
Apple Pay availability | Yes (override) |
| 38 | privateClickMeasurement |
Private Click Measurement API support | Yes (override) |
| 39 | audioBaseLatency |
AudioContext base latency (hardware-dependent) | Unspoofable hardware audio |
| 40 | dateTimeLocale |
Intl.DateTimeFormat resolved locale |
Yes |
| 41 | webGlBasics |
WebGL renderer, vendor, version, shader precision | Partial can block debug_info |
| 42 | webGlExtensions |
List of supported WebGL extensions | Partial can block listing |
| 43 | vendor (navigator) |
navigator.vendor (e.g., "Google Inc.") |
Yes |
| 44 | mimeTypes |
navigator.mimeTypes registered MIME handlers |
Partial |
Summary of FingerprintJS vectors:
| Spoofability | Count |
|---|---|
| Fully spoofable via JS injection | 29 |
| Partially spoofable | 13 |
| Unspoofable | 2 |
Layer 4: Browser Features & Capabilities (25+ vectors)
From BrowserLeaks "Features Detection", the following are used for fingerprinting:
4.1 Web Features Support (yes/no binary vector)
Each supported/unsupported feature adds ~1 bit of entropy:
- Canvas, Canvas Text
- SVG (inline, as img, clip-path, SMIL, filters, foreignObject)
- WebGL, WebGL2
- WebGPU
- Web Audio API, Speech Recognition, Speech Synthesis
- WebRTC, MediaStream Recording
- WebSocket, WebSocket Binary
- Service Workers, Service Worker Cache
- Web Bluetooth, Web USB, Web NFC, Web Serial
- Web Authentication (WebAuthn)
- Web Cryptography API
- Web Assembly (Wasm)
- WebVR / WebXR
- Web Animations
- ResizeObserver, IntersectionObserver, MutationObserver
- Fullscreen API, Pointer Lock API, Geolocation API
- Battery API, Network Information API, Vibration API
- PushManager, Notification API, Page Visibility API
- History API, postMessage
- Web Workers, Shared Workers
- Fetch API, Beacon API, Server Sent Events
- Filesystem API, File API, Blob API
- GamePad API, Device Orientation, Device Motion
- CSS features (grid, flexbox, transforms 3D, backdrop-filter, etc.)
Total: ~100+ feature tests, but most are highly correlated (Chrome supports X, Firefox doesn't). Effective entropy: ~10-15 bits.
Verdict: Partial Can inject feature detection overrides, but very complex to maintain.
4.2 CSS Media Query Fingerprinting
What it is: Brute-forcing screen dimensions via CSS @media queries.
@media (width: 1920px) { ... }
@media (height: 1080px) { ... }
@media (device-width: 1920px) { ... }
@media (resolution: 1.5dppx) { ... }
Verdict: Partial CSS-based detection runs before JS injection.
4.3 ClientRects Fingerprinting
What it is: Element.getClientRects() returns different values for invisible elements across browsers/OS.
Verdict: Unspoofable from proxy DOM layout is browser-specific.
Layer 5: System & Hardware (15 vectors)
5.1 GPU Fingerprint
Sources:
WEBGL_debug_renderer_info.UNMASKED_RENDERER_WEBGL(exact GPU model)- WebGPU
adapterInfo(vendor, architecture, device, driver, backend) - Canvas rendering differences
- WebGL shader precision
- WebGL extension support
Entropy: Very high exact GPU model is highly identifying.
Verdict: Partial Can block UNMASKED_RENDERER_INFO and WebGPU adapter info, but rendering-based fingerprints remain.
5.2 CPU Fingerprint
Sources:
navigator.hardwareConcurrency(core count)- FPU math precision (floating-point operation differences)
performance.now()resolution- Wasm-based CPU feature detection (SIMD, AES-NI, etc.)
Verdict: Unspoofable for math precision and Wasm CPU detection.
5.3 Memory Fingerprint
Source: navigator.deviceMemory (RAM in GB, only in Chrome)
Verdict: Spoofable
5.4 Storage Fingerprint
Sources:
- LocalStorage, SessionStorage, IndexedDB, Cache API availability
- Quota storage management API
- WebSQL availability
Verdict: Spoofable
5.5 Font Fingerprinting
Sources:
- Installed system fonts (via CSS
@font-facemeasurement-based enumeration) - Font rendering metrics (letter spacing, height, width with specific fonts)
- Unicode glyph range support
Entropy: Very high font list can have >1000 fonts.
Verdict: Partial Can limit font enumeration by overriding measurement functions, but font rendering differences persist.
5.6 Screen Fingerprint
Sources:
screen.width,screen.height,availWidth,availHeight,availTop,availLeftscreen.colorDepth,screen.pixelDepthwindow.devicePixelRatiowindow.outerWidth,window.outerHeightwindow.innerWidth,window.innerHeightscreen.orientation- Multi-monitor detection via
ScreenDetailedAPI
Verdict: Spoofable via JS injection.
5.7 Input Method Fingerprint
Sources:
navigator.maxTouchPoints- Touch events support
- Pointer events support
- Keyboard layout / input method
Verdict: Spoofable for touch support. Unspoofable for keyboard layout.
5.8 Audio Hardware Fingerprint
Sources:
- AudioContext sample rate
- AudioContext base latency
- DynamicsCompressorNode output (hardware-dependent)
- Audio channel count
- Echo cancellation, noise suppression support
Verdict: Unspoofable hardware audio processing.
5.9 Battery API
Sources:
navigator.getBattery().levelnavigator.getBattery().chargingnavigator.getBattery().chargingTimenavigator.getBattery().dischargingTime
Verdict: Spoofable via JS injection.
5.10 Media Devices
Sources:
navigator.mediaDevices.enumerateDevices()- Number and type of cameras, microphones, speakers
Verdict: Spoofable via JS injection (return empty or generic device list).
Layer 6: Behavioral & Session (8 vectors)
6.1 Mouse / Touch Behavior
What it is: Mouse movement patterns, click timing, touch gestures.
Verdict: Unspoofable behavioral biometrics, no proxy control.
6.2 Keystroke Dynamics
What it is: Typing speed, key press duration, key intervals.
Verdict: Unspoofable
6.3 Scroll Behavior
What it is: Scroll speed, acceleration patterns.
Verdict: Unspoofable
6.4 Session Duration / Page Timing
What it is: Time spent on pages, navigation patterns.
Verdict: Unspoofable
6.5 Performance Timing
Signals:
performance.now()fine-grained timingperformance.timeOrigin- Navigation timing API (
performance.getEntriesByType('navigation'))
Verdict: Partial performance.now() precision can be reduced.
6.6 Multi-Window / Multi-Tab Detection
What it is: BroadcastChannel, SharedWorker, localStorage cross-tab communication.
Verdict: Partial via JS injection.
6.7 Service Worker Persistence
What it is: Detecting if a SW is registered, cache state.
Verdict: Partial can override, but SW scope is complex.
6.8 Timezone / Clock Skew
What it is: System timezone + precise clock skew from server time.
Verdict: Spoofable for timezone. Partial for clock skew.
Vector Count Summary
| Layer | Category | Count | Proxy-Spoofable | Partial | Unspoofable |
|---|---|---|---|---|---|
| 1 | Network & Protocol | 13 | 3 | 6 | 4 |
| 2 | HTTP & Headers | 12 | 11 | 1 | 0 |
| 3 | JavaScript / DOM APIs | 44 | 29 | 13 | 2 |
| 4 | Browser Features | ~100+ | 0 | ~10 | ~90+ |
| 5 | System & Hardware | 15 | 6 | 4 | 5 |
| 6 | Behavioral & Session | 8 | 1 | 4 | 3 |
| Total (unique distinct vectors) | ~60+ | ~50 | ~38 | ~100+ |
Implications for Obscura
- ~50 vectors are fully controllable at the proxy/JS injection level
- ~38 vectors can be partially mitigated but not perfectly
- ~100+ vectors are outside Obscura's control (hardware, behavioral, feature flags)
Realistic protection: A well-configured Obscura deployment can control ~55% of fingerprint surface area, but the remaining ~45% still leak information. Combined with DNS blocking of known fingerprinting domains, effective protection is meaningful but not absolute.