psf/requests · error · InvalidURL
Invalid URL {url!r}: No host supplied
Error message
Invalid URL {url!r}: No host supplied What it means
An `InvalidURL` exception raised in `prepare_url` when the URL parses successfully and has a scheme, but the host component is empty. Without a host there is nothing to connect to, so the request cannot proceed. This catches malformed URLs like 'http://' or 'http:///path'.
Source
Thrown at src/requests/models.py:522
# 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:
raise InvalidURL("URL has an invalid label.")
elif host.startswith(("*", ".")):
raise InvalidURL("URL has an invalid label.")
# Carefully reconstruct the network location
netloc = auth or ""
if netloc:
netloc += "@"
netloc += hostView on GitHub ↗ (pinned to 414f0513c3)
Solutions
- Trace where the URL was built and ensure the hostname variable is non-empty — most often a missing env var or config value.
- Validate config at startup: raise a clear error if the host setting is empty instead of letting it reach requests.
- Print/log the exact URL being requested (it appears in the exception message via {url!r}) to spot the empty authority.
Example fix
# before
host = os.environ.get('API_HOST', '')
requests.get(f'http://{host}/health')
# after
host = os.environ['API_HOST'] # KeyError early if unset
if not host:
raise RuntimeError('API_HOST is empty')
requests.get(f'http://{host}/health') Defensive patterns
Strategy: validation
Validate before calling
from urllib.parse import urlparse
parsed = urlparse(url)
if not parsed.netloc:
raise ValueError(f"URL {url!r} has no host") Try / catch
from requests.exceptions import InvalidURL
try:
resp = requests.get(url)
except InvalidURL:
... # e.g. 'http://' or 'http:///path' — reject or re-prompt for a real host
raise Prevention
- Check urlparse(url).netloc is non-empty before making the request
- Beware string concatenation bugs that produce 'http://' + '' when a host variable is empty
- Catch requests.exceptions.InvalidURL (subclass of ValueError) at the call site
When it happens
Trigger: `requests.get('http://')`, `requests.get('http:///path')`, `requests.get('https://:8080/x')` — any URL where `parse_url` returns an empty host. Commonly produced by string formatting where the hostname variable is empty: `f'http://{host}/api'` with `host=''`.
Common situations: An unset environment variable or config key interpolated into a URL template (e.g. `API_HOST` empty in a container/CI environment), yielding 'http:///endpoint'; URL builders that accept optional host; accidental double slashes replacing the authority.
Related errors
- Invalid percent-escape sequence: '{h}'
- Invalid URL {url!r}: No scheme supplied. Perhaps you meant h
- URL has an invalid label.
- No connection adapters were found for {url!r}
- Files must be provided.
AI-assisted analysis of psf/requests@414f0513c3 (2026-07-31).
Data as JSON: /data/errors/e8fe13b5afb24b50.json.
Report an issue: GitHub ↗.