ytdl-org/youtube-dl · error · ExtractorError

error

Error message

error

What it means

Raised by the xHamster extractor when the desktop page contains a <div id="videoClosed"> element. xHamster uses this element to state why a video is unavailable (removed, private, banned in region, disabled by uploader), and its text is forwarded as the error message.

Source

Thrown at youtube_dl/extractor/xhamster.py:143

        'only_matching': True,
    }, {
        'url': 'https://xhvid.com/videos/lk-mm-xhc6wn6',
        'only_matching': True,
    }]

    def _real_extract(self, url):
        mobj = re.match(self._VALID_URL, url)
        video_id = mobj.group('id') or mobj.group('id_2')
        display_id = mobj.group('display_id') or mobj.group('display_id_2')

        desktop_url = re.sub(r'^(https?://(?:.+?\.)?)m\.', r'\1', url)
        webpage, urlh = self._download_webpage_handle(desktop_url, video_id)

        error = self._html_search_regex(
            r'<div[^>]+id=["\']videoClosed["\'][^>]*>(.+?)</div>',
            webpage, 'error', default=None)
        if error:
            raise ExtractorError(error, expected=True)

        age_limit = self._rta_search(webpage)

        def get_height(s):
            return int_or_none(self._search_regex(
                r'^(\d+)[pP]', s, 'height', default=None))

        initials = self._parse_json(
            self._search_regex(
                (r'window\.initials\s*=\s*({.+?})\s*;\s*</script>',
                 r'window\.initials\s*=\s*({.+?})\s*;'), webpage, 'initials',
                default='{}'),
            video_id, fatal=False)
        if initials:
            video = initials['videoModel']
            title = video['title']
            formats = []
            format_urls = set()

View on GitHub (pinned to 956b8c5855)

Solutions

  1. Read the videoClosed div text forwarded in the error — it names the exact cause.
  2. For region bans, access via an permitted region or accept unavailability.
  3. For private/deleted videos, no download is possible without the uploader's grant.
Defensive patterns

Strategy: try-catch

Try / catch

try:
    info = ydl.extract_info(url)
except ExtractorError as e:
    if 'videoClosed' in str(e) or is_site_availability_error(e):
        classify_and_skip(url, str(e))
    else:
        raise

Prevention

When it happens

Trigger: Downloading an xHamster video whose page (after rewriting mobile URLs to desktop) matches r'<div[^>]+id=["\']videoClosed["\'][^>]*>(.+?)</div>' with non-empty content.

Common situations: Videos set to private or deleted by the uploader; content banned in the requester's country (some regions redirect to a closed notice); uploader accounts terminated.

Related errors


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