ytdl-org/youtube-dl · error · ExtractorError
%s returned error: %s
Error message
%s returned error: %s
What it means
Raised by the Vidme extractor when the api.vid.me response JSON (normally fetched, or recovered from a 400 body) contains a non-empty top-level 'error' key. The API's message is passed through with the extractor name. expected=True — the API explicitly rejected the videoByUrl lookup.
Source
Thrown at youtube_dl/extractor/vidme.py:149
'skip_download': True,
},
}]
def _real_extract(self, url):
video_id = self._match_id(url)
try:
response = self._download_json(
'https://api.vid.me/videoByUrl/%s' % video_id, video_id)
except ExtractorError as e:
if isinstance(e.cause, compat_HTTPError) and e.cause.code == 400:
response = self._parse_json(e.cause.read(), video_id)
else:
raise
error = response.get('error')
if error:
raise ExtractorError(
'%s returned error: %s' % (self.IE_NAME, error), expected=True)
video = response['video']
if video.get('state') == 'deleted':
raise ExtractorError(
'Vidme said: Sorry, this video has been deleted.',
expected=True)
if video.get('state') in ('user-disabled', 'suspended'):
raise ExtractorError(
'Vidme said: This video has been suspended either due to a copyright claim, '
'or for violating the terms of use.',
expected=True)
formats = []
for f in video.get('formats', []):
format_url = url_or_none(f.get('uri'))View on GitHub (pinned to 956b8c5855)
Solutions
- Accept that Vidme is defunct — the API will not return video data for any id.
- Remove/skip vid.me URLs from batch downloads and link checkers.
- If you maintain a fork, consider deleting or disabling the extractor family since the service is dead.
- Do not attempt retries; the error is a definitive API rejection.
Defensive patterns
Strategy: validation
Validate before calling
import json, urllib.request
try:
resp = json.load(urllib.request.urlopen('https://api.vid.me/videoByUrl/%s' % video_id))
except urllib.error.HTTPError as he:
resp = json.loads(he.read().decode())
if resp.get('error'):
skip(video_id, 'vidme api: %s' % resp['error']) Try / catch
try:
ydl.extract_info(url)
except ExtractorError as e:
if e.expected and 'returned error' in str(e):
archive_dead(url) # service shut down; permanent
raise Prevention
- Strip vid.me URLs from crawl lists — the service is defunct.
- Pre-check the API error field once and cache the verdict.
- Classify service-shutdown domains as permanently dead in link checkers.
When it happens
Trigger: Extracting a vid.me URL where the API answers {"error": ...} — nonexistent video slug, API version changes, or Vidme's shutdown responses. The same handler also covers the branch where a 400 response body is manually parsed.
Common situations: Vid.me shut down in late 2017, so virtually every vid.me URL now errors; archived playlists still contain vid.me links; the API domain no longer serves the videoByUrl contract.
Related errors
- %s returned error: %s
- Video %s is no longer available
- Vidme said: Sorry, this video has been deleted.
- % said: %s
- %s said: %s
AI-assisted analysis of ytdl-org/youtube-dl@956b8c5855 (2026-08-14).
Data as JSON: /api/errors/c3041e4df849616b.
Report an issue: GitHub.