ytdl-org/youtube-dl · error · ExtractorError

Video %s is locked

Error message

Video %s is locked

What it means

PornHubIE raises ExtractorError('Video %s is locked' % video_id, expected=True) when, after scanning all flashvar JS variable prefixes ('media', 'quality', 'qualityItems'), no video URLs were collected AND the webpage contains an element with id starting 'lockedPlayer'. This means the video requires a purchase, subscription tier, or is otherwise premium-locked, so PornHub serves a locked player with no media URLs.

Source

Thrown at youtube_dl/extractor/pornhub.py:396

                return
            for item in q_items:
                if isinstance(item, dict):
                    add_video_url(item.get('url'))

        if not video_urls:
            FORMAT_PREFIXES = ('media', 'quality', 'qualityItems')
            js_vars = extract_js_vars(
                webpage, r'(var\s+(?:%s)_.+)' % '|'.join(FORMAT_PREFIXES),
                default=None)
            if js_vars:
                for key, format_url in js_vars.items():
                    if key.startswith(FORMAT_PREFIXES[-1]):
                        parse_quality_items(format_url)
                    elif any(key.startswith(p) for p in FORMAT_PREFIXES[:2]):
                        add_video_url(format_url)
            if not video_urls and re.search(
                    r'<[^>]+\bid=["\']lockedPlayer', webpage):
                raise ExtractorError(
                    'Video %s is locked' % video_id, expected=True)

        if not video_urls:
            js_vars = extract_js_vars(
                dl_webpage('tv'), r'(var.+?mediastring.+?)</script>')
            add_video_url(js_vars['mediastring'])

        for mobj in re.finditer(
                r'<a[^>]+\bclass=["\']downloadBtn\b[^>]+\bhref=(["\'])(?P<url>(?:(?!\1).)+)\1',
                webpage):
            video_url = mobj.group('url')
            if video_url not in video_urls_set:
                video_urls.append((video_url, None))
                video_urls_set.add(video_url)

        upload_date = None
        formats = []

View on GitHub (pinned to 956b8c5855)

Solutions

  1. Log in with an account that has purchased/subscribed access (use --cookies from an entitled browser session).
  2. Verify the video's lock status on the site; if it is paywalled, extraction without entitlement is not possible.
  3. If you believe the video is free but still locked, update youtube-dl — flashvar variable naming changes can make free videos look 'locked' to old extractors.
  4. Remove the URL from automated batches to avoid repeat failures.

Example fix

# before
youtube_dl 'https://www.pornhub.com/view_video.php?viewkey=PREMIUM_ID'

# after
youtube_dl --cookies entitled-cookies.txt 'https://www.pornhub.com/view_video.php?viewkey=PREMIUM_ID'
Defensive patterns

Strategy: try-catch

Try / catch

try:
    info = ydl.extract_info(url)
except ExtractorError as e:
    if 'is locked' in str(e):
        retry_with_entitled_cookies(url)

Prevention

When it happens

Trigger: Extracting a premium/paid or VIP-locked video while not entitled: extract_js_vars finds no usable media/quality variables, video_urls stays empty, and the regex r'<[^>]+\bid=["\']lockedPlayer' matches the page. Only raised on the PC webpage path (inside the branch that downloaded webpage with those format prefixes).

Common situations: Model-channel or premium videos requiring paid access; logged-out extraction of subscriber-only content; cookies for an account without the needed entitlement.

Related errors


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