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

Code before:
        sidhash = hashlib.sha1(' '.join(hash_parts).encode()).hexdigest()

        parts = [timestamp, sidhash]
        if additional_parts:
            parts.append(''.join(additional_parts))

        return f'{scheme} {"_".join(parts)}'

    _SAPISID = _3PSAPISID = _1PSAPISID = None

    def _load_sid_cookies(self):
        yt_cookies = self._get_cookies('https://www.youtube.com')
        yt_sapisid = try_call(lambda: yt_cookies['SAPISID'].value)
        yt_3papisid = try_call(lambda: yt_cookies['__Secure-3PAPISID'].value)

        if not self._SAPISID:
            # Sometimes SAPISID cookie isn't present but __Secure-3PAPISID is.
            # YouTube also falls back to __Secure-3PAPISID if SAPISID is missing.
            # See: https://github.com/yt-dlp/yt-dlp/issues/393
            self._SAPISID = yt_sapisid or yt_3papisid

        if not self._1PSAPISID:
            self._1PSAPISID = try_call(lambda: yt_cookies['__Secure-1PAPISID'].value)

        if not self._3PSAPISID:
            self._3PSAPISID = yt_3papisid

    def _get_sid_authorization_header(self, origin='https://www.youtube.com', user_session_id=None):
        """
        Generate API Session ID Authorization for Innertube requests. Assumes all requests are secure (https).
        @param origin: Origin URL
        @param user_session_id: Optional User Session ID
        @return: Authorization header value
        """

        authorizations = []
        additional_parts = {}
        if user_session_id:
            additional_parts['u'] = user_session_id

        self._load_sid_cookies()

        for scheme, sid in (('SAPISIDHASH', self._SAPISID),
                            ('SAPISID1PHASH', self._1PSAPISID),
                            ('SAPISID3PHASH', self._3PSAPISID)):
            if sid:
                authorizations.append(self._make_sid_authorization(scheme, sid, origin, additional_parts))

        if not authorizations:
            return None


Review comment (bug):
This will cache invalidated cookie values and send them with the API calls. It will make it difficult for us to debug what is happening when cookies are rotated, and it will hammer the API with invalid auth headers which could be detrimental to users' account standing

Would be better to not cache at all IMO

Code after:
        sidhash = hashlib.sha1(' '.join(hash_parts).encode()).hexdigest()

        parts = [timestamp, sidhash]
        if additional_parts:
            parts.append(''.join(additional_parts))

        return f'{scheme} {"_".join(parts)}'

    def _get_sid_cookies(self):
        """
        Get SAPISID, 1PSAPISID, 3PSAPISID cookie values
        @returns sapisid, 1psapisid, 3psapisid
        """
        yt_cookies = self._get_cookies('https://www.youtube.com')
        yt_sapisid = try_call(lambda: yt_cookies['SAPISID'].value)
        yt_3papisid = try_call(lambda: yt_cookies['__Secure-3PAPISID'].value)
        yt_1papisid = try_call(lambda: yt_cookies['__Secure-1PAPISID'].value)

        # Sometimes SAPISID cookie isn't present but __Secure-3PAPISID is.
        # YouTube also falls back to __Secure-3PAPISID if SAPISID is missing.
        # See: https://github.com/yt-dlp/yt-dlp/issues/393

        return yt_sapisid or yt_3papisid, yt_1papisid, yt_3papisid

    def _get_sid_authorization_header(self, origin='https://www.youtube.com', user_session_id=None):
        """
        Generate API Session ID Authorization for Innertube requests. Assumes all requests are secure (https).
        @param origin: Origin URL
        @param user_session_id: Optional User Session ID
        @return: Authorization header value
        """

        authorizations = []
        additional_parts = {}
        if user_session_id:
            additional_parts['u'] = user_session_id

        yt_sapisid, yt_1psapisid, yt_3psapisid = self._get_sid_cookies()

        for scheme, sid in (('SAPISIDHASH', yt_sapisid),
                            ('SAPISID1PHASH', yt_1psapisid),
                            ('SAPISID3PHASH', yt_3psapisid)):
            if sid:
                authorizations.append(self._make_sid_authorization(scheme, sid, origin, additional_parts))

        if not authorizations:
            return None

        return ' '.join(authorizations)

    def _call_api(self, ep, query, video_id, fatal=True, headers=None,