yt-dlp/yt-dlp · error · ExtractorError

Invalid login credentials

Error message

Invalid login credentials

What it means

Raised as an expected error by the Iwara extractor when a `user/login` API call returns HTTP-successfully but carries no `token` and its `message` contains 'invalidLogin' - i.e. the email/password taken from .netrc were rejected by the server.

Source

Thrown at yt_dlp/extractor/iwara.py:55

    def _get_user_token(self):
        username, password = self._get_login_info()
        if not username or not password:
            return

        user_token = IwaraBaseIE._USERTOKEN or self.cache.load(self._NETRC_MACHINE, username)
        if not user_token or self._is_token_expired(user_token, 'User'):
            response = self._call_api(
                'user/login', None, note='Logging in',
                headers={'Content-Type': 'application/json'}, data=json.dumps({
                    'email': username,
                    'password': password,
                }).encode(), expected_status=lambda x: True)
            user_token = traverse_obj(response, ('token', {str}))
            if not user_token:
                error = traverse_obj(response, ('message', {str}))
                if 'invalidLogin' in error:
                    raise ExtractorError('Invalid login credentials', expected=True)
                else:
                    raise ExtractorError(f'Iwara API said: {error or "nothing"}')

            self.cache.store(self._NETRC_MACHINE, username, user_token)

        IwaraBaseIE._USERTOKEN = user_token

    def _get_media_token(self):
        self._get_user_token()
        if not IwaraBaseIE._USERTOKEN:
            return  # user has not passed credentials

        if not IwaraBaseIE._MEDIATOKEN or self._is_token_expired(IwaraBaseIE._MEDIATOKEN, 'Media'):
            IwaraBaseIE._MEDIATOKEN = self._call_api(
                'user/token', None, note='Fetching media token',
                data=b'', headers={
                    'Authorization': f'Bearer {IwaraBaseIE._USERTOKEN}',
                    'Content-Type': 'application/json',

View on GitHub (pinned to 81ecd58b13)

Solutions

  1. Fix the .netrc entry: `machine iwara login <email> password <password>` (file must be readable only by you, chmod 600)
  2. Verify the same email/password actually logs in at iwara.gg in a browser
  3. Check for stray quotes/spaces in the .netrc line being sent as literal characters
  4. If credentials are fine, update yt-dlp in case the login endpoint changed

Example fix

# ~/.netrc - before (wrong password)
machine iwara login me@example.com password hunter2
# after
machine iwara login me@example.com password correct-horse-battery
Defensive patterns

Strategy: validation

Validate before calling

def netrc_entry_valid(machine: str, login: str, password: str) -> bool:
    # cheap pre-flight: confirm the credentials still work via the same endpoint
    import json, urllib.request
    req = urllib.request.Request(
        'https://api.iwara.tv/user/login',
        data=json.dumps({'email': login, 'password': password}).encode(),
        headers={'Content-Type': 'application/json'})
    resp = json.load(urllib.request.urlopen(req))
    return bool(resp.get('token'))

Try / catch

try:
    info = ydl.extract_info(url, download=False)
except ExtractorError as e:
    if 'Invalid login credentials' in str(e):
        alert('iwara .netrc password is wrong - update ~/.netrc')
    else:
        raise

Prevention

When it happens

Trigger: Calling any Iwara extractor with credentials while IwaraBaseIE._USERTOKEN is unset/expired and the cached token for that username is missing, and the supplied email/password pair is wrong. The check is a substring match of 'invalidLogin' in the API's message field.

Common situations: Wrong or outdated credentials in ~/.netrc (machine iwara), a password changed since the .netrc entry was written, typos, or .netrc permission/format problems causing garbage to be sent.

Related errors


AI-assisted analysis of yt-dlp/yt-dlp@81ecd58b13 (2026-08-22). Data as JSON: /api/errors/1eda7e3f91e3aec8. Report an issue: GitHub.