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

Code before:
    def _search_nextjs_data(self, webpage, video_id, *, fatal=True, default=NO_DEFAULT, **kw):
        if default == '{}':
            self._downloader.deprecation_warning('using `default=\'{}\'` is deprecated, use `default={}` instead')
            default = {}
        if default is not NO_DEFAULT:
            fatal = False

        return self._search_json(
            r'<script[^>]+id=[\'"]__NEXT_DATA__[\'"][^>]*>', webpage, 'next.js data',
            video_id, end_pattern='</script>', fatal=fatal, default=default, **kw)

    def _search_nextjs_v13_data(self, webpage, video_id, fatal=True):
        """Parses Next.js app router flight data that was introduced in Next.js v13"""
        nextjs_data = []
        if not fatal and not isinstance(webpage, str):
            return nextjs_data

        def flatten(flight_data):
            if not isinstance(flight_data, list) or not flight_data:
                return
            if len(flight_data) == 4 and flight_data[0] == '$':
                _, name, _, data = flight_data
                if not isinstance(data, dict):
                    return
                children = data.pop('children', None)
                if data and name and name[0] == '$':
                    # It is useful hydration JSON data
                    nextjs_data.append(data)
                flatten(children)
                return
            for f in flight_data:
                flatten(f)

        # The flight segments regex pattern can afford to be (and should be) strict
        # Ref: https://github.com/vercel/next.js/commit/5a4a08fdce91a038f2ed3a70568d3ed040403150
        #      /packages/next/src/server/app-render/use-flight-response.tsx
        for flight_segment in re.findall(r'<script[^>]*>self\.__next_f\.push\((\[.+?\])\)</script>', webpage):
            segment = self._parse_json(flight_segment, video_id, fatal=fatal, errnote=None if fatal else False)
            # Some earlier versions of next.js "optimized" away this array structure; this is unsupported
            # Ref: https://github.com/vercel/next.js/commit/0123a9d5c9a9a77a86f135b7ae30b46ca986d761
            if not isinstance(segment, list) or len(segment) != 2:
                self.write_debug(
                    f'{video_id}: Unsupported next.js flight data structure detected', only_once=True)
                continue
            payload_type, chunk = segment
            if payload_type == 3:
                try:
                    chunk = base64.b64decode(chunk).decode()
                except (ValueError, binascii.Error):
                    msg = 'Unable to parse next.js data: unable to decode flight data'
                    if not fatal:

Review comment (suggestion):
```suggestion
                if data and isinstance(name, str) and name[:1] == '$':
```

Code after:
        traverse_json_ld(json_ld)
        return filter_dict(info)

    def _search_nextjs_data(self, webpage, video_id, *, fatal=True, default=NO_DEFAULT, **kw):
        if default == '{}':
            self._downloader.deprecation_warning('using `default=\'{}\'` is deprecated, use `default={}` instead')
            default = {}
        if default is not NO_DEFAULT:
            fatal = False

        return self._search_json(
            r'<script[^>]+id=[\'"]__NEXT_DATA__[\'"][^>]*>', webpage, 'next.js data',
            video_id, end_pattern='</script>', fatal=fatal, default=default, **kw)

    def _search_nextjs_v13_data(self, webpage, video_id, fatal=True):
        """Parses Next.js app router flight data that was introduced in Next.js v13"""
        nextjs_data = []
        if not fatal and not isinstance(webpage, str):
            return nextjs_data

        def flatten(flight_data):
            if not isinstance(flight_data, list):
                return
            if len(flight_data) == 4 and flight_data[0] == '$':
                _, name, _, data = flight_data
                if not isinstance(data, dict):
                    return
                children = data.pop('children', None)
                if data and isinstance(name, str) and name.startswith('$'):
                    # It is useful hydration JSON data
                    nextjs_data.append(data)
                flatten(children)
                return
            for f in flight_data:
                flatten(f)

        flight_text = ''
        # The pattern for the surrounding JS/tag should be strict as it's a hardcoded string in the next.js source
        # Ref: https://github.com/vercel/next.js/blob/5a4a08fdc/packages/next/src/server/app-render/use-flight-response.tsx#L189
        for flight_segment in re.findall(r'<script\b[^>]*>self\.__next_f\.push\((\[.+?\])\)</script>', webpage):
            segment = self._parse_json(flight_segment, video_id, fatal=fatal, errnote=None if fatal else False)
            # Some earlier versions of next.js "optimized" away this array structure; this is unsupported
            # Ref: https://github.com/vercel/next.js/commit/0123a9d5c9a9a77a86f135b7ae30b46ca986d761
            if not isinstance(segment, list) or len(segment) != 2:
                self.write_debug(
                    f'{video_id}: Unsupported next.js flight data structure detected', only_once=True)
                continue
            # Only use the relevant payload type (1 == data)
            # Ref: https://github.com/vercel/next.js/blob/5a4a08fdc/packages/next/src/server/app-render/use-flight-response.tsx#L11-L14
            payload_type, chunk = segment
            if payload_type == 1: