MIME Type and Codec Fingerprinting: How Media Support Tracks You
Browser media codec support varies by platform and configuration. Learn how canPlayType() and MediaCapabilities create fingerprints.
Introduction
Every browser supports a different set of media codecs, and these differences create a reliable fingerprint. The canPlayType() method, MediaCapabilities API, and Encrypted Media Extensions (EME) all expose codec support information that varies by operating system, browser version, and hardware capabilities.
How Codec Fingerprinting Works
canPlayType()
The HTMLMediaElement's canPlayType() method tests codec support:
const video = document.createElement('video');
// Returns "probably", "maybe", or ""
video.canPlayType('video/mp4; codecs="avc1.42E01E"'); // H.264
video.canPlayType('video/webm; codecs="vp9"'); // VP9
video.canPlayType('audio/ogg; codecs="opus"'); // Opus
video.canPlayType('video/mp4; codecs="av01.0.01M.08"'); // AV1
video.canPlayType('video/mp4; codecs="hev1.1.6.L93.B0"'); // H.265/HEVC
Platform Differences
Codec support varies significantly:
| Codec | Windows | macOS | Linux |
|---|---|---|---|
| H.264 (AVC) | Probably | Probably | Probably |
| H.265 (HEVC) | Probably* | Probably | Maybe/No |
| VP8 | Probably | Probably | Probably |
| VP9 | Probably | Probably | Probably |
| AV1 | Probably** | Maybe | Probably** |
| AAC | Probably | Probably | Maybe |
| Opus | Probably | Probably | Probably |
*Windows HEVC support depends on the HEVC Video Extension **AV1 hardware decode depends on GPU generation
MediaCapabilities API
The MediaCapabilities API provides more detailed information:
const result = await navigator.mediaCapabilities.decodingInfo({
type: 'file',
video: {
contentType: 'video/mp4; codecs="avc1.42E01E"',
width: 1920,
height: 1080,
bitrate: 5000000,
framerate: 30,
},
});
console.log({
supported: result.supported, // true/false
smooth: result.smooth, // true/false
powerEfficient: result.powerEfficient, // true/false (hardware decode)
});
The powerEfficient flag reveals whether hardware decoding is available, which depends on the GPU and its driver.
EME (Encrypted Media Extensions)
DRM capability queries expose additional information:
const config = [{
initDataTypes: ['cenc'],
videoCapabilities: [{
contentType: 'video/mp4; codecs="avc1.42E01E"',
robustness: 'SW_SECURE_DECODE',
}],
}];
const access = await navigator.requestMediaKeySystemAccess(
'com.widevine.alpha', config
);
// Success or failure reveals Widevine support and robustness level
Cross-API Consistency
Detection systems check that codec responses are consistent across APIs:
- If
canPlayType()returns "probably" for a codec,MediaCapabilities.decodingInfo()should returnsupported: true - EME key system support should align with general codec support
- Hardware decode availability should match the claimed GPU
Inconsistencies between these APIs indicate spoofing.
How BotCloud Handles Codec Fingerprinting
BotCloud profiles ensure media codec responses are:
- Platform-appropriate - HEVC support on Windows, AAC on all platforms
- Internally consistent - canPlayType, MediaCapabilities, and EME all agree
- Hardware-aligned - Hardware decode flags match the profile's GPU
- Version-consistent - New codecs like AV1 appear in appropriate browser versions
Best Practices
- Do not block media APIs - Missing codec support is itself a signal
- Ensure cross-API consistency - canPlayType and MediaCapabilities must agree
- Match codec support to platform - HEVC on Windows, standard codecs on Linux
- Consider hardware decode flags - They should match the claimed GPU capabilities