Trust center · Device fingerprint
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.
Why it's hard
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."
Measured signals
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.
When something doesn't match
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.
Related