ytdl-org/youtube-dl · warning · ExtractorError
Invalid URL: %r . Call youtube-dl like this: youtube-dl -v
Error message
Invalid URL: %r . Call youtube-dl like this: youtube-dl -v "https://www.youtube.com/watch?v=BaW_jenozKc"
What it means
Raised by the generic extractor when the URL has no scheme, default_search is 'auto_warning', and the input is literally 'url' or 'URL'. youtube-dl interprets a bare 'url' as a likely mistyped placeholder and refuses to fall back to a YouTube search for it. Marked expected=True.
Source
Thrown at youtube_dl/extractor/generic.py:2546
def _real_extract(self, url):
if url.startswith('//'):
return self.url_result(self.http_scheme() + url)
parsed_url = compat_urlparse.urlparse(url)
if not parsed_url.scheme:
default_search = self._downloader.params.get('default_search')
if default_search is None:
default_search = 'fixup_error'
if default_search in ('auto', 'auto_warning', 'fixup_error'):
if re.match(r'^[^\s/]+\.[^\s/]+/', url):
self._downloader.report_warning('The url doesn\'t specify the protocol, trying with http')
return self.url_result('http://' + url)
elif default_search != 'fixup_error':
if default_search == 'auto_warning':
if re.match(r'^(?:url|URL)$', url):
raise ExtractorError(
'Invalid URL: %r . Call youtube-dl like this: youtube-dl -v "https://www.youtube.com/watch?v=BaW_jenozKc" ' % url,
expected=True)
else:
self._downloader.report_warning(
'Falling back to youtube search for %s . Set --default-search "auto" to suppress this warning.' % url)
return self.url_result('ytsearch:' + url)
if default_search in ('error', 'fixup_error'):
raise ExtractorError(
'%r is not a valid URL. '
'Set --default-search "ytsearch" (or run youtube-dl "ytsearch:%s" ) to search YouTube'
% (url, url), expected=True)
else:
if ':' not in default_search:
default_search += ':'
return self.url_result(default_search + url)
url, smuggled_data = unsmuggle_url(url)View on GitHub (pinned to 956b8c5855)
Solutions
- Pass a real URL including the scheme: youtube-dl "https://www.youtube.com/watch?v=BaW_jenozKc"
- Fix the script/variable that substituted the literal string 'url'
- Set --default-search explicitly if you really want search behavior
Example fix
# before youtube-dl url # after youtube-dl "https://www.youtube.com/watch?v=BaW_jenozKc"
Defensive patterns
Strategy: validation
Validate before calling
import re
def valid_cli_url(u):
return bool(re.match(r'^[a-zA-Z][a-zA-Z0-9+.-]*://', u)) or bool(re.match(r'^[^\s/]+\.[^\s/]+/', u))
if not valid_cli_url(arg) or arg.lower() in ('url',):
raise SystemExit(f'not a real URL: {arg!r}') Type guard
def is_placeholder_url(u):
return u.strip().lower() in ('url', 'http://url', 'https://url') Try / catch
try:
ydl.download([arg])
except DownloadError:
# expected=True error; correct the argument, no need to log as a bug
print('pass a full URL, not the literal placeholder "url"') Prevention
- Quote URLs in shell commands
- Fail fast in scripts on unset URL variables: : "${URL:?URL not set}"
- Never template example commands without replacing placeholders
When it happens
Trigger: Invoking the CLI with the literal argument url or URL (e.g. youtube-dl $(cat cmd.txt) where the file contained the word 'url') while --default-search is auto_warning, and the input matches neither the domain regex ^[^\s/]+\.[^\s/]+/ nor a scheme.
Common situations: Shell scripts templating a URL variable that expanded to the placeholder 'url', copy-paste of an example command without substitution, or CI configs passing an unset variable defaulting to 'url'.
Related errors
- %r is not a valid URL. Set --default-search "ytsearch" (or r
- Unsupported URL: %s
- Invalid URL: %s
- Incomplete YouTube ID %s. URL %s looks truncated.
- error running
AI-assisted analysis of ytdl-org/youtube-dl@956b8c5855 (2026-08-14).
Data as JSON: /api/errors/8fac498d662f3519.
Report an issue: GitHub.