ytdl-org/youtube-dl · error · ExtractorError
%s said: %s
Error message
%s said: %s
What it means
Raised by the TFO extractor when the TFO API responds with success == 0 and the failure is not the known geo-block code. The message embeds the extractor name and the API's own HTML-cleaned 'msg' field, so the actual reason comes from the server (e.g. expired video, removed product id). It is marked expected=True, meaning youtube-dl treats it as a content-availability error rather than an extractor bug.
Source
Thrown at youtube_dl/extractor/tfo.py:41
'ext': 'mp4',
'title': 'Video Game Hackathon',
'description': 'md5:558afeba217c6c8d96c60e5421795c07',
}
}
def _real_extract(self, url):
video_id = self._match_id(url)
self._request_webpage(HEADRequest('http://www.tfo.org/'), video_id)
infos = self._download_json(
'http://www.tfo.org/api/web/video/get_infos', video_id, data=json.dumps({
'product_id': video_id,
}).encode(), headers={
'X-tfo-session': self._get_cookies('http://www.tfo.org/')['tfo-session'].value,
})
if infos.get('success') == 0:
if infos.get('code') == 'ErrGeoBlocked':
self.raise_geo_restricted(countries=self._GEO_COUNTRIES)
raise ExtractorError('%s said: %s' % (self.IE_NAME, clean_html(infos['msg'])), expected=True)
video_data = infos['data']
return {
'_type': 'url_transparent',
'id': video_id,
'url': 'limelight:media:' + video_data['llid'],
'title': video_data['title'],
'description': video_data.get('description'),
'series': video_data.get('collection'),
'season_number': int_or_none(video_data.get('season')),
'episode_number': int_or_none(video_data.get('episode')),
'duration': int_or_none(video_data.get('duration')),
'ie_key': 'LimelightMedia',
}
View on GitHub (pinned to 956b8c5855)
Solutions
- Open the same URL in a browser and confirm the video still plays on tfo.org; if it 404s, the video is gone and no tool-side fix exists
- Update to the latest youtube-dl / yt-dlp, where TFO extractor changes are tracked
- If the API returns ErrGeoBlocked but you still see this error, check that the initial HEADRequest to www.tfo.org succeeded and set the tfo-session cookie
- Use a Canadian exit IP (VPN) since TFO is geo-restricted to _GEO_COUNTRIES
Defensive patterns
Strategy: try-catch
Validate before calling
import urllib.request, json
req = urllib.request.Request('http://www.tfo.org/api/web/video/get_infos', data=json.dumps({'product_id': vid}).encode())
# a HEAD to www.tfo.org first is needed for the session cookie; if the API returns success:0 the extractor will fail Try / catch
from youtube_dl.utils import ExtractorError
try:
ydl.extract_info(url)
except ExtractorError as e:
if e.expected and 'TFO said' in str(e):
mark_unavailable(url, str(e)) # server-side refusal; do not retry
else:
raise Prevention
- Pre-validate TFO URLs in a browser before queueing them
- Treat expected=True errors from TFO as permanent for that URL
- Use a Canadian exit IP for TFO content
When it happens
Trigger: Calling the extractor on a tfo.org video whose /api/web/video/get_infos POST returns success:0 with a code other than 'ErrGeoBlocked'; e.g. a product_id that was retired or a video whose Limelight media (llid) was deleted.
Common situations: User passes an old TFO URL found in a playlist or forum post; TFO changes its API response shape; the 'tfo-session' cookie is missing so the API rejects the request; the video is region-locked under a code not equal to 'ErrGeoBlocked'.
Related errors
AI-assisted analysis of ytdl-org/youtube-dl@956b8c5855 (2026-08-14).
Data as JSON: /api/errors/1e6e3b415202b8d9.
Report an issue: GitHub.