ytdl-org/youtube-dl · error · ExtractorError
Unable to login: %s
Error message
Unable to login: %s
What it means
Raised by TeachableBaseIE._login when the login POST went through (no privacy-policy marker) and is_logged(response) is false, but the response contains an element with class 'alert'. The alert's cleaned text (typically 'Invalid email or password' or 'account locked') is surfaced as 'Unable to login: <alert text>' with expected=True.
Source
Thrown at youtube_dl/extractor/teachable.py:98
data=urlencode_postdata(login_form),
headers={
'Content-Type': 'application/x-www-form-urlencoded',
'Referer': login_url,
})
if '>I accept the new Privacy Policy<' in response:
raise ExtractorError(
'Unable to login: %s asks you to accept new Privacy Policy. '
'Go to https://%s/ and accept.' % (site, site), expected=True)
# Successful login
if is_logged(response):
self._logged_in = True
return
message = get_element_by_class('alert', response)
if message is not None:
raise ExtractorError(
'Unable to login: %s' % clean_html(message), expected=True)
raise ExtractorError('Unable to log in')
class TeachableIE(TeachableBaseIE):
_VALID_URL = r'''(?x)
(?:
%shttps?://(?P<site_t>[^/]+)|
https?://(?:www\.)?(?P<site>%s)
)
/courses/[^/]+/lectures/(?P<id>\d+)
''' % TeachableBaseIE._VALID_URL_SUB_TUPLE
_TESTS = [{
'url': 'https://gns3.teachable.com/courses/gns3-certified-associate/lectures/6842364',
'info_dict': {
'id': 'untlgzk1v7',View on GitHub (pinned to 956b8c5855)
Solutions
- Read the alert text in the message — it is the school's own login failure reason; correct the credentials in .netrc or --username/--password accordingly.
- Confirm the login works in a browser on the same site; if the browser also fails, fix the account first.
- Verify you are using credentials for the right school subdomain (Teachable accounts are per-site in this extractor).
- If MFA is required, create a session in a browser and reuse cookies rather than CLI login.
Defensive patterns
Strategy: validation
Validate before calling
# Verify credentials in a browser first; programmatic equivalent is just # attempting login and inspecting the expected alert error
Try / catch
try:
ydl.extract_info(url)
except ExtractorError as e:
if e.expected and 'Unable to login' in str(e):
log.error('Teachable login refused: %s', str(e)) # alert text included
notify_credentials_issue(site)
else:
raise Prevention
- Test Teachable school credentials in a browser before CLI use.
- Keep .netrc entries per-school and current.
- Watch for MFA on school accounts — use --cookies instead when enabled.
When it happens
Trigger: Logging in with wrong username/password or a locked/disabled account on any Teachable-based site: the school returns its HTML page with an alert div instead of a logged-in session.
Common situations: Wrong or stale password (school reset it); expired/deleted course accounts; password managers auto-filling outdated netrc entries; MFA-enabled accounts that cannot complete the CLI flow.
Related errors
- Unable to login: %s
- Unable to login: %s
- Unable to login: %s asks you to accept new Privacy Policy. G
- clean_html(error_message)
- No login info available, needed for using %s.
AI-assisted analysis of ytdl-org/youtube-dl@956b8c5855 (2026-08-14).
Data as JSON: /api/errors/251d7be11e1e1002.
Report an issue: GitHub.