{"record":{"id":"d8d050e85ef3be3c","repo":"ytdl-org/youtube-dl","slug":"unable-to-parse-next-data","errorCode":null,"errorMessage":"Unable to parse __NEXT_DATA__","messagePattern":"Unable to parse __NEXT_DATA__","errorType":"exception","errorClass":"ExtractorError","httpStatus":null,"severity":"error","filePath":"youtube_dl/extractor/urplay.py","lineNumber":65,"sourceCode":"            'episode': 'Sovkudde',\n        },\n    }, {\n        'url': 'http://urskola.se/Produkter/155794-Smasagor-meankieli-Grodan-i-vida-varlden',\n        'only_matching': True,\n    }]\n\n    def _real_extract(self, url):\n        video_id = self._match_id(url)\n        url = url.replace('skola.se/Produkter', 'play.se/program')\n        webpage = self._download_webpage(url, video_id)\n        urplayer_data = self._search_regex(\n            r'(?s)\\bid\\s*=\\s*\"__NEXT_DATA__\"[^>]*>\\s*({.+?})\\s*</script',\n            webpage, 'urplayer next data', fatal=False) or {}\n        if urplayer_data:\n            urplayer_data = self._parse_json(urplayer_data, video_id, fatal=False)\n            urplayer_data = try_get(urplayer_data, lambda x: x['props']['pageProps']['program'], dict)\n            if not urplayer_data:\n                raise ExtractorError('Unable to parse __NEXT_DATA__')\n        else:\n            accessible_episodes = self._parse_json(self._html_search_regex(\n                r'data-react-class=\"routes/Product/components/ProgramContainer/ProgramContainer\"[^>]+data-react-props=\"({.+?})\"',\n                webpage, 'urplayer data'), video_id)['accessibleEpisodes']\n            urplayer_data = next(e for e in accessible_episodes if e.get('id') == int_or_none(video_id))\n        episode = urplayer_data['title']\n        raw_streaming_info = urplayer_data['streamingInfo']['raw']\n        host = self._download_json(\n            'http://streaming-loadbalancer.ur.se/loadbalancer.json',\n            video_id)['redirect']\n\n        formats = []\n        for k, v in raw_streaming_info.items():\n            if not (k in ('sd', 'hd') and isinstance(v, dict)):\n                continue\n            file_http = v.get('location')\n            if file_http:\n                formats.extend(self._extract_wowza_formats(","sourceCodeStart":47,"sourceCodeEnd":83,"githubUrl":"https://github.com/ytdl-org/youtube-dl/blob/956b8c585591b401a543e409accb163eeaaa1193/youtube_dl/extractor/urplay.py#L47-L83","documentation":"Raised by the UR Play (urplay.se) extractor when it finds a __NEXT_DATA__ script tag on the page but cannot turn it into usable program data — either json parsing failed (fatal=False swallows the parse error) or the expected props.pageProps.program dict is absent after traversal. It means the Next.js page structure changed or the JSON was truncated, so the primary extraction path is dead.","triggerScenarios":"Extracting any urplay.se/program (or skola.se/Produkter) URL where the regex matches the __NEXT_DATA__ script but _parse_json or try_get(...['props']['pageProps']['program']) yields None.","commonSituations":"UR Play ships a site redesign that renames pageProps.program, moves data to another key, or server-renders differently; A/B variant pages; the regex captures a partial JSON blob on very large pages.","solutions":["Open the URL in a browser and inspect the __NEXT_DATA__ script to see the new JSON shape (e.g. program moved or renamed under pageProps).","Update the try_get path in the extractor to the current location of the program object.","If the script tag itself is gone, extend the fallback branch (the data-react-class ProgramContainer path) or add a new regex for the current markup.","On an outdated youtube-dl install, upgrade first — UR Play layout changes are usually fixed upstream quickly."],"exampleFix":"// before\nurplayer_data = try_get(urplayer_data, lambda x: x['props']['pageProps']['program'], dict)\n// after (adapt to actual new location, e.g. pageReward renamed)\nurplayer_data = try_get(urplayer_data, lambda x: x['props']['pageProps']['program'], dict) or try_get(urplayer_data, lambda x: x['props']['pageProps']['data']['program'], dict)","handlingStrategy":"validation","validationCode":"import json, re\nhtml = fetch(url)\nm = re.search(r'(?s)\\bid\\s*=\\s*\"__NEXT_DATA__\"[^>]*>\\s*({.+?})\\s*</script', html)\nif not m:\n    raise SystemExit('site markup changed: no __NEXT_DATA__ script')\ndata = json.loads(m.group(1))\nif not (data.get('props', {}).get('pageProps', {}).get('program')):\n    raise SystemExit('pageProps.program missing — extractor needs updating')","typeGuard":null,"tryCatchPattern":"try:\n    info = ydl.extract_info(url)\nexcept ExtractorError as e:\n    if '__NEXT_DATA__' in str(e):\n        report_extractor_bug('urplay', url, e)  # layout change: file issue, fall back to manual inspection\n    else:\n        raise","preventionTips":["Pin a known-good youtube-dl version for production scrapes and test site-specific extractors after site updates.","Wrap single-site scrapers so a layout-change error quarantines only that site's URLs.","Cache successful extraction results to avoid re-hitting fragile pages."],"tags":["site-layout-change","json","nextjs","extractor"],"backgroundTag":null,"analyzedSha":"956b8c585591b401a543e409accb163eeaaa1193","analyzedAt":"2026-08-14T18:59:47.863Z","schemaVersion":2},"datasetVersion":"2026-08-15T17:31:12.345Z"}