What the device list reveals
Even without permission, enumerateDevices() returns one object per device with its kind (audioinput, audiooutput, videoinput) and a non-empty deviceId/groupId; the label stays blank until the user grants camera or microphone access. So a site learns how many devices of each type exist and how they are grouped, which is enough to characterise the machine class. A typical laptop reports at least one microphone, one camera, and one or more audio outputs; a desktop without a webcam reports microphone and output but no video input.
The numbers cluster by device type and are stable per machine, making them a low-entropy but coherent signal that has to agree with the rest of the fingerprint.
The headless tell
Headless browsers on servers usually have no real media hardware, so enumerateDevices() returns an empty array or a single placeholder. On a request claiming to be a normal desktop or laptop, zero devices - particularly zero audiooutput - is anomalous, because real consumer machines almost always have at least a default audio output. macOS in particular always exposes audio output devices, so a "MacBook" with none is incoherent.
Chrome flags like --use-fake-device-for-media-stream add synthetic devices, but the fake devices have recognisable default labels and group structure that differ from real hardware. As with audio and WebGL, the believable fix is a device list copied from a real machine of the claimed class, served consistently per session, rather than a generic fake.
