psf/requests · error · InvalidURL
{e.args}
Error message
{e.args} What it means
Raised by PreparedRequest.prepare_url when the underlying url_parse raises LocationParseError (from urllib3's src/urllib3/util/url.py). The message is reconstructed from the original error's args so the caller sees the precise parse failure (e.g. which character broke parsing). This wraps a low-level parse exception in requests' own InvalidURL for a consistent exception hierarchy.
Source
Thrown at src/requests/models.py:513
url = url.decode("utf8")
else:
url = str(url)
# Remove leading whitespaces from url
url = url.lstrip()
# Don't do any URL preparation for non-HTTP schemes like `mailto`,
# `data` etc to work around exceptions from `url_parse`, which
# handles RFC 3986 only.
if ":" in url and not url.lower().startswith("http"):
self.url = url
return
# Support for unicode domain names and paths.
try:
scheme, auth, host, port, path, query, fragment = parse_url(url)
except LocationParseError as e:
raise InvalidURL(*e.args)
if not scheme:
raise MissingSchema(
f"Invalid URL {url!r}: No scheme supplied. "
f"Perhaps you meant https://{url}?"
)
if not host:
raise InvalidURL(f"Invalid URL {url!r}: No host supplied")
# In general, we want to try IDNA encoding the hostname if the string contains
# non-ASCII characters. This allows users to automatically get the correct IDNA
# behaviour. For strings containing only ASCII characters, we need to also verify
# it doesn't start with a wildcard (*), before allowing the unencoded hostname.
if not unicode_is_ascii(host):
try:
host = self._get_idna_encoded_host(host)
except UnicodeError:View on GitHub (pinned to 8068356288)
Solutions
- Validate or sanitize the URL before passing it to requests (use urllib.parse.urlparse and check .scheme/.netloc are non-empty).
- Strip whitespace and control characters from URL components: url.strip().
- URL-encode path/query segments with urllib.parse.quote before assembly.
Example fix
// before
requests.get(user_input)
// after
from urllib.parse import urlparse
p = urlparse(user_input.strip())
if not p.scheme or not p.netloc:
raise ValueError(f'bad url: {user_input!r}')
requests.get(p.geturl()) Defensive patterns
Strategy: validation
Validate before calling
from urllib.parse import urlparse
def is_parseable_url(url: str) -> bool:
try:
p = urlparse(url)
return bool(p.scheme) and bool(p.netloc)
except ValueError:
return False Type guard
from urllib.parse import urlparse
def is_well_formed_url(url: str) -> bool:
if not isinstance(url, str) or not url.strip():
return False
p = urlparse(url.strip())
return bool(p.scheme in ('http', 'https')) and bool(p.netloc) Try / catch
from requests.exceptions import InvalidURL
try:
resp = requests.get(url)
except InvalidURL as e:
# log and reject the input
raise Prevention
- Validate URLs with urllib.parse.urlparse before sending.
- Strip whitespace and control characters from URL inputs.
- URL-encode path/query components with urllib.parse.quote.
When it happens
Trigger: Passing a malformed URL to requests.get/Session.request — e.g. unbalanced brackets in IPv6 ('http://[::1'), stray characters, spaces, or control characters; URLs with invalid percent-encoding; URLs constructed by string concatenation that produced garbage.
Common situations: Building URLs from untrusted/user input without validation; copy-paste artifacts (trailing spaces, smart quotes); templating bugs that emit 'http:///host' (triple slash) or missing protocol separators.
Related errors
- Invalid URL {url!r}: No host supplied
- Invalid URL {url!r}: No scheme supplied. Perhaps you meant h
- {e}
- URL has an invalid label.
- Please check proxy URL. It is malformed and could be missing
AI-assisted analysis of psf/requests@8068356288 (2026-08-11).
Data as JSON: /api/errors/3109338761042325.
Report an issue: GitHub.