Skip to main content

Device fingerprint methodology.

A device fingerprint is the full set of measurable signals a website can read from a browser session. Driftstack's product claim — that a website reading these signals sees iPhone Safari — is only meaningful if every one of those signals matches what the reference phone sends. This page documents what we measure, how, and against which reference.

The table below shows the full set of checks run against iPhone 16 Pro · iOS 18.7 · Safari 26.4 as a worked example. The five areas it covers — canvas drawing, fonts, screen size, viewport height and browser configuration — are what a device profile marked ✓ Verified in the app has passed, either checked directly or matched to a directly checked profile that renders the same way. 16 device profiles are selectable in the product, across iPhone 13 → 15 Plus, on iOS 18.7, Safari 26.4–26.6.1. (A device profile is one specific iPhone model + iOS version + Safari version combination — see the glossary.) If any signal differs from what the reference phone sends, we treat it as a bug that blocks release and fix the underlying browser — we never patch over it.

Any single signal is easy. Every signal at once is the hard part.

A stealth Chromium tool can change the user-agent string in five minutes. It can change the screen size in another five. But the deeper measurements — how the browser draws an invisible test image (the canvas hash), which graphics engine it reports (the WebGL renderer), how its audio system rounds numbers (the AudioContext fingerprint), how its fonts measure on screen (its font metrics), even the timing rhythm of its JavaScript engine — still come from the underlying Chromium engine in the next layer of measurement.

Websites read these signals together, and they have to agree. A browser that introduces itself as an iPhone (its user-agent, "UA") while its drawing output comes from Chrome's engine (the canvas hash says Chrome) gives two different answers about itself. Driftstack's claim isn't "we got the user-agent right." It's "every signal we check, at the same time, returns the iPhone value."

Signal-by-signal table.

Each row is a signal a website can read. The "Driftstack" column is what a session on the iPhone 16 Pro device profile returns; the "Stealth Chromium" column is what a representative Chromium-with-stealth-plugin tool returns. Cells marked unique-per-session are where the two differ most: the answers a real iPhone gives stay fixed where they are fixed and vary in a known way where Safari deliberately varies them, while those tools return a hash no real iPhone shares.

Signal Stealth Chromium Driftstack (iPhone 16 Pro · iOS 18.7)
Browser identity string (navigator.userAgent) spoofed string iPhone Safari UA (unmodified)
Operating system (navigator.platform) spoofed "iPhone"
Canvas drawing fingerprint (Canvas 2D hash) unique-per-session same as a real iPhone (Apple's own drawing code)
Graphics engine name (WebGL renderer) "ANGLE / SwiftShader" "Apple GPU"
Graphics fingerprint (WebGL hash) unique-per-session stable, like a real iPhone
Audio fingerprint (AudioContext) Chrome's audio engine iOS audio engine
Font measurements (font metrics) Linux / desktop fonts iOS text rendering
JavaScript engine timing Chrome's JavaScript engine (V8) Safari's JavaScript engine (JavaScriptCore)
Encrypted-connection handshake (TLS ClientHello) Chrome / Edge profile iOS Safari profile
Touch support (touch-event flag) absent or spoofed native
Screen size and pixel density (DPR) configurable 402x874 @ 3x (iPhone 16 Pro)
Hover support (CSS @media hover) "hover" "none" (touch device)
Idle-callback API presence (requestIdleCallback) present (Chromium) absent (Safari)
Same fingerprint, session after session? Hash uniqueness across sessions 100% unique stable, like a real iPhone

14 signals shown above: the ones websites read most often to identify a browser and the device it presents.

Drift on a verified device is a launch-blocking bug.

On a device profile marked ✓ Verified in the app, any signal that differs from what the reference returns is treated as a launch-blocking bug. On one marked Measured — its identity measured on a real iPhone, its drawing not yet proven identical — a difference is a known gap we track until it is closed. We don't paper over individual signals with JavaScript patches ("shims") layered on top — that's the approach every stealth-plugin tool takes, and it's exactly what these checks catch.

When Apple ships a new iOS or Safari version, our reference moves and we have to catch up. Until we fully match the new version, we keep offering the previous version's device profiles — a phone Apple really shipped — rather than a half-finished blend of old and new.