{"record":{"id":"46235d760e9cee44","repo":"yt-dlp/yt-dlp","slug":"unsupported-url-redirect-url","errorCode":null,"errorMessage":"Unsupported URL: {redirect_url}","messagePattern":"Unsupported URL: (.+?)","errorType":"exception","errorClass":"UnsupportedError","httpStatus":null,"severity":"error","filePath":"yt_dlp/extractor/blackboardcollaborate.py","lineNumber":178,"sourceCode":"            'only_matching': True,\n        },\n        {\n            'url': 'https://us.bbcollab.com/launch/eyJhbGciOiJIUzI1NiJ9.eyJpc3MiOiJiYkNvbGxhYkFwaSIsInN1YiI6ImJiQ29sbGFiQXBpIiwiZXhwIjoxNjk0NDgxOTc3LCJpYXQiOjE2OTQ0ODE2NzcsInJlc291cmNlQWNjZXNzVGlja2V0Ijp7InJlc291cmNlSWQiOiI3YWU0MTFhNTU3NjU0OWFiOTZlYjVmMTM1YmY3MWU5MCIsImNvbnN1bWVySWQiOiJBRUU2MEI4MDI2QzM3ODU2RjMwMzNEN0ZEOTQzMTFFNSIsInR5cGUiOiJSRUNPUkRJTkciLCJyZXN0cmljdGlvbiI6eyJ0eXBlIjoiVElNRSIsImV4cGlyYXRpb25Ib3VycyI6MCwiZXhwaXJhdGlvbk1pbnV0ZXMiOjUsIm1heFJlcXVlc3RzIjotMX0sImRpc3Bvc2l0aW9uIjoiTEFVTkNIIiwibGF1bmNoVHlwZSI6bnVsbCwibGF1bmNoQ29tcG9uZW50IjpudWxsLCJsYXVuY2hQYXJhbUtleSI6bnVsbH19.yOhRZNaIjXYoMYMpcTzgjZJCnIFaYf2cAzbco8OAxlY',\n            'only_matching': True,\n        },\n        {\n            'url': 'https://eu.bbcollab.com/launch/eyJhbGciOiJIUzI1NiJ9.eyJpc3MiOiJiYkNvbGxhYkFwaSIsInN1YiI6ImJiQ29sbGFiQXBpIiwiZXhwIjoxNzUyNjgyODYwLCJpYXQiOjE3NTI2ODI1NjAsInJlc291cmNlQWNjZXNzVGlja2V0Ijp7InJlc291cmNlSWQiOiI4MjQzYjFiODg2Nzk0NTZkYjkwN2NmNDZmZmE1MmFhZiIsImNvbnN1bWVySWQiOiI5ZTY4NzYwZWJiNzM0MzRiYWY3NTQyZjA1YmJkOTMzMCIsInR5cGUiOiJSRUNPUkRJTkciLCJyZXN0cmljdGlvbiI6eyJ0eXBlIjoiVElNRSIsImV4cGlyYXRpb25Ib3VycyI6MCwiZXhwaXJhdGlvbk1pbnV0ZXMiOjUsIm1heFJlcXVlc3RzIjotMX0sImRpc3Bvc2l0aW9uIjoiTEFVTkNIIiwibGF1bmNoVHlwZSI6bnVsbCwibGF1bmNoQ29tcG9uZW50IjpudWxsLCJsYXVuY2hQYXJhbUtleSI6bnVsbH19.Xj4ymojYLwZ1vKPKZ-KxjpqQvFXoJekjRaG0npngwWs',\n            'only_matching': True,\n        },\n    ]\n\n    def _real_extract(self, url):\n        token = self._match_id(url)\n        video_id = jwt_decode_hs256(token)['resourceAccessTicket']['resourceId']\n\n        redirect_url = self._request_webpage(url, video_id).url\n        if self.suitable(redirect_url):\n            raise UnsupportedError(redirect_url)\n        return self.url_result(redirect_url, BlackboardCollaborateIE, video_id)\n","sourceCodeStart":160,"sourceCodeEnd":180,"githubUrl":"https://github.com/yt-dlp/yt-dlp/blob/81ecd58b1394793e6da9998cc19fdb45657f1685/yt_dlp/extractor/blackboardcollaborate.py#L160-L180","documentation":"BlackboardCollaborateLaunchIE handles bbcollab.com/launch/<jwt> links by decoding the JWT for the resourceId and following the redirect; a healthy link redirects to a collab/ui/session/playback URL handled by BlackboardCollaborateIE. When the redirect target AGAIN matches the launch pattern (the server bounced it back to another launch/gate page), it raises UnsupportedError(redirect_url) - yt-dlp's standard 'this URL cannot be processed' signal, surfaced as 'Unsupported URL: <redirect_url>'.","triggerScenarios":"The launch token is expired (the JWT exp / expirationMinutes restriction passed), the session requires authenticated SSO rather than guest access, or the recording is not yet available - so the server never hands over the playback URL.","commonSituations":"Reusing launch links copied from LMS pages or emails minutes-to-hours later; institutional recordings behind login; retrying old saved links after the token lifetime elapsed.","solutions":["Get a fresh launch URL from the LMS/email and run yt-dlp on it immediately - launch tokens are short-lived.","Open the link in a browser, authenticate if asked, then copy the final https://<region>.bbcollab.com/collab/ui/session/playback/load/<id> URL from the address bar and give THAT to yt-dlp.","Check the JWT payload (e.g. on jwt.io) to confirm the exp claim has not already passed.","If the recording requires your institution's login, browser + copied playback URL is the reliable path."],"exampleFix":"# before\nyt-dlp 'https://eu.bbcollab.com/launch/<stale-jwt>'\n# Unsupported URL: https://eu.bbcollab.com/launch/...\n\n# after (open launch link in a browser, log in, copy final URL)\nyt-dlp 'https://eu.bbcollab.com/collab/ui/session/playback/load/<recording-id>'","handlingStrategy":"fallback","validationCode":"import base64, json, time\n\ndef launch_token_still_valid(launch_url):\n    token = launch_url.rsplit('/', 1)[-1].split('.')[0]\n    payload = token + '=' * (-len(token) % 4)\n    claims = json.loads(base64.urlsafe_b64decode(payload))\n    return claims.get('exp', 0) > time.time()\n\nif not launch_token_still_valid(url):\n    get_fresh_link_from_lms()  # do not bother yt-dlp with an expired token","typeGuard":null,"tryCatchPattern":"from yt_dlp.utils import DownloadError, UnsupportedError\n\ntry:\n    info = ydl.extract_info(launch_url, download=False)\nexcept UnsupportedError:\n    # token bounced back to another /launch page: fall back to the manual path\n    info = ydl.extract_info(manually_copied_playback_url, download=False)","preventionTips":["Run yt-dlp on launch links immediately after obtaining them - the JWT exp is often minutes away.","For protected sessions, always keep the browser-open-then-copy-playback-URL fallback handy.","Decode the JWT and compare exp with current time before scripting downloads of shared launch links."],"tags":["blackboard-collaborate","unsupported-url","token-expired","redirect","yt-dlp"],"backgroundTag":"unsupported-url-format","analyzedSha":"81ecd58b1394793e6da9998cc19fdb45657f1685","analyzedAt":"2026-08-22T12:21:25.439Z","schemaVersion":2},"datasetVersion":"2026-08-22T14:17:55.899Z"}