ytdl-org/youtube-dl · error · ExtractorError
Invalid URL: %s
Error message
Invalid URL: %s
What it means
Raised by the static YoutubeIE.extract_id when the given URL does not match the (verbose) _VALID_URL regex for YouTube video URLs. It is a plain ExtractorError (not expected), signaling the caller passed something that is not a recognizable youtube.com/watch (or equivalent) URL — typically a truncated URL mangled by the shell.
Source
Thrown at youtube_dl/extractor/youtube.py:2254
# Wordpress "YouTube Video Importer" plugin
matches = re.findall(r'''(?x)<div[^>]+
class=(?P<q1>[\'"])[^\'"]*\byvii_single_video_player\b[^\'"]*(?P=q1)[^>]+
data-video_id=(?P<q2>[\'"])([^\'"]+)(?P=q2)''', webpage)
entries.extend(m[-1] for m in matches)
return entries
@staticmethod
def _extract_url(webpage):
urls = YoutubeIE._extract_urls(webpage)
return urls[0] if urls else None
@classmethod
def extract_id(cls, url):
mobj = re.match(cls._VALID_URL, url, re.VERBOSE)
if mobj is None:
raise ExtractorError('Invalid URL: %s' % url)
return mobj.group(2)
@staticmethod
def _extract_chapters_from_json(data, video_id, duration):
chapters_list = try_get(
data,
lambda x: x['playerOverlays']
['playerOverlayRenderer']
['decoratedPlayerBarRenderer']
['decoratedPlayerBarRenderer']
['playerBar']
['chapteredPlayerBarRenderer']
['chapters'],
list)
if not chapters_list:
return
def chapter_time(chapter):View on GitHub (pinned to 956b8c5855)
Solutions
- Quote the URL: youtube-dl "https://www.youtube.com/watch?feature=foo&v=BaW_jenozKc", or pass just the id: youtube-dl BaW_jenozKc.
- In code, validate with YoutubeIE.suitable(url) (or re.match(_VALID_URL, url, re.VERBOSE)) before calling extract_id.
- Update youtube-dl so newly added YouTube hosts/URL shapes are recognized.
- Check for stray whitespace/newlines in programmatically supplied URLs.
Example fix
// before
video_id = YoutubeIE.extract_id('https://www.youtube.com/watch?feature=foo')
// after
video_id = YoutubeIE.extract_id('https://www.youtube.com/watch?feature=foo&v=BaW_jenozKc') # quoted in shell: "...&v=BaW_jenozKc" Defensive patterns
Strategy: validation
Validate before calling
import re
def is_valid_youtube_url(url: str) -> bool:
return re.match(YoutubeIE._VALID_URL, url, re.VERBOSE) is not None
assert is_valid_youtube_url(url), 'URL lacks the video id (quote it in shells!)' Type guard
def extract_video_id_safe(url: str):
m = re.match(YoutubeIE._VALID_URL, url, re.VERBOSE)
return m.group(2) if m else None # None instead of raising Try / catch
try:
vid = YoutubeIE.extract_id(url)
except ExtractorError as e:
if 'Invalid URL' in str(e):
raise ValueError('Not a YouTube video URL: %r — was it truncated at & ?' % url)
raise Prevention
- Always quote URLs containing & in shells.
- Prefer bare 11-character ids as input to scripts and APIs.
When it happens
Trigger: Calling YoutubeIE.extract_id('https://www.youtube.com/watch?feature=foo') — an URL whose query string was cut at '&' by an unquoted shell — or any string that does not contain a capturable 11-char video id group.
Common situations: Unquoted URLs in shells where & backgrounds the command and truncates the URL; programmatic callers passing already-stripped or malformed URLs; URLs from other regions/hosts not covered by _VALID_URL in the installed version.
Related errors
- Cannot identify player %r
- Did you forget to quote the URL? Remember that & is a meta c
- Incomplete YouTube ID %s. URL %s looks truncated.
- error
- Invalid URL: %r . Call youtube-dl like this: youtube-dl -v
AI-assisted analysis of ytdl-org/youtube-dl@956b8c5855 (2026-08-14).
Data as JSON: /api/errors/58fa5cf429571b2a.
Report an issue: GitHub.