ytdl-org/youtube-dl · error · ExtractorError

This video is DRM protected.

Error message

This video is DRM protected.

What it means

Raised by ShahidIE._real_extract when the playout response for the requested asset has a truthy 'drm' flag. Shahid marks subscription/protected streams as DRM, and the extractor refuses them explicitly because the HLS URL it would fetch is unusable without a DRM license. Marked expected=True so users see a clear message instead of a download failure mid-stream.

Source

Thrown at youtube_dl/extractor/shahid.py:122

            None, 'Populate Context', data=urlencode_postdata({
                'firstName': user_data['firstName'],
                'lastName': user_data['lastName'],
                'userName': user_data['email'],
                'csg_user_name': user_data['email'],
                'subscriberId': user_data['id'],
                'sessionId': user_data['sessionId'],
            }))

    def _real_extract(self, url):
        page_type, video_id = re.match(self._VALID_URL, url).groups()
        if page_type == 'clip':
            page_type = 'episode'

        playout = self._call_api(
            'playout/new/url/' + video_id, video_id)['playout']

        if playout.get('drm'):
            raise ExtractorError('This video is DRM protected.', expected=True)

        formats = self._extract_m3u8_formats(re.sub(
            # https://docs.aws.amazon.com/mediapackage/latest/ug/manifest-filtering.html
            r'aws\.manifestfilter=[\w:;,-]+&?',
            '', playout['url']), video_id, 'mp4')
        self._sort_formats(formats)

        # video = self._call_api(
        #     'product/id', video_id, {
        #         'id': video_id,
        #         'productType': 'ASSET',
        #         'productSubType': page_type.upper()
        #     })['productModel']

        response = self._download_json(
            'http://api.shahid.net/api/v1_1/%s/%s' % (page_type, video_id),
            video_id, 'Downloading video JSON', query={
                'apiKey': 'sh@hid0nlin3',

View on GitHub (pinned to 956b8c5855)

Solutions

  1. Accept that this asset is DRM protected and cannot be downloaded with youtube-dl/yt-dlp anonymous access.
  2. Look for the same content on a non-DRM source (free Shahid episode, MBC YouTube channel, another platform supported by yt-dlp).
  3. Verify with a browser that the asset plays without a subscription; if it does, the extractor's session may lack entitlement - retry with a fresh session (clear cache).
  4. Keep the extractor updated in case Shahid changes the flag semantics.
Defensive patterns

Strategy: validation

Validate before calling

playout = call_shahid_playout(video_id)
if playout.get('drm'):
    skip_asset(video_id, reason='DRM protected')

Type guard

def is_drm_playout(playout):
    return bool(playout.get('drm'))

Try / catch

try:
    extract(url)
except ExtractorError as e:
    if 'DRM protected' in str(e):
        mark_unextractable(video_id)
    else:
        raise

Prevention

When it happens

Trigger: Calling the Shahid playout API (playout/new/url/<video_id>) for an episode/movie whose playout dict contains 'drm': true (or any truthy value). This correlates with premium Shahid MVP-subscription content; free content returns drm false or omits the key.

Common situations: Attempting to download Shahid Premier / MVP exclusive shows without a subscription account; youtube-dl has no account support, so DRM assets always fail; also hit when a previously-free episode moves behind the paywall.

Related errors


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