ytdl-org/youtube-dl · error · ExtractorError

This video is DRM protected.

Error message

This video is DRM protected.

What it means

Raised by TV2IE when the video metadata from tv2.no marks the asset as drmProtected and no playable formats could be extracted (all MPD/HLS/plain-URL extraction yielded nothing). It is an expected ExtractorError, so youtube-dl reports it as a user-facing 'video unavailable' rather than a bug. DRM content is encrypted and cannot be downloaded by youtube-dl.

Source

Thrown at youtube_dl/extractor/tv2.py:106

                    if not data.get('drmProtected'):
                        formats.extend(self._extract_m3u8_formats(
                            video_url, video_id, 'mp4',
                            'm3u8' if is_live else 'm3u8_native',
                            m3u8_id=format_id, fatal=False))
                elif ext == 'mpd':
                    formats.extend(self._extract_mpd_formats(
                        video_url, video_id, format_id, fatal=False))
                elif ext == 'ism' or video_url.endswith('.ism/Manifest'):
                    pass
                else:
                    formats.append({
                        'url': video_url,
                        'format_id': format_id,
                        'tbr': int_or_none(item.get('bitrate')),
                        'filesize': int_or_none(item.get('fileSize')),
                    })
        if not formats and data.get('drmProtected'):
            raise ExtractorError('This video is DRM protected.', expected=True)
        self._sort_formats(formats)

        thumbnails = [{
            'id': thumbnail.get('@type'),
            'url': thumbnail.get('url'),
        } for _, thumbnail in (asset.get('imageVersions') or {}).items()]

        return {
            'id': video_id,
            'url': video_url,
            'title': self._live_title(title) if is_live else title,
            'description': strip_or_none(asset.get('description')),
            'thumbnails': thumbnails,
            'timestamp': parse_iso8601(asset.get('createTime')),
            'duration': float_or_none(asset.get('accurateDuration') or asset.get('duration')),
            'view_count': int_or_none(asset.get('views')),
            'categories': asset.get('keywords', '').split(','),
            'formats': formats,

View on GitHub (pinned to 956b8c5855)

Solutions

  1. Accept that DRM-protected TV2 content cannot be downloaded with youtube-dl; use the broadcaster's official app/portal.
  2. Verify the video actually plays without entitlements in a browser on the same network/cookies; if the page itself refuses, nothing youtube-dl can do.
  3. Try a different, non-DRM episode/clip ID from the same show.
  4. Pass --cookies from an authenticated browser session if the asset requires login (only helps for non-DRM paywalls).
Defensive patterns

Strategy: try-catch

Type guard

def is_tv2_drm(data: dict) -> bool:
    return not data.get('formats') and bool(data.get('drmProtected'))

Try / catch

from youtube_dl.utils import ExtractorError
try:
    ydl.extract_info('https://www.tv2.no/video/1234567/')
except ExtractorError as e:
    if 'DRM protected' in str(e):
        log.warning('Skipping DRM item: %s', e)
    else:
        raise

Prevention

When it happens

Trigger: Requesting a tv2.no (or TV 2 Sumo) URL whose asset JSON contains data['drmProtected'] == true while every candidate video_url produced zero formats (e.g. only .ism/Manifest entries, which are skipped with 'pass').

Common situations: Premium/licensed broadcasts on TV2 Norway, Hollywood movies or live sports behind DRM licensing, region-locked assets that only expose PlayReady/Widevine manifests.

Related errors


AI-assisted analysis of ytdl-org/youtube-dl@956b8c5855 (2026-08-14). Data as JSON: /api/errors/d37c1e8b5bab9ad2. Report an issue: GitHub.