{"record":{"id":"796dbfd2582c09db","repo":"yt-dlp/yt-dlp","slug":"invalid-cookie-consent-redirect-url","errorCode":null,"errorMessage":"Invalid cookie consent redirect URL","messagePattern":"Invalid cookie consent redirect URL","errorType":"exception","errorClass":"ExtractorError","httpStatus":null,"severity":"error","filePath":"yt_dlp/extractor/youtube/_redirect.py","lineNumber":247,"sourceCode":"            'channel_follower_count': int,\n            'channel_id': 'UCIdEIHpS0TdkqRkHL5OkLtA',\n            'categories': ['Entertainment'],\n            'live_status': 'was_live',\n            'release_timestamp': 1671793345,\n            'channel': 'さなちゃんねる',\n            'description': 'md5:6aebf95cc4a1d731aebc01ad6cc9806d',\n            'uploader': 'さなちゃんねる',\n            'channel_is_verified': True,\n            'heatmap': 'count:100',\n        },\n        'add_ie': ['Youtube'],\n        'params': {'skip_download': 'Youtube'},\n    }]\n\n    def _real_extract(self, url):\n        redirect_url = url_or_none(parse_qs(url).get('continue', [None])[-1])\n        if not redirect_url:\n            raise ExtractorError('Invalid cookie consent redirect URL', expected=True)\n        return self.url_result(redirect_url)\n","sourceCodeStart":229,"sourceCodeEnd":249,"githubUrl":"https://github.com/yt-dlp/yt-dlp/blob/81ecd58b1394793e6da9998cc19fdb45657f1685/yt_dlp/extractor/youtube/_redirect.py#L229-L249","documentation":"YoutubeCookieConsentRedirectIE handles consent redirect URLs by reading the continue query parameter (last value, checked with url_or_none). If continue is missing or not a valid URL string, it raises expected=True instead of passing a broken URL downstream.","triggerScenarios":"Feeding yt-dlp a consent.youtube.com/m?... URL whose continue parameter was stripped, empty, or HTML-escaped into a non-URL value; typically these URLs are harvested programmatically from page HTML or logs rather than typed by hand.","commonSituations":"Scrapers extracting the consent redirect href but losing the query string; manually cleaning URLs and dropping params; double-escaping (&&amp;) making parse_qs yield an unusable value.","solutions":["Skip the consent wrapper entirely and give yt-dlp the intended target URL (the value that should be in continue=)","When harvesting redirect links from HTML, unescape entities first and preserve the full query string","Re-copy the complete consent URL including all parameters"],"exampleFix":"# before\nyt-dlp \"https://consent.youtube.com/m\"\n# -> Invalid cookie consent redirect URL\n\n# after: use the real destination directly\nyt-dlp \"https://www.youtube.com/watch?v=YE7VzlLtp-4\"","handlingStrategy":"validation","validationCode":"from urllib.parse import urlparse, parse_qs\nfrom yt_dlp.utils import url_or_none\n\ndef usable_consent_url(url: str) -> bool:\n    if 'consent.youtube.com' not in (host := urlparse(url).netloc):\n        return True  # not a consent redirect\n    continue_vals = parse_qs(urlparse(url).query).get('continue', [])\n    return bool(continue_vals) and url_or_none(continue_vals[-1]) is not None","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Store and hand yt-dlp the final target URL, not consent interstitials","When scraping redirect hrefs from HTML, unescape entities and keep the full query string","Reject harvested consent URLs lacking a continue parameter at ingest"],"tags":["youtube","consent","redirect","url-parsing"],"backgroundTag":"invalid-redirect-url","analyzedSha":"81ecd58b1394793e6da9998cc19fdb45657f1685","analyzedAt":"2026-08-22T12:21:25.439Z","schemaVersion":2},"datasetVersion":"2026-08-22T14:17:55.899Z"}