ytdl-org/youtube-dl · error · ExtractorError
This video is DRM protected.
Error message
This video is DRM protected.
What it means
Raised by YoutubeIE._real_extract when the streaming_data contains no usable formats and includes 'licenseInfos', meaning YouTube served DRM-licensed streams only. Expected=True: the video is published with DRM protection that youtube-dl cannot and will not circumvent. It is distinct from report_drm, which fires when formats exist but all carry has_drm.
Source
Thrown at youtube_dl/extractor/youtube.py:2783
for f in self._extract_mpd_formats(
dash_manifest_url, video_id, fatal=False):
if process_manifest_format(
f, 'dash', None, f['format_id']):
f['filesize'] = traverse_obj(f, (
('fragment_base_url', 'url'), T(lambda u: self._search_regex(
r'/clen/(\d+)', u, 'file size', default=None)),
T(int_or_none)), get_all=False)
formats.append(f)
playable_formats = [f for f in formats if not f.get('has_drm')]
if formats:
if not playable_formats:
# If there are no formats that definitely don't have DRM, all have DRM
self.report_drm(video_id)
formats[:] = playable_formats
else:
if streaming_data.get('licenseInfos'):
raise ExtractorError(
'This video is DRM protected.', expected=True)
pemr = try_get(
playability_status,
lambda x: x['errorScreen']['playerErrorMessageRenderer'],
dict) or {}
reason = get_text(pemr.get('reason')) or playability_status.get('reason') or ''
subreason = pemr.get('subreason')
if subreason:
subreason = clean_html(get_text(subreason))
if subreason.startswith('The uploader has not made this video available in your country'):
countries = microformat.get('availableCountries')
if not countries:
regions_allowed = search_meta('regionsAllowed')
countries = regions_allowed.split(',') if regions_allowed else None
self.raise_geo_restricted(
subreason, countries)
reason += '\n' + subreason
View on GitHub (pinned to 956b8c5855)
Solutions
- Accept that DRM content is out of scope — no youtube-dl option will decrypt it.
- If you believe the video should be DRM-free, verify in a browser and check whether a non-DRM format appears when authenticated; otherwise use another source.
- For batch jobs, catch this expected error and skip such entries.
- Ensure you are not hitting this due to a partial player response (try with cookies); a normal video with licenseInfos absent would instead surface a playability reason.
Defensive patterns
Strategy: try-catch
Validate before calling
def is_drm_response(player_response: dict) -> bool:
streaming_data = player_response.get('streamingData') or {}
return bool(streaming_data.get('licenseInfos')) Try / catch
try:
info = ydl.extract_info(url)
except ExtractorError as e:
if 'DRM protected' in str(e):
skip_permanently(url) # not retryable; no workaround exists
raise Prevention
- Exclude paid movies/TV and DRM-flagged content from download queues at source.
- Do not retry — DRM availability will not change without a license youtube-dl will never use.
When it happens
Trigger: Extracting a video whose player response has empty/no streaming formats but streaming_data['licenseInfos'] is non-empty — e.g. movies/TV purchases, DRM-protected channel content (often also requiring purchase).
Common situations: Paid rentals/purchases on YouTube Movies; labels/publishers delivering DRM-protected streams; users expecting youtube-dl to bypass DRM (it does not).
Related errors
- This video is DRM protected.
- This video is DRM protected.
- DRM protected
- This video is DRM protected.
- This video is DRM protected.
AI-assisted analysis of ytdl-org/youtube-dl@956b8c5855 (2026-08-14).
Data as JSON: /api/errors/6e1218f71ddfd010.
Report an issue: GitHub.