ytdl-org/youtube-dl · error · ExtractorError
%s
Error message
%s
What it means
Raised from ShahidBaseIE._handle_error when an AWS API Gateway call to api2.shahid.net fails and the HTTP error body parses as JSON containing a 'faults' array. Each fault's 'userMessage' (cleaned of HTML) is joined into one message and re-raised as an expected ExtractorError. It converts opaque AWS gateway faults into readable, user-facing Shahid API errors.
Source
Thrown at youtube_dl/extractor/shahid.py:33
parse_iso8601,
str_or_none,
urlencode_postdata,
)
class ShahidBaseIE(AWSIE):
_AWS_PROXY_HOST = 'api2.shahid.net'
_AWS_API_KEY = '2RRtuMHx95aNI1Kvtn2rChEuwsCogUd4samGPjLh'
_VALID_URL_BASE = r'https?://shahid\.mbc\.net/[a-z]{2}/'
def _handle_error(self, e):
fail_data = self._parse_json(
e.cause.read().decode('utf-8'), None, fatal=False)
if fail_data:
faults = fail_data.get('faults', [])
faults_message = ', '.join([clean_html(fault['userMessage']) for fault in faults if fault.get('userMessage')])
if faults_message:
raise ExtractorError(faults_message, expected=True)
def _call_api(self, path, video_id, request=None):
query = {}
if request:
query['request'] = json.dumps(request)
try:
return self._aws_execute_api({
'uri': '/proxy/v2/' + path,
'access_key': 'AKIAI6X4TYCIXM2B7MUQ',
'secret_key': '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',
}, video_id, query)
except ExtractorError as e:
if isinstance(e.cause, compat_HTTPError):
self._handle_error(e)
raise
class ShahidIE(ShahidBaseIE):View on GitHub (pinned to 956b8c5855)
Solutions
- Read the userMessage text: it names the real fault (session, entitlement, geo, or auth).
- If it is a session/device fault, re-run with a clean cache so the extractor regenerates its session (--no-cache-dir / delete ~/.cache/youtube-dl).
- If the fault is entitlement/DRM, the asset requires a Shahid subscription and cannot be downloaded anonymously.
- If every request faults with an auth/signature message, the extractor's embedded AWS credentials are stale - update to the latest youtube-dl/yt-dlp where new keys are shipped.
- If geo-blocked, use an appropriate VPN region or choose another source.
Defensive patterns
Strategy: try-catch
Try / catch
try:
result = shahid_call(path, video_id)
except ExtractorError as e:
if e.expected and 'session' in str(e).lower():
clear_cache(); retry_once()
else:
log_fault_message(str(e)) Prevention
- Clear the youtube-dl cache before Shahid batches so sessions are re-created.
- Treat any fault mentioning signature/auth as 'extractor outdated' - update immediately.
- Do not retry entitlement/DRM faults; they are deterministic.
When it happens
Trigger: Any _call_api invocation (e.g. playout/new/url/<id>, getuser or product endpoints) where _aws_execute_api raises ExtractorError whose cause is an HTTPError whose body has {'faults': [{'userMessage': ...}]}. Common fault causes: expired/invalid device session, DRM-restricted asset requiring subscription, geo restriction, or an expired API key/signature.
Common situations: Expired Shahid session token (the API demands a fresh deviceId/sessionId); trying to play premium/DRM content on a free account; the hard-coded AWS access key/secret in the extractor being rotated by MBC so every call is rejected with a signature fault; region blocks outside the MBC footprint.
Related errors
- This video is DRM protected.
- This video is DRM protected.
- This video is DRM protected.
- %s returned error: %s
- This video is DRM protected.
AI-assisted analysis of ytdl-org/youtube-dl@956b8c5855 (2026-08-14).
Data as JSON: /api/errors/fec04d73959186d8.
Report an issue: GitHub.