ytdl-org/youtube-dl · error · ExtractorError

Unable to parse __NEXT_DATA__

Error message

Unable to parse __NEXT_DATA__

What it means

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.

Source

Thrown at youtube_dl/extractor/urplay.py:65

            'episode': 'Sovkudde',
        },
    }, {
        'url': 'http://urskola.se/Produkter/155794-Smasagor-meankieli-Grodan-i-vida-varlden',
        'only_matching': True,
    }]

    def _real_extract(self, url):
        video_id = self._match_id(url)
        url = url.replace('skola.se/Produkter', 'play.se/program')
        webpage = self._download_webpage(url, video_id)
        urplayer_data = self._search_regex(
            r'(?s)\bid\s*=\s*"__NEXT_DATA__"[^>]*>\s*({.+?})\s*</script',
            webpage, 'urplayer next data', fatal=False) or {}
        if urplayer_data:
            urplayer_data = self._parse_json(urplayer_data, video_id, fatal=False)
            urplayer_data = try_get(urplayer_data, lambda x: x['props']['pageProps']['program'], dict)
            if not urplayer_data:
                raise ExtractorError('Unable to parse __NEXT_DATA__')
        else:
            accessible_episodes = self._parse_json(self._html_search_regex(
                r'data-react-class="routes/Product/components/ProgramContainer/ProgramContainer"[^>]+data-react-props="({.+?})"',
                webpage, 'urplayer data'), video_id)['accessibleEpisodes']
            urplayer_data = next(e for e in accessible_episodes if e.get('id') == int_or_none(video_id))
        episode = urplayer_data['title']
        raw_streaming_info = urplayer_data['streamingInfo']['raw']
        host = self._download_json(
            'http://streaming-loadbalancer.ur.se/loadbalancer.json',
            video_id)['redirect']

        formats = []
        for k, v in raw_streaming_info.items():
            if not (k in ('sd', 'hd') and isinstance(v, dict)):
                continue
            file_http = v.get('location')
            if file_http:
                formats.extend(self._extract_wowza_formats(

View on GitHub (pinned to 956b8c5855)

Solutions

  1. 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).
  2. Update the try_get path in the extractor to the current location of the program object.
  3. 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.
  4. On an outdated youtube-dl install, upgrade first — UR Play layout changes are usually fixed upstream quickly.

Example fix

// before
urplayer_data = try_get(urplayer_data, lambda x: x['props']['pageProps']['program'], dict)
// after (adapt to actual new location, e.g. pageReward renamed)
urplayer_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)
Defensive patterns

Strategy: validation

Validate before calling

import json, re
html = fetch(url)
m = re.search(r'(?s)\bid\s*=\s*"__NEXT_DATA__"[^>]*>\s*({.+?})\s*</script', html)
if not m:
    raise SystemExit('site markup changed: no __NEXT_DATA__ script')
data = json.loads(m.group(1))
if not (data.get('props', {}).get('pageProps', {}).get('program')):
    raise SystemExit('pageProps.program missing — extractor needs updating')

Try / catch

try:
    info = ydl.extract_info(url)
except ExtractorError as e:
    if '__NEXT_DATA__' in str(e):
        report_extractor_bug('urplay', url, e)  # layout change: file issue, fall back to manual inspection
    else:
        raise

Prevention

When it happens

Trigger: 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.

Common situations: 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.

Understand the failure class

Related errors


AI-assisted analysis of ytdl-org/youtube-dl@956b8c5855 (2026-08-14). Data as JSON: /api/errors/d8d050e85ef3be3c. Report an issue: GitHub.