Repository: yt-dlp/yt-dlp
File: yt_dlp/extractor/reddit.py (Python)

Code before:
                'api_type': 'json',
            }), note='Logging in', errnote='Login request failed')
        errors = '; '.join(traverse_obj(login, ('json', 'errors', ..., 1)))
        if errors:
            raise ExtractorError(f'Unable to login, Reddit API says {errors}', expected=True)
        elif not traverse_obj(login, ('json', 'data', 'cookie', {str})):
            raise ExtractorError('Unable to login, no cookie was returned')

    def _get_subtitles(self, video_id):
        # Fallback if there were no subtitles provided by DASH or HLS manifests
        caption_url = f'https://v.redd.it/{video_id}/wh_ben_en.vtt'
        if self._is_valid_url(caption_url, video_id, item='subtitles'):
            return {'en': [{'url': caption_url}]}

    def _real_extract(self, url):
        host, slug, video_id = self._match_valid_url(url).group('host', 'slug', 'id')

        data = self._download_json(
            f'https://{host}/{slug}/.json', video_id, fatal=False, expected_status=403)
        if not data:
            fallback_host = 'old.reddit.com' if host != 'old.reddit.com' else 'www.reddit.com'
            self.to_screen(f'{host} request failed, retrying with {fallback_host}')
            data = self._download_json(
                f'https://{fallback_host}/{slug}/.json', video_id, fatal=False, expected_status=403)
            if not data:
                self.raise_login_required('Account authentication is required')

        if traverse_obj(data, 'error') == 403:
            reason = data.get('reason')
            if reason == 'quarantined':
                self.raise_login_required('Quarantined subreddit; an account that has opted in is required')
            elif reason == 'private':
                self.raise_login_required('Private subreddit; an account that has been approved is required')
            else:
                raise ExtractorError(f'HTTP Error 403 Forbidden; reason given: {reason}')

        data = data[0]['data']['children'][0]['data']
        video_url = data['url']

        over_18 = data.get('over_18')
        if over_18 is True:
            age_limit = 18
        elif over_18 is False:
            age_limit = 0
        else:
            age_limit = None

        thumbnails = []

        def add_thumbnail(src):
            if not isinstance(src, dict):

Review comment (security):
It's specifically a JSONDecodeError that occurs when auth is needed, right? We'd still want to raise the HTTPError if we get a 404 etc, no?

Code after:
                'passwd': password,
                'api_type': 'json',
            }), note='Logging in', errnote='Login request failed')
        errors = '; '.join(traverse_obj(login, ('json', 'errors', ..., 1)))
        if errors:
            raise ExtractorError(f'Unable to login, Reddit API says {errors}', expected=True)
        elif not traverse_obj(login, ('json', 'data', 'cookie', {str})):
            raise ExtractorError('Unable to login, no cookie was returned')

    def _get_subtitles(self, video_id):
        # Fallback if there were no subtitles provided by DASH or HLS manifests
        caption_url = f'https://v.redd.it/{video_id}/wh_ben_en.vtt'
        if self._is_valid_url(caption_url, video_id, item='subtitles'):
            return {'en': [{'url': caption_url}]}

    def _real_extract(self, url):
        slug, video_id = self._match_valid_url(url).group('slug', 'id')

        try:
            data = self._download_json(
                f'https://www.reddit.com/{slug}/.json', video_id, expected_status=403)
        except ExtractorError as e:
            if isinstance(e.cause, json.JSONDecodeError):
                self.raise_login_required('Account authentication is required')
            raise

        if traverse_obj(data, 'error') == 403:
            reason = data.get('reason')
            if reason == 'quarantined':
                self.raise_login_required('Quarantined subreddit; an account that has opted in is required')
            elif reason == 'private':
                self.raise_login_required('Private subreddit; an account that has been approved is required')
            else:
                raise ExtractorError(f'HTTP Error 403 Forbidden; reason given: {reason}')

        data = data[0]['data']['children'][0]['data']
        video_url = data['url']

        over_18 = data.get('over_18')
        if over_18 is True:
            age_limit = 18
        elif over_18 is False:
            age_limit = 0
        else:
            age_limit = None

        thumbnails = []

        def add_thumbnail(src):
            if not isinstance(src, dict):
                return