yt-dlp/yt-dlp · error · ExtractorError
{error_msg}{login_hint}
Error message
{error_msg}{login_hint} What it means
Weverse does not accept email/password in yt-dlp. Login works via OAuth tokens: the username must start with the literal prefix 'oauth' (e.g. oauth+LABEL), and the password must be the refresh token copied from the browser cookie. _report_login_error wraps the mapped error message with a hint that spells out the exact --username/--password values or the session-cookie alternative.
Source
Thrown at yt_dlp/extractor/weverse.py:159
def _get_authorization_header(self):
if not self._is_logged_in:
return {}
if self._token_is_expired(self._ACCESS_TOKEN_KEY):
self._refresh_access_token()
return {'Authorization': f'Bearer {self._oauth_tokens[self._ACCESS_TOKEN_KEY]}'}
def _report_login_error(self, error_id):
error_msg = self._LOGIN_ERRORS_MAP[error_id]
username = self._get_login_info()[0]
if error_id == 'invalid_username':
error_msg = error_msg.format(username)
username = f'{self._OAUTH_PREFIX}+{username}'
elif not username:
username = f'{self._OAUTH_PREFIX}+USERNAME'
raise ExtractorError(join_nonempty(
error_msg, self._LOGIN_HINT_TMPL.format(self._OAUTH_PREFIX, self._REFRESH_TOKEN_KEY, username),
'Or else you can u', self._login_hint(method='session_cookies')[1:], delim=''), expected=True)
def _perform_login(self, username, password):
if self._is_logged_in:
return
if username.partition('+')[0] != self._OAUTH_PREFIX:
self._report_login_error('invalid_username')
self._oauth_tokens.update(self.cache.load(self._NETRC_MACHINE, self._oauth_cache_key, default={}))
if self._is_logged_in and self._access_token_is_valid():
return
rt_key = self._REFRESH_TOKEN_KEY
if not self._oauth_tokens.get(rt_key) or self._token_is_expired(rt_key):
if try_call(lambda: jwt_decode_hs256(password)['scope']) != 'refresh':
self._report_login_error('invalid_password')View on GitHub (pinned to 81ecd58b13)
Solutions
- Follow the hint embedded in the error text: --username 'oauth+ANY_LABEL' --password 'REFRESH_TOKEN' where REFRESH_TOKEN is the value of the cookie named in the message from a logged-in browser
- Run 'yt-dlp --rm-cache-dir' to drop stale cached Weverse tokens, then log in again with a fresh refresh token
- Alternatively export session cookies from a logged-in browser with --cookies-from-browser
- Update yt-dlp - the token scheme and hint text have changed across releases
Example fix
# before: email/password is not a valid Weverse login for yt-dlp yt-dlp --username fan@mail.com --password hunter2 'https://weverse.io/artist/live/1-123' # after: oauth-prefixed username + refresh token cookie value yt-dlp --username 'oauth+fan@mail.com' --password 'REFRESH_TOKEN_FROM_BROWSER_COOKIE' 'https://weverse.io/artist/live/1-123'
Defensive patterns
Strategy: try-catch
Validate before calling
# Weverse login contract: username must start with 'oauth+' and the
# password must be the refresh token cookie value, not the account password.
if not username.startswith('oauth+'):
raise ValueError("Weverse username must be 'oauth+LABEL', not an email")
if password == account_password:
raise ValueError('Weverse password must be the refresh token cookie value from the browser') Type guard
def is_weverse_login_hint(exc: Exception) -> bool:
return isinstance(exc, ExtractorError) and (
'not valid login username' in str(exc)
or 'valid refresh token' in str(exc)
or 'logged-in users' in str(exc)
or 'refresh token' in str(exc)) Try / catch
try:
with YoutubeDL({'username': 'oauth+main', 'password': refresh_token}) as ydl:
ydl.download([url])
except DownloadError as e:
if 'refresh token' in str(e) or 'login' in str(e):
refresh_token = fetch_fresh_refresh_token_cookie() # from the logged-in browser
subprocess.run(['yt-dlp', '--rm-cache-dir'])
retry_with(refresh_token)
else:
raise Prevention
- Always use the 'oauth+' username prefix and the refresh token cookie as the password
- Copy the cookie value named in the error hint, not the access token
- Clear the yt-dlp cache after re-logging in on the web so stale tokens are dropped
- Automate token refresh by exporting fresh cookies periodically for long-running jobs
When it happens
Trigger: Running with --username that does not start with 'oauth+' (e.g. an email address), passing an access token instead of the refresh token as the password, an expired cached refresh token, or hitting members-only content with no login at all - each maps to an id in _LOGIN_ERRORS_MAP and this combined message-plus-hint.
Common situations: Trying email+password like a normal site; copying the wrong cookie value; refresh tokens expiring after web re-login; stale cached tokens on disk.
Related errors
- Access token has expired or been invalidated. Get a new "acc
- Login failed
- Unable to login: {self.IE_NAME} said: {error}
- Unable to login: {error}
- Unable to log in
AI-assisted analysis of yt-dlp/yt-dlp@81ecd58b13 (2026-08-22).
Data as JSON: /api/errors/be213823909a7df7.
Report an issue: GitHub.