ytdl-org/youtube-dl · warning · ExtractorError
not a video
Error message
not a video
What it means
Raised by the Flickr extractor when the photo's media type in the API response is anything other than 'video'. Flickr hosts both photos and videos under the same URL scheme, and only video entries yield formats/duration; a plain photo falls through to this expected error. It is a clean, expected classification error, not a failure.
Source
Thrown at youtube_dl/extractor/flickr.py:116
uploader_url = 'https://www.flickr.com/photos/%s/' % uploader_path if uploader_path else None
return {
'id': video_id,
'title': video_info['title']['_content'],
'description': video_info.get('description', {}).get('_content'),
'formats': formats,
'timestamp': int_or_none(video_info.get('dateuploaded')),
'duration': int_or_none(video_info.get('video', {}).get('duration')),
'uploader_id': uploader_id,
'uploader': owner.get('realname'),
'uploader_url': uploader_url,
'comment_count': int_or_none(video_info.get('comments', {}).get('_content')),
'view_count': int_or_none(video_info.get('views')),
'tags': [tag.get('_content') for tag in video_info.get('tags', {}).get('tag', [])],
'license': self._LICENSES.get(video_info.get('license')),
}
else:
raise ExtractorError('not a video', expected=True)
View on GitHub (pinned to 956b8c5855)
Solutions
- Inspect the URL's page in a browser: if it shows a still photo, this error is correct behavior
- Find the actual video item in the album and pass its individual /photos/<user>/<id> URL
- For still images, use an image downloader instead of a video extractor
- In batch pipelines, pre-filter items with flickr.photos.getInfo (media == 'video') before invoking the extractor
Example fix
# before youtube_dl 'https://www.flickr.com/photos/user/11111111111' # a photo # ERROR: not a video # after youtube_dl 'https://www.flickr.com/photos/user/22222222222' # the video item
Defensive patterns
Strategy: validation
Validate before calling
# Pre-filter to video media only
info = flickr_api_call('photos.getInfo', photo_id=pid)
if info['photo']['media'] != 'video':
continue # skip photos, avoid the extractor entirely Type guard
def is_flickr_video(info: dict) -> bool:
return (
isinstance(info, dict)
and isinstance(info.get('photo'), dict)
and info['photo'].get('media') == 'video'
) Try / catch
try:
ydl.extract_info(url)
except ExtractorError as e:
if str(e) == 'not a video':
continue # expected for photos; skip silently Prevention
- Pre-check media type via the Flickr API in pipelines
- Album crawlers must expect mostly non-video items and filter
When it happens
Trigger: _call_api('photos.getInfo') returns video_info['media'] != 'video', so the else branch raises 'not a video' with expected=True. Produced by passing a photo (still image) URL to a video downloader, e.g. an album page link or a single image in a photoset.
Common situations: Feeding Flickr album/set URLs to youtube-dl; batch jobs that enumerate all photo ids in an account and hit the non-video majority; users assuming every Flickr URL is downloadable video.
Related errors
- data['message']
- %s is not a video
- Invalid path
- Unauthorized user "%s"
- Missing "id" field in extractor result
AI-assisted analysis of ytdl-org/youtube-dl@956b8c5855 (2026-08-14).
Data as JSON: /api/errors/301ee90a68d23c96.
Report an issue: GitHub.