yt-dlp/yt-dlp · error · ExtractorError

Failed to retrieve video list for page {page + 1}

Error message

Failed to retrieve video list for page {page + 1}

What it means

Thrown by MurrtubeUserIE._fetch_page (yt_dlp/extractor/murrtube.py:131) while paginating a user's uploads. The GraphQL POST to https://murrtube.net/graphql (operationName 'Media', limit 10, offset page*10) returned HTTP 200 whose 'data' key is null - the standard GraphQL error envelope - so _download_gql returns None and that page of the video list is unusable. The extractor class is even marked _WORKING = False because the site's API keeps drifting.

Source

Thrown at yt_dlp/extractor/murrtube.py:131

    def _fetch_page(self, username, user_id, page):
        data = self._download_gql(username, {
            'operationName': 'Media',
            'variables': {
                'limit': self._PAGE_SIZE,
                'offset': page * self._PAGE_SIZE,
                'sort': 'latest',
                'userId': user_id,
            },
            'query': '''\
query Media($q: String, $sort: String, $userId: ID, $offset: Int!, $limit: Int!) {
  media(q: $q, sort: $sort, userId: $userId, offset: $offset, limit: $limit) {
    id
    __typename
  }
}'''},
            f'Downloading page {page + 1}')
        if data is None:
            raise ExtractorError(f'Failed to retrieve video list for page {page + 1}')

        media = data['media']

        for entry in media:
            yield self.url_result('murrtube:{}'.format(entry['id']), MurrtubeIE.ie_key())

    def _real_extract(self, url):
        username = self._match_id(url)
        data = self._download_gql(username, {
            'operationName': 'User',
            'variables': {
                'id': username,
            },
            'query': '''\
query User($id: ID!) {
  user(id: $id) {
    id
    __typename

View on GitHub (pinned to 81ecd58b13)

Solutions

  1. Update yt-dlp to the latest nightly (python -m pip -U --pre 'yt-dlp[default]'); murrtube is patched often and is currently marked broken
  2. Reproduce the call: POST the 'Media' query to https://murrtube.net/graphql with the same variables and read the 'errors' array to see the real reason
  3. Verify the username is a real profile - the 'User' query in _real_extract must return a user id before pagination starts
  4. Run with --verbose and confirm the age-check step (murrtube.net/accept_age_check) succeeded; clear cookies and retry
  5. If the API shape changed, report it with the --verbose log to https://github.com/yt-dlp/yt-dlp/issues
Defensive patterns

Strategy: try-catch

Validate before calling

import json, urllib.request

def murrtube_media_page_ok(username, user_id, page):
    op = {'operationName': 'Media', 'variables': {'limit': 10, 'offset': page * 10,
          'sort': 'latest', 'userId': user_id},
          'query': 'query Media($q: String, $sort: String, $userId: ID, $offset: Int!, $limit: Int!) { media(q: $q, sort: $sort, userId: $userId, offset: $offset, limit: $limit) { id __typename } }'}
    req = urllib.request.Request('https://murrtube.net/graphql', data=json.dumps(op).encode(),
                                 headers={'Content-Type': 'application/json'})
    with urllib.request.urlopen(req) as r:
        return json.load(r).get('data') is not None

Type guard

def is_graphql_null_data(resp: dict) -> bool:
    return resp.get('data') is None

Try / catch

from yt_dlp.utils import ExtractorError
try:
    info = ydl.extract_info(url, download=False)
except ExtractorError as e:
    if 'Failed to retrieve video list' in str(e):
        log.warning('murrtube pagination failed (site API drift, extractor is _WORKING=False): %s', e)
    else:
        raise

Prevention

When it happens

Trigger: POST to murrtube.net/graphql with variables {limit: 10, offset: page*10, sort: 'latest', userId: <id>}; the response body is {'errors': [...], 'data': null} instead of containing a 'media' array - invalid userId, WAF/Cloudflare challenge JSON, or a changed schema. Offsets past the end of a user's media can also return null data.

Common situations: Site API schema drift (extractor already flagged broken via _WORKING = False); stale yt-dlp version; missing age-check session because _real_initialize could not set the murrtube.net cookies; datacenter IP served a challenge instead of GraphQL data.

Related errors


AI-assisted analysis of yt-dlp/yt-dlp@81ecd58b13 (2026-08-22). Data as JSON: /api/errors/73f004e050ea9c4c. Report an issue: GitHub.