ytdl-org/youtube-dl · error · ExtractorError
response['body']['message']
Error message
response['body']['message']
What it means
Raised by the Hotstar extractor's _call_api when the API response's statusCode is not 'OK'; the message comes from response['body']['message']. Marked expected=True. Note: if body or message is missing on a non-OK response this line KeyErrors, but the normal path surfaces Hotstar's own message (geo, entitlement, not-found).
Source
Thrown at youtube_dl/extractor/hotstar.py:49
exp = st + 6000
auth = 'st=%d~exp=%d~acl=/*' % (st, exp)
auth += '~hmac=' + hmac.new(self._AKAMAI_ENCRYPTION_KEY, auth.encode(), hashlib.sha256).hexdigest()
h = {'hotstarauth': auth}
h.update(headers)
return self._download_json(
'https://api.hotstar.com/' + path,
video_id, headers=h, query=query, data=data)
def _call_api(self, path, video_id, query_name='contentId'):
response = self._call_api_impl(path, video_id, {
'x-country-code': 'IN',
'x-platform-code': 'JIO',
}, {
query_name: video_id,
'tas': 10000,
})
if response['statusCode'] != 'OK':
raise ExtractorError(
response['body']['message'], expected=True)
return response['body']['results']
def _call_api_v2(self, path, video_id, headers, query=None, data=None):
h = {'X-Request-Id': compat_str(uuid.uuid4())}
h.update(headers)
try:
return self._call_api_impl(
path, video_id, h, query, data)
except ExtractorError as e:
if isinstance(e.cause, compat_HTTPError):
if e.cause.code == 402:
self.raise_login_required()
message = self._parse_json(e.cause.read().decode(), video_id)['message']
if message in ('Content not available in region', 'Country is not supported'):
raise self.raise_geo_restricted(message)
raise ExtractorError(message)
raise eView on GitHub (pinned to 956b8c5855)
Solutions
- Read the body message with -v: it distinguishes geo vs entitlement vs not-found
- For premium content, pass credentials/cookies of an entitled account
- Update to yt-dlp — Hotstar's API and headers changed repeatedly
- Verify the content still plays on hotstar.com in a browser
Defensive patterns
Strategy: try-catch
Validate before calling
import requests
resp = requests.get(f'https://api.hotstar.com/{path}', params={'contentId': vid, 'tas': 10000}, headers={'x-country-code': 'IN', 'x-platform-code': 'JIO'}).json()
if resp.get('statusCode') != 'OK':
print('Hotstar refusal:', resp.get('body', {}).get('message')) Type guard
def hotstar_ok(response):
return (
isinstance(response, dict)
and response.get('statusCode') == 'OK'
and isinstance(response.get('body'), dict)
and 'results' in response['body']
) Try / catch
try:
ydl.extract_info(url)
except DownloadError as e:
if 'Hotstar' in str(e) or 'hotstar' in str(e):
classify_and_log(url, str(e)) # geo vs entitlement vs removed
else:
raise Prevention
- Pass entitled account cookies for premium content
- Remember the extractor pins x-country-code: IN — region availability is judged for India
- Update to yt-dlp when Hotstar/JioHotstar API changes land
When it happens
Trigger: Calling api.hotstar.com with x-country-code: IN and x-platform-code: JIO for content that is not available in India, is premium-only, or has been removed — statusCode comes back non-OK with an error body.
Common situations: Premium Hotstar content without subscription login, region-locked content (headers force IN region), removed matches/episodes, or old builds predating Hotstar's API changes (now JioHotstar).
Related errors
- %s said: %s
- error['error_description']
- %s said: %s
- %s said: %s
- ', '.join([e['message'] for e in entitlement_issues])
AI-assisted analysis of ytdl-org/youtube-dl@956b8c5855 (2026-08-14).
Data as JSON: /api/errors/f57de3640d64b5d0.
Report an issue: GitHub.