Protected Content Identifiers EME / DRM

Web Encrypted Media Extensions Interactive Toolkit & Developer Guide

Live API Test

Browser DRM & EME Capability Checker

Tests if your browser allows Encrypted Media Extensions (`navigator.requestMediaKeySystemAccess`) and hardware security levels.

Encrypted Media Extensions (EME) Support
Detecting browser navigator capability...
Checking...

Google Widevine

Chrome, Firefox, Edge, Opera, Android
Testing

Commonly used across Chromium-based browsers, Android devices, and Smart TVs.

Key System: com.widevine.alpha
Persistent State: -
Robustness: -
Querying system...

Microsoft PlayReady

Microsoft Edge, Windows, Xbox
Testing

Deeply integrated with Windows OS and Microsoft Edge for hardware-accelerated playback.

Key System: com.microsoft.playready
Persistent State: -
Hardware Security: -
Querying system...

Apple FairPlay

Safari, macOS, iOS, iPadOS
Testing

Apple's proprietary DRM system for HTTP Live Streaming (HLS) inside Safari and iOS apps.

Key System: com.apple.fps.1_0
Format: HLS / FairPlay Streaming
Safari Only: -
Querying system...

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:

Google Chrome & Brave
  1. Open chrome://settings/content/protectedContent
  2. Select "Sites can play protected content".
  3. Ensure "Sites can use identifiers to recognize your device" is enabled for HD streaming.
Microsoft Edge
  1. Open edge://settings/content/protectedContent
  2. Enable "Allow sites to play protected content".
  3. Turn on "Allow identifiers for protected content".
Mozilla Firefox
  1. Go to Settings → General.
  2. Scroll to Digital Rights Management (DRM) Content.
  3. Check the box for "Play DRM-controlled content" (Installs Google Widevine CDM).
Apple Safari (macOS / iOS)
  1. Safari natively enables FairPlay DRM via macOS/iOS security system.
  2. 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

1
Encrypted Stream Media encoded with CENC / AES-128 via DASH or HLS.
2
EME Initialization Browser reads initialization data from media header & fires encrypted event.
3
License Request CDM generates license challenge containing Protected Identifier token.
4
Key Decryption License Server responds with decryption keys to CDM for secure playback.
1

Media Preparation (Encryption & Packaging)

Shaka Packager / FFmpeg

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
2

Client Web Integration (Shaka Player / Video.js)

JavaScript / HTML5

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>
3

Low-Level JS API (`navigator.requestMediaKeySystemAccess`)

Vanilla JavaScript

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);
  });