ytdl-org/youtube-dl · error · ExtractorError
No API host found
Error message
No API host found
What it means
Raised by the GB News extractor when the Simplestream metadata endpoint (self._SSMP_URL, downloaded with fatal=False) returns JSON lacking response.api_hostname. Because the download is non-fatal, network failure also funnels here: json_data can be None and traverse_obj yields nothing.
Source
Thrown at youtube_dl/extractor/gbnews.py:94
webpage, 'video data')
video_data = extract_attributes(video_data)
ss_id = video_data.get('data-id')
if not ss_id:
raise ExtractorError('Simplestream ID not found')
json_data = self._download_json(
self._SSMP_URL, display_id,
note='Downloading Simplestream JSON metadata',
errnote='Unable to download Simplestream JSON metadata',
query={
'id': ss_id,
'env': video_data.get('data-env', 'production'),
}, fatal=False)
meta_url = traverse_obj(json_data, ('response', 'api_hostname'))
if not meta_url:
raise ExtractorError('No API host found')
uvid = video_data['data-uvid']
dtype = video_data.get('data-type')
stream_data = self._download_json(
'%s/api/%s/stream/%s' % (meta_url, 'show' if dtype == 'vod' else dtype, uvid),
uvid,
query={
'key': video_data.get('data-key'),
'platform': self._PLATFORM,
},
headers={
'Token': video_data.get('data-token'),
'Token-Expiry': video_data.get('data-expiry'),
'Uvid': uvid,
}, fatal=False)
stream_url = traverse_obj(stream_data, (
'response', 'stream', T(url_or_none)))View on GitHub (pinned to 956b8c5855)
Solutions
- Re-run with -v to see whether the SSMP JSON request actually failed (fatal=False hides it)
- Update youtube-dl/yt-dlp to pick up SSMP URL/host changes
- Manually curl the SSMP URL with the page's data-id and data-env to inspect the JSON returned
- If the video was removed, try a different GB News URL or the broadcaster's official app
Defensive patterns
Strategy: try-catch
Validate before calling
import requests
r = requests.get(SSMP_URL, params={'id': ss_id, 'env': env})
if not r.ok() or not r.json().get('response', {}).get('api_hostname'):
print('SSMP metadata unavailable or missing api_hostname') Type guard
def ssmp_meta_ok(json_data):
return (
isinstance(json_data, dict)
and isinstance(json_data.get('response'), dict)
and isinstance(json_data['response'].get('api_hostname'), str)
) Try / catch
try:
info = ydl.extract_info(url)
except DownloadError as e:
if 'No API host found' in str(e):
retry_later_or_report(url) # could be transient (fatal=False) or site change
else:
raise Prevention
- Run with -v when this fires: fatal=False hides the underlying request failure
- Retry once after a short delay — transient SSMP failures are common
- Check data-env on the page matches an environment that still resolves
When it happens
Trigger: Querying the SSMP endpoint with the page's data-id/data-env returns an error payload (bad/expired ID, wrong env) instead of {response: {api_hostname: ...}}, or the request silently failed because fatal=False swallowed the network error.
Common situations: Expired or removed video IDs, Simplestream rotating API hostnames without updating the SSMP service, data-env other than 'production' pointing at a dead environment, or transient network failures masked by fatal=False.
Related errors
AI-assisted analysis of ytdl-org/youtube-dl@956b8c5855 (2026-08-14).
Data as JSON: /api/errors/34d2a60a87aa5d0c.
Report an issue: GitHub.