Browser DRM & EME Capability Checker
Tests if your browser allows Encrypted Media Extensions (`navigator.requestMediaKeySystemAccess`) and hardware security levels.
Google Widevine
Chrome, Firefox, Edge, Opera, AndroidCommonly used across Chromium-based browsers, Android devices, and Smart TVs.
Microsoft PlayReady
Microsoft Edge, Windows, XboxDeeply integrated with Windows OS and Microsoft Edge for hardware-accelerated playback.
Apple FairPlay
Safari, macOS, iOS, iPadOSApple's proprietary DRM system for HTTP Live Streaming (HLS) inside Safari and iOS apps.
What Are Protected Content Identifiers?
Understanding Encrypted Media Extensions (EME), CDM, and browser privacy controls.
Encrypted Media Extensions (EME)
EME is a W3C standard JavaScript API that enables web applications to interact with Content Decryption Modules (CDMs) to play encrypted audio and video without requiring third-party plugins like Flash or Silverlight.
Protected Content Identifiers
A unique cryptographic identifier or token generated by the device's hardware/CDM. DRM license servers use this identifier to verify device authenticity, check HDCP compliance, and enforce digital license rights.
Privacy & User Consent
Because identifiers can uniquely distinguish hardware, modern browsers give users granular toggles to enable or disable "Protected Content Identifiers". When disabled, premium DRM playback (e.g., Netflix, Spotify) will fail.
How Users Enable Protected Identifiers in Browsers
If your users encounter playback errors, guide them to toggle this setting based on their browser:
- Open
chrome://settings/content/protectedContent - Select "Sites can play protected content".
- Ensure "Sites can use identifiers to recognize your device" is enabled for HD streaming.
- Open
edge://settings/content/protectedContent - Enable "Allow sites to play protected content".
- Turn on "Allow identifiers for protected content".
- Go to Settings → General.
- Scroll to Digital Rights Management (DRM) Content.
- Check the box for "Play DRM-controlled content" (Installs Google Widevine CDM).
- Safari natively enables FairPlay DRM via macOS/iOS security system.
- Ensure standard video playback permissions are granted under Preferences → Websites.
Developer Implementation Architecture
How to host encrypted video streams on your website step-by-step.
DRM Architecture & Key Exchange Flow
encrypted event.
Media Preparation (Encryption & Packaging)
Before serving content, encrypt your source video using Common Encryption (CENC) for Widevine/PlayReady (MPEG-DASH) or Sample AES for FairPlay (HLS).
# Example: Encrypting video stream with Shaka Packager for Widevine & PlayReady packager \ input=input_video.mp4,stream=video,output=encrypted_video.mp4 \ input=input_audio.mp4,stream=audio,output=encrypted_audio.mp4 \ --enable_raw_key_encryption \ --keys label=0:key_id=14060879435b52a1b942000000000000:key=1a2b3c4d5e6f7a8b9c0d1e2f3a4b5c6d \ --protection_scheme cenc \ --mpd_output stream.mpd
Client Web Integration (Shaka Player / Video.js)
The easiest way to integrate EME & Protected Identifiers into your web app is using open-source players like Shaka Player or Video.js that encapsulate the complex low-level MediaKeys API calls.
<!-- HTML Video Element -->
<video id="video" width="100%" controls autoplay></video>
<!-- Shaka Player Library -->
<script src="https://cdnjs.cloudflare.com/ajax/libs/shaka-player/4.3.5/shaka-player.compiled.js"></script>
<script>
async function initApp() {
// Install polyfills
shaka.polyfill.installAll();
if (!shaka.Player.isBrowserSupported()) {
console.error('Browser does not support EME or HTML5 video!');
return;
}
const video = document.getElementById('video');
const player = new shaka.Player(video);
// Configure DRM License Servers & Protected Identifier Requirements
player.configure({
drm: {
servers: {
'com.widevine.alpha': 'https://widevine-license.your-domain.com/proxy',
'com.microsoft.playready': 'https://playready-license.your-domain.com/proxy',
'com.apple.fps.1_0': 'https://fairplay-license.your-domain.com/proxy'
},
advanced: {
'com.widevine.alpha': {
'persistentStateRequired': true, // Request Protected Content Identifiers
'distinctiveIdentifierRequired': false
}
}
}
});
try {
// Load manifest (MPEG-DASH or HLS)
await player.load('https://your-cdn.com/streams/protected_manifest.mpd');
console.log('Encrypted stream loaded successfully!');
} catch (e) {
console.error('Playback Error (DRM / Permission denied):', e);
}
}
document.addEventListener('DOMContentLoaded', initApp);
</script>
Low-Level JS API (`navigator.requestMediaKeySystemAccess`)
If you are building a custom player framework, here is how to request key system access directly using modern Web APIs:
// Custom Request for Protected Content Identifier Capabilities
const config = [{
initDataTypes: ['cenc'],
audioCapabilities: [{
contentType: 'audio/mp4; codecs="mp4a.40.2"'
}],
videoCapabilities: [{
contentType: 'video/mp4; codecs="avc1.4d401f"',
robustness: 'SW_SECURE_CRYPTO' // or 'HW_SECURE_ALL' for hardware DRM
}],
distinctiveIdentifier: 'optional', // 'required' demands Protected Content Identifiers
persistentState: 'optional'
}];
navigator.requestMediaKeySystemAccess('com.widevine.alpha', config)
.then(function(keySystemAccess) {
return keySystemAccess.createMediaKeys();
})
.then(function(createdMediaKeys) {
console.log('MediaKeys created successfully!', createdMediaKeys);
// Attach keys to HTMLMediaElement: video.setMediaKeys(createdMediaKeys);
})
.catch(function(error) {
console.error('Key System Access denied or not supported:', error);
});