Client Signals
Detailed reference for all 29 client-side signals collected by the FingerprintIQ SDK.
The FingerprintIQ SDK collects signals across five categories, running all collectors in parallel to minimize latency. Each signal is wrapped in a SignalResult containing the value and collection duration in milliseconds.
Signals derived from how the browser renders graphics and text. These are highly device-specific because they depend on GPU drivers, font renderers, and anti-aliasing implementations.
Canvas — Renders a complex scene (gradients, text, shapes, emoji) on a 2D canvas and hashes the pixel output. Different GPU drivers, font renderers, and anti-aliasing engines produce unique results.
- Entropy: High | Stability: Medium
- Renders 3x and checks consistency to detect Brave's canvas farbling
- Skipped on Safari 17+ and Firefox 120+ which inject rendering noise
WebGL — Queries GPU hardware information via WEBGL_debug_renderer_info:
- Unmasked renderer string (full GPU model)
- Unmasked vendor
- 5 GL parameters (MAX_TEXTURE_SIZE, etc.)
- GPU timing via fragment shader benchmark
- Software renderer detection (SwiftShader, LLVMpipe, Mesa)
- Entropy: Very High | Stability: Very High
WebGPU — Queries the WebGPU adapter for architecture, description, device, and vendor strings. Available in Chrome 113+ and Edge 113+.
- Entropy: High | Stability: Very High
Audio — Renders audio through an OfflineAudioContext with oscillator and compressor pipeline. Hashes the first 100 float samples from the rendered buffer. Different audio stacks produce unique waveforms.
- Entropy: High | Stability: Medium
SVG Text — Creates SVG text elements with emoji content and measures via getBBox(), getComputedTextLength(), and getSubStringLength(). Independent from Canvas rendering, different font shaping engines produce different measurements.
- Entropy: Medium | Stability: High
DOMRect — Measures getBoundingClientRect() precision and emoji rendering dimensions. Sub-pixel differences reveal browser engine version and font rendering settings.
- Entropy: Medium | Stability: High
Signals derived from device hardware characteristics. These are among the most stable signals — hardware rarely changes.
Navigator — System properties that identify the device:
hardwareConcurrency(CPU core count)deviceMemory(RAM in GB, Chrome only)maxTouchPoints(0 for non-touch devices)platform,languages,cookieEnabled- Keyboard layout, connection type
- Device capabilities: Bluetooth, USB, HID, Serial
- Entropy: Medium | Stability: Very High
Screen — Display characteristics:
- Resolution (width × height)
- Available area (minus taskbar/dock)
- Color depth and pixel ratio
- Firefox RFP rounding detection
- Entropy: Medium | Stability: Very High
Platform Features — Tests 15+ APIs to estimate the platform:
- BarcodeDetector, ContactsManager (Android-specific)
- HID, Serial, USB (desktop-only)
- SharedWorker, PointerEvent, TouchEvent
- Cross-validates against claimed platform string
- Entropy: High | Stability: Very High
WASM Timing — Executes a minimal WebAssembly module and measures execution time over 10 iterations. The median and standard deviation create a CPU microarchitecture fingerprint that differs between Intel, AMD, and Apple Silicon.
- Entropy: Medium | Stability: Medium
Signals derived from JavaScript and CSS engine behavior. These reveal the exact browser version and engine used.
Math Precision — JavaScript engines (V8, SpiderMonkey, JavaScriptCore) compute Math.sin, Math.tan, Math.log with subtly different floating-point precision. The hash of computed values reliably identifies the engine.
- Entropy: Medium | Stability: Very High
JS Error Messages — Deliberately triggers 9 JavaScript errors and captures the exact error message text. Error wording differs between engine versions and is nearly impossible to spoof without patching the engine binary.
- Entropy: High | Stability: Very High
CSS Computed Style — Three sub-signals:
- Counts
getComputedStyleproperty count (identifies browser version precisely) - Reads 19 CSS system colors (reveals OS theme: light/dark)
- Reads 6 system fonts (reveals OS font configuration)
- Entropy: High | Stability: High
Window Features — Counts Object.getOwnPropertyNames(window) and categorizes by prefix (webkit/moz). Detects "client litter" — non-standard properties injected by browser extensions.
- Entropy: Medium | Stability: High
HTML Element Properties — Walks the prototype chain of document.documentElement collecting all property names. The full set differs between browser versions.
- Entropy: Medium | Stability: High
Signals derived from the operating system configuration. These are highly specific to the user's locale, installed software, and system settings.
Speech Synthesis — Enumerates speechSynthesis.getVoices(). The installed TTS voice list is OS and locale-specific. An en-US macOS device has completely different voices than an en-US Windows device.
- Entropy: Very High | Stability: High
Intl Locale — Tests all 7 Intl constructors (DateTimeFormat, NumberFormat, Collator, etc.) and fingerprints their formatted output. Detects locale spoofing by comparing against navigator.language.
- Entropy: High | Stability: Very High
Timezone (Deep) — Goes beyond basic UTC offset:
- Historical offset calculation across DST boundaries
- Cross-validation of reported vs computed timezone name
- Timezone spoofing detection
- Entropy: Medium | Stability: Very High
Media Codecs — Tests 12 audio/video MIME types across canPlayType(), MediaSource.isTypeSupported(), and MediaRecorder.isTypeSupported(). Codec support differs by OS, browser, and hardware.
- Entropy: High | Stability: High
Fonts — Measures text width against ~650 font families using sub-pixel precision getBoundingClientRect(). The set of installed fonts differs substantially between operating systems and user configurations.
- Entropy: High | Stability: High
Signals specifically designed to detect bots, headless browsers, privacy tools, and API tampering.
Integrity — Detects API tampering via Function.prototype.toString.call() checks on 30+ browser APIs. Computes a "lie score" from detected fake implementations. Compares main thread vs Web Worker values to catch inconsistencies.
- Entropy: Medium | Stability: High
Worker Scope Cross-Validation — Spawns a Web Worker and collects navigator and WebGL data independently. Most spoofing tools only modify the main window object — worker scope reveals true underlying values.
- Entropy: Medium | Stability: High
Headless Detection — Checks for automation markers:
- WebDriver flag (
navigator.webdriver) - Puppeteer/Playwright/Selenium signatures
- Missing or fake Chrome runtime object
- Zero plugins in a non-private session
- Headless User-Agent substrings
- Entropy: High | Stability: High
Resistance (Privacy Tools) — Detects privacy browsers (Brave, Tor Browser, Firefox RFP) and extensions (CanvasBlocker, JShelter, DuckDuckGo Privacy Essentials, Trace). Measures timer precision reduction.
- Entropy: Medium | Stability: Medium
Storage — Tests localStorage, sessionStorage, IndexedDB, and cookie availability. Storage quota is reduced in incognito mode — detects private browsing.
- Entropy: Low | Stability: High
Status — Miscellaneous device signals:
- Timer precision (reduced by Firefox RFP and some extensions)
- Max call stack size (differs by engine version and device)
- Storage quota (reduced in incognito)
- Battery API availability
- V8 heap size limit (Chrome/Edge only)
- Entropy: Medium | Stability: Medium
Web3 wallet signals (MetaMask, Phantom, Rabby, and 15+ others) are covered in the Web3 Signals reference.