{"record":{"id":"301ee90a68d23c96","repo":"ytdl-org/youtube-dl","slug":"not-a-video","errorCode":null,"errorMessage":"not a video","messagePattern":"not a video","errorType":"exception","errorClass":"ExtractorError","httpStatus":null,"severity":"warning","filePath":"youtube_dl/extractor/flickr.py","lineNumber":116,"sourceCode":"            uploader_url = 'https://www.flickr.com/photos/%s/' % uploader_path if uploader_path else None\n\n            return {\n                'id': video_id,\n                'title': video_info['title']['_content'],\n                'description': video_info.get('description', {}).get('_content'),\n                'formats': formats,\n                'timestamp': int_or_none(video_info.get('dateuploaded')),\n                'duration': int_or_none(video_info.get('video', {}).get('duration')),\n                'uploader_id': uploader_id,\n                'uploader': owner.get('realname'),\n                'uploader_url': uploader_url,\n                'comment_count': int_or_none(video_info.get('comments', {}).get('_content')),\n                'view_count': int_or_none(video_info.get('views')),\n                'tags': [tag.get('_content') for tag in video_info.get('tags', {}).get('tag', [])],\n                'license': self._LICENSES.get(video_info.get('license')),\n            }\n        else:\n            raise ExtractorError('not a video', expected=True)\n","sourceCodeStart":98,"sourceCodeEnd":117,"githubUrl":"https://github.com/ytdl-org/youtube-dl/blob/956b8c585591b401a543e409accb163eeaaa1193/youtube_dl/extractor/flickr.py#L98-L117","documentation":"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.","triggerScenarios":"_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.","commonSituations":"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.","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"],"exampleFix":"# before\nyoutube_dl 'https://www.flickr.com/photos/user/11111111111'  # a photo\n# ERROR: not a video\n\n# after\nyoutube_dl 'https://www.flickr.com/photos/user/22222222222'  # the video item","handlingStrategy":"validation","validationCode":"# Pre-filter to video media only\ninfo = flickr_api_call('photos.getInfo', photo_id=pid)\nif info['photo']['media'] != 'video':\n    continue  # skip photos, avoid the extractor entirely","typeGuard":"def is_flickr_video(info: dict) -> bool:\n    return (\n        isinstance(info, dict)\n        and isinstance(info.get('photo'), dict)\n        and info['photo'].get('media') == 'video'\n    )","tryCatchPattern":"try:\n    ydl.extract_info(url)\nexcept ExtractorError as e:\n    if str(e) == 'not a video':\n        continue  # expected for photos; skip silently","preventionTips":["Pre-check media type via the Flickr API in pipelines","Album crawlers must expect mostly non-video items and filter"],"tags":["flickr","extractor","not-a-video","classification"],"backgroundTag":null,"analyzedSha":"956b8c585591b401a543e409accb163eeaaa1193","analyzedAt":"2026-08-14T18:59:47.863Z","schemaVersion":2},"datasetVersion":"2026-08-15T17:31:12.345Z"}