Fingerprint consistency checker¶
A real browser's fingerprint is full of cross-surface correlations: a Mac reports an Apple GPU, a desktop has no battery, a 4K Retina panel reports a DPR of 2.0. Bot detectors actively look for combinations that violate these correlations — "macOS with an NVIDIA GPU" or "a phone touchscreen on a Linux desktop" — because no real hardware ships that way.
Ghostvault ships a heuristic consistency checker that flags the most obvious impossible combinations before they ever reach the browser. It runs:
- on every
gv_create_accountcall (over the resolveddevice_config+ profile), and - over the warning strings it produces are returned to the caller.
What it checks¶
The checker is implemented as check_consistency() in
src/ghostvault/browser/device_profiles.py. It runs five independent heuristics:
1. OS ↔ GPU vendor¶
Apple Silicon GPUs only appear on macOS. NVIDIA and AMD GPUs are Windows/Linux territory.
The checker cross-references the os argument against webGl:vendor / webGl:renderer.
| OS | GPU pattern | Result |
|---|---|---|
macos |
NVIDIA | Warning: "macOS with an NVIDIA GPU is extremely rare — likely a bot tell" |
macos |
AMD / Radeon | Warning: "macOS with an AMD GPU is rare (only Mac Pro with AMD cards)" |
macos |
non-Apple vendor | Warning: "macOS usually has vendor 'Apple Inc.', got …" |
windows / linux |
Apple GPU | Warning: "{os} with an Apple GPU is impossible" |
2. Touch ↔ screen¶
A desktop OS with navigator.maxTouchPoints > 5 is suspicious unless it's a known touch
device (Surface, touchscreen monitor). We can't enumerate every touch model, so only the
obviously-wrong combo is flagged.
| OS | maxTouchPoints |
Result |
|---|---|---|
linux |
> 5 |
Warning: "Linux with > 5 touch points is unusual — most Linux desktops have no touchscreen" |
The Surface Laptop 5 profile is the only bundled profile with
maxTouchPoints > 0 (it reports 10).
3. DPR range¶
window.devicePixelRatio outside the realistic range is a strong tell.
| DPR | Result |
|---|---|
< 1.0 |
Warning: "devicePixelRatio < 1.0 is very rare" |
> 3.0 |
Warning: "devicePixelRatio > 3.0 is unusual (phones cap at ~3x)" |
4. Audio sample rate¶
AudioContext:sampleRate must be a rate real hardware actually uses.
Valid rates: 22050, 32000, 44100, 48000, 88200, 96000, 192000. Anything
else produces:
"AudioContext sampleRate {sr} is not a standard rate (44100/48000 are most common)"
5. Core count plausibility¶
navigator.hardwareConcurrency outside the 1–128 range produces:
"hardwareConcurrency {cores} is implausible (range: 1–128)"
Heuristic, not exhaustive
The checker deliberately does NOT flag battery-on-desktop, because we can't always
know the hardware from the config alone. Use a device profile
that omits battery keys for desktop hardware — the imac-24, windows-desktop-rtx,
linux-workstation, and headless-server profiles all do this correctly.
How warnings are surfaced¶
Warnings are non-fatal — they never block account creation. They appear in the
consistency_warnings field of the gv_create_account response:
{
"id": "a913fd57244a",
"name": "Bad",
"os": "macos",
"device_profile": null,
"device_config": {
"webGl:vendor": "Google Inc. (NVIDIA)",
"webGl:renderer": "ANGLE (NVIDIA, NVIDIA GeForce RTX 4070 ...)",
"window.devicePixelRatio": 4.0,
"AudioContext:sampleRate": 12345,
"navigator.hardwareConcurrency": 256
},
"consistency_warnings": [
"macOS with an NVIDIA GPU is extremely rare — likely a bot tell",
"devicePixelRatio 4.0 > 3.0 is unusual (phones cap at ~3x)",
"AudioContext sampleRate 12345 is not a standard rate (44100/48000 are most common)",
"hardwareConcurrency 256 is implausible (range: 1–128)"
]
}
When you're scripting with the SDK, the warnings come back as part of the JSON result —
parse with json.loads and inspect the list:
import json
result = await gv.create_account(
name="Bad",
os="macos",
device_config={
"webGl:vendor": "Google Inc. (NVIDIA)",
"window.devicePixelRatio": 4.0,
},
)
data = json.loads(_text(result))
if data["consistency_warnings"]:
print("Bot tells:", data["consistency_warnings"])
Treat non-empty warnings as a bug in your config
Detectors weight impossible combinations heavily. If consistency_warnings is
non-empty, the right move is almost always to fix the config — not proceed. Start
from a device profile and override only the keys you need.
Examples of impossible combos¶
| Combination | Why it's flagged |
|---|---|
os=macos + webGl:renderer="ANGLE (NVIDIA, ...)" |
No Mac ships with an NVIDIA GPU |
os=windows + webGl:vendor="Apple Inc." |
Apple GPUs are Apple-Silicon only |
os=linux + navigator.maxTouchPoints=10 |
Most Linux desktops have no touchscreen |
window.devicePixelRatio=4.0 |
Above the ~3× cap on real phone panels |
window.devicePixelRatio=0.5 |
No real display reports sub-1.0 DPR |
AudioContext:sampleRate=12345 |
Not a rate any DAC produces |
navigator.hardwareConcurrency=0 |
Below the plausible minimum |
navigator.hardwareConcurrency=256 |
Above the plausible maximum |
Related pages¶
- Device profile templates — pre-built consistent bundles
- Camoufox config schema — the keys the checker inspects
- Programmatic SDK — scripting account creation with warning checks