What Is Media Device Fingerprinting? β Definition and How It Works
Learn how enumerateDevices reveals cameras, microphones, and speakers, and why an empty list betrays a server.
Media device fingerprinting reads the inventory of audio and video hardware a browser can see, and uses its composition as an identifying and automation-detecting signal.
1. The API
const devices = await navigator.mediaDevices.enumerateDevices();
// each: {deviceId, kind, label, groupId}
// kind: "audioinput" | "audiooutput" | "videoinput"
Without permission granted, label is empty and deviceId is masked β but the number and kinds of devices are still visible. That residual information is the fingerprinting signal.
2. Why an Empty List Is Revealing
A typical consumer machine returns several entries: at least one audio output, usually a microphone, frequently a camera.
A server or container has none. So:
(await navigator.mediaDevices.enumerateDevices()).length === 0
An empty inventory on a session claiming to be a desktop or mobile browser is a strong signal, and it is one of the cheapest checks available. It is also among the most commonly overlooked in stealth configurations, which patch navigator properties and leave this untouched.
3. The Counts Carry Entropy
Beyond presence, the composition varies meaningfully across real devices:
| Profile | Typical inventory |
|---|---|
| Laptop | 1 camera, 1β2 microphones, 1β2 outputs |
| Desktop with headset | 1β2 microphones, 2β3 outputs, often no camera |
| Phone | 2 cameras, 1β2 microphones, 1β2 outputs |
| Server / container | Nothing |
| VM with virtual audio | 1 output, no inputs |
A phone profile reporting one camera is mildly inconsistent; a phone profile reporting none is strongly so.
4. Labels After Permission
Once camera or microphone permission is granted, label becomes populated with human-readable device names β which are high-entropy, naming specific hardware models.
The practical consequence: do not grant media permissions in automation unless the task genuinely requires them. Granting turns a coarse signal into a precise one, and there is rarely any benefit.
5. Group Identifiers
groupId links devices belonging to the same physical unit β a headset's microphone and output share a group. The grouping structure is itself a signal, because a coherent inventory has plausible groupings while a fabricated one often does not.
That makes naive spoofing harder than it appears: inventing three devices with unrelated group identifiers describes a machine with three separate single-function peripherals, which is unusual.
6. Mitigations and Their Costs
Provide virtual devices. Chromium can be launched with fake media devices, which populates the inventory. It is the closest thing to a clean fix.
Grant no permissions, keeping labels masked and entropy low.
Run on hardware that has devices β a real workstation rather than a container β which is the honest version.
Do not fabricate the list in JavaScript. Overriding enumerateDevices is a patched-function signature, detectable by the hook-detection techniques that check whether native methods have been replaced.
7. Where It Fits in Priority
Media device inventory is a supporting signal rather than a decisive one. Address reputation, TLS fingerprint, and rendering characteristics matter far more.
Its value to a defender is as a corroborating check: a session that already looks slightly automated, and also has no audio hardware at all, is easier to classify confidently. Its value to you is that it is cheap to fix with a launch flag.
8. Summary
Media device fingerprinting reads the number and kinds of cameras, microphones, and speakers a browser can see, with human-readable labels appearing only after permission is granted.
An entirely empty inventory is the characteristic server-or-container tell and is frequently missed by stealth setups β so populate it with virtual devices at launch rather than patching enumerateDevices, and never grant media permissions unnecessarily, since that upgrades a coarse signal into precise hardware names.