{"id":28118,"library":"pywidevine","title":"PyWidevine","description":"A Python implementation of the Widevine Content Decryption Module (CDM) for decrypting DRM-protected content. Version 1.9.0 supports Python 3.9–3.14. Regular releases, roughly quarterly.","status":"active","version":"1.9.0","language":"python","source_language":"en","source_url":"https://github.com/devine-dl/pywidevine","tags":["widevine","drm","cdm","content-decryption"],"install":[{"cmd":"pip install pywidevine","lang":"bash","label":"Default installation"},{"cmd":"pip install pywidevine[serve]","lang":"bash","label":"With HTTP server extras"}],"dependencies":[{"reason":"Required for protobuf serialization","package":"protobuf","optional":false},{"reason":"Required for YAML config; was missing before 1.8.0 without 'serve' extras","package":"pyyaml","optional":false},{"reason":"HTTP requests for license challenges","package":"requests","optional":false},{"reason":"Only needed for the 'serve' CLI command","package":"flask","optional":true}],"imports":[{"note":"Since 1.5.1 Cdm is exported from base package; direct import from submodule also works but is less stable.","wrong":"from pywidevine.cdm import Cdm","symbol":"Cdm","correct":"from pywidevine import Cdm"},{"note":"Direct import from submodule also works, but base package import is preferred.","wrong":"from pywidevine.pssh import PSSH","symbol":"PSSH","correct":"from pywidevine import PSSH"},{"note":"Same as above.","wrong":"from pywidevine.device import Device","symbol":"Device","correct":"from pywidevine import Device"}],"quickstart":{"code":"from pywidevine import Cdm, Device, PSSH\n\n# Load a Widevine device (WVD file)\ndevice = Device.load('path/to/device.wvd')\n\n# Create a CDM session\ncdm = Cdm()\nsession = cdm.open(device)\n\n# Set a service certificate (optional, for privacy mode)\ncert_data = b'...'  # your service certificate bytes\ncdm.set_service_certificate(session, cert_data)\n\n# Obtain a license challenge from a PSSH box\npssh = PSSH(pssh='AAAAWnBzc2gAAAAA...')\nchallenge = cdm.get_license_challenge(session, pssh)\n\n# Send the challenge to your license server, get license response\nlicense_response = b'...'  # bytes from server\ncdm.parse_license(session, license_response)\n\n# Extract content keys\nfor key in cdm.get_keys(session):\n    print(f'{key.type}: {key.kid.hex} -> {key.key.hex()}')\n\ncdm.close(session)\n","lang":"python","description":"Basic usage: load a device, open session, get license challenge, parse response, print keys."},"warnings":[{"fix":"Upgrade to Python 3.9 or newer. If you must use older Python, pin to pywidevine<1.9.0.","message":"Dropped Python 3.8 support in v1.9.0. Python 3.7 dropped in v1.8.0.","severity":"breaking","affected_versions":">=1.9.0"},{"fix":"Upgrade to v1.8.0+ or install with extras: pip install pywidevine[serve]","message":"The 'serve' extras group installs flask and yaml. Without it, yaml dependency was missing before v1.8.0, causing import errors if YAML config is used.","severity":"gotcha","affected_versions":"<1.8.0"},{"fix":"Ensure the response is passed as bytes, e.g., response.content from requests.","message":"License responses must be the raw bytes returned from the license server, not base64-encoded strings.","severity":"gotcha","affected_versions":"all"}],"env_vars":null,"last_verified":"2026-05-09T00:00:00.000Z","next_check":"2026-08-07T00:00:00.000Z","problems":[{"fix":"Upgrade to v1.8.0+ or install yaml separately: pip install pyyaml","cause":"yaml dependency was not installed unless the 'serve' extras were used. Fixed in v1.8.0.","error":"ModuleNotFoundError: No module named 'yaml'"},{"fix":"Use correct import: from pywidevine import Cdm. Or upgrade to v1.5.1+. Alternatively use: from pywidevine.cdm import Cdm","cause":"Importing incorrectly; Cdm is only available in top-level since v1.5.1. Older versions or wrong import path.","error":"AttributeError: module 'pywidevine' has no attribute 'Cdm'"},{"fix":"Ensure PSSH string is a valid base64-encoded Widevine PSSH box. Use PSSH() with raw bytes or a valid base64 string.","cause":"PSSH data is malformed or not base64 encoded correctly.","error":"pywidevine.exceptions.InvalidInitData: Failed to parse PSSH data"}],"ecosystem":"pypi","meta_description":null,"install_score":null,"install_tag":null,"quickstart_score":null,"quickstart_tag":null}