{"record":{"id":"3e157312ebf84ad8","repo":"ytdl-org/youtube-dl","slug":"unable-to-login-s-3e1573","errorCode":null,"errorMessage":"Unable to login: %s","messagePattern":"Unable to login: (.+?)","errorType":"exception","errorClass":"ExtractorError","httpStatus":null,"severity":"error","filePath":"youtube_dl/extractor/safari.py","lineNumber":67,"sourceCode":"        qs = compat_parse_qs(parsed_url.query)\n        next_uri = compat_urlparse.urljoin(\n            'https://api.oreilly.com', qs['next'][0])\n\n        auth, urlh = self._download_json_handle(\n            'https://www.oreilly.com/member/auth/login/', None, 'Logging in',\n            data=json.dumps({\n                'email': username,\n                'password': password,\n                'redirect_uri': next_uri,\n            }).encode(), headers={\n                'Content-Type': 'application/json',\n                'Referer': redirect_url,\n            }, expected_status=400)\n\n        credentials = auth.get('credentials')\n        if (not auth.get('logged_in') and not auth.get('redirect_uri')\n                and credentials):\n            raise ExtractorError(\n                'Unable to login: %s' % credentials, expected=True)\n\n        # oreilly serves two same instances of the following cookies\n        # in Set-Cookie header and expects first one to be actually set\n        for cookie in ('groot_sessionid', 'orm-jwt', 'orm-rt'):\n            self._apply_first_set_cookie_header(urlh, cookie)\n\n        _, urlh = self._download_webpage_handle(\n            auth.get('redirect_uri') or next_uri, None, 'Completing login',)\n\n        if is_logged(urlh):\n            self.LOGGED_IN = True\n            return\n\n        raise ExtractorError('Unable to log in')\n\n\nclass SafariIE(SafariBaseIE):","sourceCodeStart":49,"sourceCodeEnd":85,"githubUrl":"https://github.com/ytdl-org/youtube-dl/blob/956b8c585591b401a543e409accb163eeaaa1193/youtube_dl/extractor/safari.py#L49-L85","documentation":"Raised by the Safari Books/O'Reilly login helper when the auth API response (requested with expected_status=400) has logged_in false, no redirect_uri, and a 'credentials' payload - i.e. the server rejected the credentials and told you why. Message: 'Unable to login: <credentials text>'. Expected=True.","triggerScenarios":"Running youtube-dl with --username/--password against oreilly/safaribooksonline where the email/password JSON POST returns 400 plus a credentials error (wrong password, unknown email).","commonSituations":"Typos in credentials, expired passwords, or accounts without video entitlement; also stale cookies interleaving with the login POST.","solutions":["Re-enter username/password carefully (the credentials text from the server names the exact problem).","Reset the password on oreilly.com if it expired.","Verify the account has access to the content being downloaded.","Clear stored cookies for the site and retry so the login POST is clean."],"exampleFix":null,"handlingStrategy":"try-catch","validationCode":null,"typeGuard":null,"tryCatchPattern":"try:\n    ydl.extract_info(url)\nexcept ExtractorError as e:\n    if str(e).startswith('Unable to login:'):\n        fix_credentials(e)  # server message names the credential problem\n    else:\n        raise","preventionTips":["Test credentials on oreilly.com before using them with youtube-dl.","Keep credentials in a netrc file rather than CLI flags to avoid typos and shell history leaks.","Clear site cookies between attempts so the auth POST starts clean."],"tags":["safari","oreilly","login","credentials","expected-error"],"backgroundTag":null,"analyzedSha":"956b8c585591b401a543e409accb163eeaaa1193","analyzedAt":"2026-08-14T18:59:47.863Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}