ytdl-org/youtube-dl · error · ExtractorError

Video %s is DRM protected

Error message

Video %s is DRM protected

What it means

Raised by TVNowIE (old api.tvnow.de path) when no formats could be extracted from any of the mpd/hss/hls manifest URLs and the API metadata flags info['isDrm']. It means the episode is delivered only with DRM (Widevine/PlayReady) and youtube-dl cannot process it. Expected error: presented to the user as content unavailability.

Source

Thrown at youtube_dl/extractor/tvnow.py:71

                if hd_url != urls[0]:
                    urls.append(hd_url)
                return urls

            for man_url in make_urls('dash', '.mpd'):
                formats = self._extract_mpd_formats(
                    man_url, video_id, mpd_id='dash', fatal=False)
            for man_url in make_urls('hss', 'Manifest'):
                formats.extend(self._extract_ism_formats(
                    man_url, video_id, ism_id='mss', fatal=False))
            for man_url in make_urls('hls', '.m3u8'):
                formats.extend(self._extract_m3u8_formats(
                    man_url, video_id, 'mp4', 'm3u8_native', m3u8_id='hls',
                    fatal=False))
            if formats:
                break
        else:
            if info.get('isDrm'):
                raise ExtractorError(
                    'Video %s is DRM protected' % video_id, expected=True)
            if info.get('geoblocked'):
                raise self.raise_geo_restricted()
            if not info.get('free', True):
                raise ExtractorError(
                    'Video %s is not available for free' % video_id, expected=True)
        self._sort_formats(formats)

        description = info.get('articleLong') or info.get('articleShort')
        timestamp = parse_iso8601(info.get('broadcastStartDate'), ' ')
        duration = parse_duration(info.get('duration'))

        f = info.get('format', {})

        thumbnails = [{
            'url': 'https://aistvnow-a.akamaihd.net/tvnow/movie/%s' % video_id,
        }]
        thumbnail = f.get('defaultImage169Format') or f.get('defaultImage169Logo')

View on GitHub (pinned to 956b8c5855)

Solutions

  1. Confirm the episode plays in a browser without a paid TVNOW subscription; DRM flagged items cannot be downloaded.
  2. If you have a TVNOW subscription, try --cookies exported from the logged-in browser (only works where DRM is not applied).
  3. Try the URL of a free/preview episode of the same show.
  4. Switch to a maintained fork (yt-dlp) whose TVNowIE uses the new apigw.tvnow.de backend.
Defensive patterns

Strategy: try-catch

Type guard

def tvnow_is_drm(info: dict) -> bool:
    return bool(info.get('isDrm'))

Try / catch

try:
    ydl.extract_info(tvnow_url)
except ExtractorError as e:
    if 'DRM protected' in str(e):
        report_skip('drm', url)
    else:
        raise

Prevention

When it happens

Trigger: Extracting a tvnow.de/.at/.ch episode where all _extract_mpd_formats/_extract_ism_formats/_extract_m3u8_formats calls return nothing (all fatal=False) and info.get('isDrm') is truthy.

Common situations: Premium RTL/TVM Now content (US series, movies) sold with studio DRM, previews whose manifests require a license server, new-style URLs that the old-API loophole no longer covers.

Related errors


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