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
- Accept that the video is removed — there is no parameter that recovers it.
- Find a mirror or re-upload of the content on another site.
- 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.
- 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
- Assume VeeHD links are dead; validate before queueing.
- Mark removal errors as permanent in job state so they are never re-fetched.
- Keep a dead-link archive to short-circuit future runs.
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
- Video %s is no longer available
- no video on the webpage
- %s returned error: %s
- No video found
- %s returned error: %s
AI-assisted analysis of ytdl-org/youtube-dl@956b8c5855 (2026-08-14).
Data as JSON: /api/errors/42d05d56857df0b4.
Report an issue: GitHub.