cross-device-fingerprint
v0.2.0
Published
Cross-browser device fingerprinting using hardware-level signals only (WebGL, canvas, audio, fonts, CPU, screen). Works across Chrome, Firefox, Edge, and incognito mode.
Maintainers
Readme
cross-device-fingerprint
Cross-browser device fingerprinting using hardware-level signals only. Identifies the same physical device across Chrome, Firefox, Edge, Opera, and Brave — even in incognito mode.
Unlike libraries that mix browser-specific signals (userAgent, plugins, language), this library deliberately uses only signals that originate from the hardware or operating system — so different browsers on the same machine produce the same device ID.
Why this exists
| Library | Cross-browser? | Incognito? | Cost | |---------|---------------|------------|------| | FingerprintJS (OSS) | ❌ | ❌ (~60%) | Free | | FingerprintJS Pro | ❌ | ✅ (~99.5%) | Paid | | cross-device-fingerprint | ✅ (~85-95%) | ✅ (~70-95%) | Free |
How it works
The library collects signals from 8 sources and combines them into a weighted SHA-256 hash:
| Signal | Weight | Source | |--------|--------|--------| | WebGL renderer + vendor | 35% | GPU driver (hardware) | | Canvas shape rendering | 20% | GPU rasterization | | Installed fonts | 15% | Operating system | | Audio sample rate + waveform | 10% | Audio hardware | | Screen resolution + color depth | 5% | Display hardware | | CPU cores | 8% | Processor | | Pixel ratio | 2% | Display | | Timezone | 5% | OS config |
If a signal is blocked (e.g., WebGL in some modes), it's gracefully skipped and the confidence score decreases. Even with minimal signals (screen + CPU + timezone), the device ID remains consistent.
Installation
npm install cross-device-fingerprintUsage
import { computeDeviceId } from 'cross-device-fingerprint'
const result = await computeDeviceId()
console.log(result.deviceId) // "a1b2c3d4..." (64-char SHA-256 hex)
console.log(result.confidence) // 0.95 (95% confidence)
console.log(result.availableSignals) // ["webgl", "canvas", "audio", ...]
// Raw signal values for debugging
console.log(result.allSignals.webgl?.renderer) // "Intel Iris Xe Graphics"
console.log(result.allSignals.fonts) // ["Arial", "Calibri", ...]API
computeDeviceId(): Promise<DeviceResult>
Returns:
deviceId— 64-character SHA-256 hex stringconfidence— number 0.0 to 1.0 indicating reliabilityavailableSignals— which signals contributed to the hashallSignals— raw signal values for debugging
getSignals(): Promise<DeviceSignals>
Returns just the raw signals without computing the hash (faster if you only need signal inspection).
Browser support
| Browser | Fingerprint | Incognito/Private | |---------|-----------|-------------------| | Chrome | ✅ Stable | ✅ Stable | | Firefox | ✅ Stable | ⚠️ Reduced confidence (canvas noise) | | Edge | ✅ Stable | ✅ Stable | | Opera | ✅ Stable | ✅ Stable | | Brave | ✅ Stable | ⚠️ May block WebGL/Audio | | Safari | ⚠️ Limited | ❌ Limited WebGL |
License
MIT
