ytdl-org/youtube-dl · error · ExtractorError

Video %s is no longer available

Error message

Video %s is no longer available

What it means

Raised by the VGTV extractor (and its sibling hosts via _HOST_TO_APPNAME) when the svp.vg.no asset JSON reports status == 'inactive'. That is the platform's own flag for retired/unpublished assets, so the message is a faithful content-state report. expected=True.

Source

Thrown at youtube_dl/extractor/vgtv.py:180

            'url': 'http://www.vgtv.no/video/84196/hevnen-er-soet-episode-10-abu',
            'only_matching': True,
        },
    ]

    def _real_extract(self, url):
        mobj = re.match(self._VALID_URL, url)
        video_id = mobj.group('id')
        host = mobj.group('host')
        appname = self._HOST_TO_APPNAME[host] if host else mobj.group('appname')
        vendor = self._APP_NAME_TO_VENDOR[appname]

        data = self._download_json(
            'http://svp.vg.no/svp/api/v1/%s/assets/%s?appName=%s-website'
            % (vendor, video_id, appname),
            video_id, 'Downloading media JSON')

        if data.get('status') == 'inactive':
            raise ExtractorError(
                'Video %s is no longer available' % video_id, expected=True)

        info = {
            'formats': [],
        }
        if len(video_id) == 5:
            if appname == 'bttv':
                info = self._extract_video_info('btno', video_id)

        streams = data['streamUrls']
        stream_type = data.get('streamType')
        is_live = stream_type == 'live'
        formats = []

        hls_url = streams.get('hls')
        if hls_url:
            formats.extend(self._extract_m3u8_formats(
                hls_url, video_id, 'mp4',

View on GitHub (pinned to 956b8c5855)

Solutions

  1. Open the article in a browser — if the player says the video is unavailable, it is gone.
  2. Search the publisher's site for a re-published version of the clip and use that URL.
  3. If the video plays in a browser but the API says inactive, the appName/vendor mapping changed — verify _HOST_TO_APPNAME/_APP_NAME_TO_VENDOR and the appName=<x>-website query parameter.
  4. Treat as terminal: skip, do not retry.
Defensive patterns

Strategy: try-catch

Validate before calling

import json, urllib.request
api = 'http://svp.vg.no/svp/api/v1/%s/assets/%s?appName=%s-website' % (vendor, video_id, appname)
data = json.load(urllib.request.urlopen(api))
if data.get('status') == 'inactive':
    skip(video_id, 'asset inactive')

Try / catch

try:
    ydl.extract_info(url)
except ExtractorError as e:
    if e.expected and 'no longer available' in str(e):
        log_skip(url, str(e))  # rights-expired news clips are permanent
    else:
        raise

Prevention

When it happens

Trigger: Extracting a vg.no/vgtv.no/bttv/abgtv URL whose SVP API asset (vendor path /assets/<id>?appName=...) has data['status'] == 'inactive'.

Common situations: News clips taken down after rights expired (very common for NRK/Schibsted sports highlights); articles deleted; short 5-char ids routed to the btno path that no longer resolves.

Related errors


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