ytdl-org/youtube-dl · error · ExtractorError

Login failed, %s said: %r

Error message

Login failed, %s said: %r

What it means

Raised by TennisTVIE._login when the POST to tennistv.com/api/users/v1/login succeeds at HTTP level but the JSON body has a truthy error.errorCode. The API's errorMessage is embedded as 'Login failed, TennisTV said: <message>'. Unlike other login errors here it is NOT marked expected=True, so youtube-dl logs it as a login error with the site's reason.

Source

Thrown at youtube_dl/extractor/tennistv.py:58

            'Email': username,
            'Password': password,
        }
        login_json = json.dumps(login_form).encode('utf-8')
        headers = {
            'content-type': 'application/json',
            'Referer': 'https://www.tennistv.com/login',
            'Origin': 'https://www.tennistv.com',
        }

        login_result = self._download_json(
            'https://www.tennistv.com/api/users/v1/login', None,
            note='Logging in',
            errnote='Login failed (wrong password?)',
            headers=headers,
            data=login_json)

        if login_result['error']['errorCode']:
            raise ExtractorError('Login failed, %s said: %r' % (self.IE_NAME, login_result['error']['errorMessage']))

        if login_result['entitlement'] != 'SUBSCRIBED':
            self.report_warning('%s may not be subscribed to %s.' % (username, self.IE_NAME))

        self._session_token = login_result['sessionToken']

    def _real_initialize(self):
        self._login()

    def _real_extract(self, url):
        video_id = self._match_id(url)
        webpage = self._download_webpage(url, video_id)

        internal_id = self._search_regex(r'video=([0-9]+)', webpage, 'internal video id')

        headers = {
            'Origin': 'https://www.tennistv.com',
            'authorization': 'ATP %s' % self._session_token,

View on GitHub (pinned to 956b8c5855)

Solutions

  1. Read the relayed errorMessage — it is TennisTV's exact refusal reason; fix credentials accordingly.
  2. Verify sign-in at https://www.tennistv.com/login in a browser before blaming the tool.
  3. Confirm your subscription is active; a lapsed subscription can produce API-level login errors.
  4. If credentials are right but it still fails, the API schema likely changed — upgrade youtube-dl/yt-dlp or switch to cookie-based auth (--cookies from a logged-in browser session).
Defensive patterns

Strategy: try-catch

Try / catch

try:
    ydl.extract_info(url)
except ExtractorError as e:
    if 'Login failed, TennisTV said' in str(e):
        log.error('TennisTV API: %s', str(e))  # contains errorMessage
        prompt_reauth()
    else:
        raise

Prevention

When it happens

Trigger: Submitting credentials that the TennisTV login API rejects: wrong password (errorCode set), unknown email, or account-level refusal; also fires when the API changes its error envelope shape so error.errorCode becomes truthy unexpectedly.

Common situations: Expired/changed passwords; API contract changes after TennisTV site updates; accounts locked for too many attempts; free accounts trying to fetch subscriber content.

Related errors


AI-assisted analysis of ytdl-org/youtube-dl@956b8c5855 (2026-08-14). Data as JSON: /api/errors/750c7e65c68c3deb. Report an issue: GitHub.