ytdl-org/youtube-dl · error · ExtractorError
resp.get('userMessage') or resp['id']
Error message
resp.get('userMessage') or resp['id'] What it means
Raised by the Globo extractor's login helper when the auth API returns HTTP 401: it parses the error body and re-raises with its 'userMessage' (falling back to 'id'). Marked expected=True. Note the fallback resp['id'] will itself KeyError if the 401 body contains neither field.
Source
Thrown at youtube_dl/extractor/globo.py:90
return
try:
glb_id = (self._download_json(
'https://login.globo.com/api/authentication', None, data=json.dumps({
'payload': {
'email': email,
'password': password,
'serviceId': 4654,
},
}).encode(), headers={
'Content-Type': 'application/json; charset=utf-8',
}) or {}).get('glbId')
if glb_id:
self._set_cookie('.globo.com', 'GLBID', glb_id)
except ExtractorError as e:
if isinstance(e.cause, compat_HTTPError) and e.cause.code == 401:
resp = self._parse_json(e.cause.read(), None)
raise ExtractorError(resp.get('userMessage') or resp['id'], expected=True)
raise
def _real_extract(self, url):
video_id = self._match_id(url)
video = self._download_json(
'http://api.globovideos.com/videos/%s/playlist' % video_id,
video_id)['videos'][0]
if video.get('encrypted') is True:
raise ExtractorError('This video is DRM protected.', expected=True)
title = video['title']
formats = []
subtitles = {}
for resource in video['resources']:
resource_id = resource.get('_id')
resource_url = resource.get('url')View on GitHub (pinned to 956b8c5855)
Solutions
- Confirm your Globo credentials work in a browser on the same content
- Ensure the account has the subscription required for that video
- Re-enter credentials (--username/--password or netrc) to rule out stale ones
- Update youtube-dl/yt-dlp for auth endpoint changes
Defensive patterns
Strategy: try-catch
Validate before calling
import requests
r = requests.post(globo_auth_url, json=payload, headers={'Content-Type': 'application/json; charset=utf-8'})
if r.status_code == 401:
body = r.json()
print('Globo auth refused:', body.get('userMessage') or body.get('id')) Type guard
def globo_auth_ok(resp_json):
return isinstance(resp_json, dict) and 'glbId' in resp_json Try / catch
try:
ydl.extract_info(url)
except DownloadError as e:
if 'glbId' in str(e) or 'userMessage' in str(e) or 'Globo' in str(e):
reauth_and_retry(url) # 401 = credentials/entitlement
else:
raise Prevention
- Confirm the account's Globoplay tier covers premium content before automating
- Re-run login when you change the account password
- Treat 401s as expected auth failures, not extractor bugs
When it happens
Trigger: POSTing email/password to Globo's glbId endpoint with invalid credentials, an unentitled account (no Globoplay subscription for the content), or an expired session, yielding 401 with a JSON body.
Common situations: Wrong password, account without the required subscription, Globo changing its auth endpoint/response, or a 401 from rate-limiting whose body lacks userMessage/id (causing the secondary KeyError).
Related errors
- %s said: %s
- self._parse_json(e.cause.read(), None)['errorMessage']
- We're sorry, but either the User ID or Password entered is n
- Unable to login: %s said: %s
- Unable to login: %s
AI-assisted analysis of ytdl-org/youtube-dl@956b8c5855 (2026-08-14).
Data as JSON: /api/errors/fe033cc24cad3a8d.
Report an issue: GitHub.