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

Code before:
            try:
                return self._call_api_impl(ep, real_query, video_id, fatal, note, errnote)
            except ExtractorError as e:
                if isinstance(e.cause, json.JSONDecodeError) and e.cause.pos == 0:
                    message = str(e.cause or e.msg)
                    if not self._get_next_app_info():
                        if fatal:
                            raise
                        else:
                            self.report_warning(message)
                            return
                    self.report_warning(f'{message}. Retrying... (attempt {count} of {max_tries})')
                    continue
                raise

    def _extract_aweme_app(self, aweme_id):
        feed_list = self._call_api(
            'feed', {'aweme_id': aweme_id}, aweme_id, note='Downloading video feed',
            errnote='Unable to download video feed').get('aweme_list') or []
        aweme_detail = next((aweme for aweme in feed_list if str(aweme.get('aweme_id')) == aweme_id), None)
        if not aweme_detail:
            raise ExtractorError('Unable to find video in feed', video_id=aweme_id)
        return self._parse_aweme_video_app(aweme_detail)

    def _extract_web_data_and_status(self, url, video_id, fatal=True):
        webpage = self._download_webpage(url, video_id, headers={'User-Agent': 'Mozilla/5.0'}, fatal=fatal)
        video_data, status = {}, None

        if universal_data := self._get_universal_data(webpage, video_id):
            self.write_debug('Found universal data for rehydration')
            status = traverse_obj(universal_data, ('webapp.video-detail', 'statusCode', {int})) or 0
            video_data = traverse_obj(universal_data, ('webapp.video-detail', 'itemInfo', 'itemStruct', {dict}))

        elif sigi_data := self._get_sigi_state(webpage, video_id):
            self.write_debug('Found sigi state data')
            status = traverse_obj(sigi_data, ('VideoPage', 'statusCode', {int})) or 0
            video_data = traverse_obj(sigi_data, ('ItemModule', video_id, {dict}))

        elif next_data := self._search_nextjs_data(webpage, video_id, default={}):
            self.write_debug('Found next.js data')
            status = traverse_obj(next_data, ('props', 'pageProps', 'statusCode', {int})) or 0
            video_data = traverse_obj(next_data, ('props', 'pageProps', 'itemInfo', 'itemStruct', {dict}))

        elif fatal:
            raise ExtractorError('Unable to extract webpage video data')

        return video_data, status

    def _get_subtitles(self, aweme_detail, aweme_id, user_url):
        # TODO: Extract text positioning info
        subtitles = {}

Review comment (suggestion):
```suggestion
        webpage = self._download_webpage(url, video_id, headers={'User-Agent': 'Mozilla/5.0'}, fatal=fatal) or ''
```

Code after:
            try:
                return self._call_api_impl(ep, real_query, video_id, fatal, note, errnote)
            except ExtractorError as e:
                if isinstance(e.cause, json.JSONDecodeError) and e.cause.pos == 0:
                    message = str(e.cause or e.msg)
                    if not self._get_next_app_info():
                        if fatal:
                            raise
                        else:
                            self.report_warning(message)
                            return
                    self.report_warning(f'{message}. Retrying... (attempt {count} of {max_tries})')
                    continue
                raise

    def _extract_aweme_app(self, aweme_id):
        feed_list = self._call_api(
            'feed', {'aweme_id': aweme_id}, aweme_id, note='Downloading video feed',
            errnote='Unable to download video feed').get('aweme_list') or []
        aweme_detail = next((aweme for aweme in feed_list if str(aweme.get('aweme_id')) == aweme_id), None)
        if not aweme_detail:
            raise ExtractorError('Unable to find video in feed', video_id=aweme_id)
        return self._parse_aweme_video_app(aweme_detail)

    def _extract_web_data_and_status(self, url, video_id, fatal=True):
        webpage = self._download_webpage(url, video_id, headers={'User-Agent': 'Mozilla/5.0'}, fatal=fatal) or ''
        video_data, status = {}, None

        if universal_data := self._get_universal_data(webpage, video_id):
            self.write_debug('Found universal data for rehydration')
            status = traverse_obj(universal_data, ('webapp.video-detail', 'statusCode', {int})) or 0
            video_data = traverse_obj(universal_data, ('webapp.video-detail', 'itemInfo', 'itemStruct', {dict}))

        elif sigi_data := self._get_sigi_state(webpage, video_id):
            self.write_debug('Found sigi state data')
            status = traverse_obj(sigi_data, ('VideoPage', 'statusCode', {int})) or 0
            video_data = traverse_obj(sigi_data, ('ItemModule', video_id, {dict}))

        elif next_data := self._search_nextjs_data(webpage, video_id, default={}):
            self.write_debug('Found next.js data')
            status = traverse_obj(next_data, ('props', 'pageProps', 'statusCode', {int})) or 0
            video_data = traverse_obj(next_data, ('props', 'pageProps', 'itemInfo', 'itemStruct', {dict}))

        elif fatal:
            raise ExtractorError('Unable to extract webpage video data')

        return video_data, status

    def _get_subtitles(self, aweme_detail, aweme_id, user_url):
        # TODO: Extract text positioning info
        subtitles = {}