ytdl-org/youtube-dl · error · ExtractorError

Video %s has been removed

Error message

Video %s has been removed

What it means

Raised by the VeeHD extractor when the second (post-garbage-first-request) download of the video page contains the literal marker 'This video has been removed<'. VeeHD serves corrupt data on the first request, so the code downloads twice; seeing the removal marker on the clean fetch means the video is gone. expected=True — content condition, not a network fault.

Source

Thrown at youtube_dl/extractor/veehd.py:62

        'info_dict': {
            'id': '2046729',
            'ext': 'avi',
            'title': '2012 (2009) DivX Trailer',
            'description': 'md5:75435ee95255e6a9838ac6f6f3a2396b',
            'uploader_id': 'Movie_Trailers',
        }
    }]

    def _real_extract(self, url):
        video_id = self._match_id(url)

        # VeeHD seems to send garbage on the first request.
        # See https://github.com/ytdl-org/youtube-dl/issues/2102
        self._download_webpage(url, video_id, 'Requesting webpage')
        webpage = self._download_webpage(url, video_id)

        if 'This video has been removed<' in webpage:
            raise ExtractorError('Video %s has been removed' % video_id, expected=True)

        player_path = self._search_regex(
            r'\$\("#playeriframe"\).attr\({src : "(.+?)"',
            webpage, 'player path')
        player_url = compat_urlparse.urljoin(url, player_path)

        self._download_webpage(player_url, video_id, 'Requesting player page')
        player_page = self._download_webpage(
            player_url, video_id, 'Downloading player page')

        video_url = None

        config_json = self._search_regex(
            r'value=\'config=({.+?})\'', player_page, 'config json', default=None)

        if config_json:
            config = json.loads(config_json)
            video_url = compat_urllib_parse_unquote(config['clip']['url'])

View on GitHub (pinned to 956b8c5855)

Solutions

  1. Accept that the video is removed — there is no parameter that recovers it.
  2. Find a mirror or re-upload of the content on another site.
  3. If maintaining the extractor and the page layout changed, update the marker string to the current removal text; otherwise the failure moves to the player-path regex.
  4. Filter veehd.com URLs out of batch downloads since the site is largely dead.
Defensive patterns

Strategy: validation

Validate before calling

html = fetch('http://veehd.com/video/' + video_id)  # second fetch: first returns garbage
if 'This video has been removed<' in html:
    skip(video_id, 'video removed from veehd')

Try / catch

try:
    ydl.extract_info(url)
except ExtractorError as e:
    if e.expected and 'has been removed' in str(e):
        archive_dead(url)  # permanent, do not retry
    raise

Prevention

When it happens

Trigger: Extracting any VeeHD video URL whose page now shows the removal notice; the string check on the second webpage download matches.

Common situations: VeeHD was effectively defunct — nearly all legacy links hit this; DMCA removals; template text changed so the marker no longer matches and the code instead fails later at the player-path regex.

Related errors


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