ytdl-org/youtube-dl · error · ExtractorError
%s: %s
Error message
%s: %s
What it means
This is the generic failure template of _download_webpage internals: when a webpage (or API) download raises a network/HTTP error that is not handled more specifically, youtube-dl builds '<errnote>: <original error>' and, if fatal=True, raises ExtractorError with the underlying exception as cause. 'errnote' defaults to 'Unable to download webpage' but extractors override it (e.g. 'Unable to download API JSON').
Source
Thrown at youtube_dl/extractor/common.py:700
return self._downloader.urlopen(url_or_request)
except tuple(exceptions) as err:
if isinstance(err, compat_urllib_error.HTTPError):
if self.__can_accept_status_code(err, expected_status):
# Retain reference to error to prevent file object from
# being closed before it can be read. Works around the
# effects of <https://bugs.python.org/issue15002>
# introduced in Python 3.4.1.
err.fp._error = err
return err.fp
if errnote is False:
return False
if errnote is None:
errnote = 'Unable to download webpage'
errmsg = '%s: %s' % (errnote, error_to_compat_str(err))
if fatal:
raise ExtractorError(errmsg, sys.exc_info()[2], cause=err)
else:
self.report_warning(errmsg)
return False
def _download_webpage_handle(self, url_or_request, video_id, note=None, errnote=None, fatal=True, encoding=None, data=None, headers={}, query={}, expected_status=None):
"""
Return a tuple (page content as string, URL handle).
See _download_webpage docstring for arguments specification.
"""
# Strip hashes from the URL (#1038)
if isinstance(url_or_request, (compat_str, str)):
url_or_request = url_or_request.partition('#')[0]
urlh = self._request_webpage(url_or_request, video_id, note, errnote, fatal, data=data, headers=headers, query=query, expected_status=expected_status)
if urlh is False:
assert not fatal
return FalseView on GitHub (pinned to 956b8c5855)
Solutions
- Read the '<original error>' part of the message — it names the real cause (HTTP Error 404, connection reset, etc.).
- Set a browser-like User-Agent (--user-agent) and/or pass cookies (--cookies) to pass bot checks.
- Check the URL in a browser; 404s mean the link is dead.
- For flaky networks, increase --retries/--socket-timeout or use --force-ipv4.
Example fix
# before
ydl.extract(url) # ERROR: Unable to download webpage: HTTP Error 403: Forbidden
# after
from youtube_dl import YoutubeDL
with YoutubeDL({'http_headers': {'User-Agent': 'Mozilla/5.0'}}) as ydl:
ydl.extract(url) Defensive patterns
Strategy: try-catch
Validate before calling
import urllib.request
def url_reachable(url, headers):
try:
req = urllib.request.Request(url, headers=headers)
with urllib.request.urlopen(req, timeout=15) as r:
return r.status == 200
except Exception:
return False Try / catch
from youtube_dl.utils import ExtractorError, DownloadError
try:
ydl.extract_info(url)
except ExtractorError as e:
msg = str(e)
if 'HTTP Error 403' in msg:
retry_with_browser_ua(url) # bot block
elif 'HTTP Error 404' in msg:
mark_dead(url) # permanent
else:
raise Prevention
- Always parse the '<original error>' suffix to pick the right remedy.
- Send a browser User-Agent and cookies for sites with bot protection.
- Pre-validate URLs (status 200) in batch pipelines to fail fast.
When it happens
Trigger: Any URLError/HTTPError/socket failure while fetching a URL the extractor requested: DNS failure, connection refused, TLS errors, 403/404/500 responses (unless expected_status was set), timeouts. fatal=False converts it to a warning and returns False instead.
Common situations: Dead links (404), bot-blocking WAFs returning 403 to youtube-dl's default User-Agent, corporate proxies/DNS issues, TLS interception problems, transient 5xx.
Related errors
- No such Python version: %s
- A network error has occurred.
- Access to this webpage has been blocked by Websense filterin
- No API host found
- %s: %s
AI-assisted analysis of ytdl-org/youtube-dl@956b8c5855 (2026-08-14).
Data as JSON: /api/errors/9d50c4426ad09782.
Report an issue: GitHub.