ytdl-org/youtube-dl · error · ExtractorError

Cannot download embed-only video without embedding URL. Plea

Error message

Cannot download embed-only video without embedding URL. Please call youtube-dl with the URL of the page that embeds this video.

What it means

Raised by VimeoIE._real_extract when downloading the video page returns HTTP 403 whose body contains 'Because of its privacy settings, this video cannot be played here' — the mark of an embed-only (domain-restricted) video. The player refuses off-domain access, so the extractor needs the URL of the page that embeds the player, not the player/video URL alone. expected=True.

Source

Thrown at youtube_dl/extractor/vimeo.py:668

        if is_pro:
            # some videos require portfolio_id to be present in player url
            # https://github.com/ytdl-org/youtube-dl/issues/20070
            url = self._extract_url(url, self._download_webpage(url, video_id))
            if not url:
                url = 'https://vimeo.com/' + video_id
        elif any(p in url for p in ('play_redirect_hls', 'moogaloop.swf')):
            url = 'https://vimeo.com/' + video_id

        try:
            # Retrieve video webpage to extract further information
            webpage, urlh = self._download_webpage_handle(
                url, video_id, headers=headers)
            redirect_url = urlh.geturl()
        except ExtractorError as ee:
            if isinstance(ee.cause, compat_HTTPError) and ee.cause.code == 403:
                errmsg = ee.cause.read()
                if b'Because of its privacy settings, this video cannot be played here' in errmsg:
                    raise ExtractorError(
                        'Cannot download embed-only video without embedding '
                        'URL. Please call youtube-dl with the URL of the page '
                        'that embeds this video.',
                        expected=True)
            raise

        if '//player.vimeo.com/video/' in url:
            config = self._search_json(
                r'\b(?:playerC|c)onfig\s*=', webpage, 'info section', video_id)
            if config.get('view') == 4:
                config = self._verify_player_video_password(
                    redirect_url, video_id, headers)
            info = self._parse_config(config, video_id)
            self._vimeo_sort_formats(info['formats'])
            return info

        if re.search(r'<form[^>]+?id="pw_form"', webpage):
            video_password = self._get_video_password()

View on GitHub (pinned to 956b8c5855)

Solutions

  1. Call youtube-dl with the full URL of the page that embeds the video, not the player iframe URL.
  2. If you only have the player URL, find the originating site (referrer, search the video id) and use that page's URL.
  3. If you are the video owner, loosen privacy settings (allow embedding anywhere / public) to extract from vimeo.com directly.
  4. As a last resort, authenticated session cookies for the allowed domain plus the page URL are required — there is no parameter to bypass domain restriction.

Example fix

# before
youtube_dl 'https://player.vimeo.com/video/12345678'
# after
youtube_dl 'https://example.com/course/lesson-1'   # page that embeds the player
Defensive patterns

Strategy: validation

Validate before calling

if 'player.vimeo.com/video/' in url or 'moogaloop.swf' in url:
    warn('embed-only risk: prefer the URL of the page embedding this player; domain-restricted videos 403 otherwise')

Type guard

def is_vimeo_player_url(u: str) -> bool:
    """True when u targets the Vimeo player directly and may hit embed-only privacy 403s."""
    return ('player.vimeo.com/video/' in u) or ('moogaloop.swf' in u) or ('play_redirect_hls' in u)

Try / catch

try:
    ydl.extract_info(url)
except ExtractorError as e:
    if e.expected and 'embeds this video' in str(e):
        resolve_containing_page_and_retry(url)  # swap in the embedding page's URL
    else:
        raise

Prevention

When it happens

Trigger: Passing a player.vimeo.com/video/<id> URL (or moogaloop/play_redirect_hls variant) for a video whose privacy settings restrict playback to specific embed domains; the 403 body matches the marker string.

Common situations: Users copy the iframe src from devtools instead of the containing page; course/event sites that domain-lock their player; videos with 'hide from Vimeo' + domain-whitelist privacy.

Related errors


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