psf/requests · error · MissingSchema
Invalid URL {url!r}: No scheme supplied. Perhaps you meant h
Error message
Invalid URL {url!r}: No scheme supplied. Perhaps you meant https://{url}? What it means
A `MissingSchema` exception raised by `PreparedRequest.prepare_url` when `urllib3.util.parse_url` finds no scheme component in the URL. Requests needs the scheme to pick a connection adapter (http:// vs https://), so a bare host like 'example.com/path' cannot be dispatched. The message suggests the likely fix of prepending https://.
Source
Thrown at src/requests/models.py:516
# 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:
raise InvalidURL("URL has an invalid label.")
elif host.startswith(("*", ".")):
raise InvalidURL("URL has an invalid label.")View on GitHub ↗ (pinned to 414f0513c3)
Solutions
- Prepend an explicit scheme: `requests.get('https://' + url)` (as the error message suggests).
- Normalize inputs at the boundary: `if '://' not in url: url = 'https://' + url` before making requests.
- If using a base URL from config, validate it at startup (e.g. with `urllib.parse.urlparse(url).scheme`) and fail fast with a clear config error.
Example fix
# before
requests.get('api.example.com/v1/users')
# after
requests.get('https://api.example.com/v1/users') Defensive patterns
Strategy: validation
Validate before calling
from urllib.parse import urlparse
parsed = urlparse(url)
if not parsed.scheme:
url = "https://" + url Try / catch
from requests.exceptions import MissingSchema
try:
resp = requests.get(url)
except MissingSchema:
resp = requests.get("https://" + url) Prevention
- Normalize user-supplied URLs by prepending https:// when urlparse shows no scheme
- Catch requests.exceptions.MissingSchema specifically, not bare ValueError
- Validate URLs at input boundaries (form/CLI parsing), not at request time
When it happens
Trigger: `requests.get('example.com')`, `requests.get('//example.com/x')`, or a URL built by joining strings where the scheme part ended up empty. Note URLs containing ':' that don't start with 'http' (e.g. mailto:) bypass this check entirely at src/requests/models.py:505.
Common situations: URLs read from config files, environment variables, CSVs, or user input where people naturally omit the scheme; base-URL concatenation bugs (`base + path` where base is empty or lost its prefix); copy-pasting a domain from a browser bar that hides the scheme.
Related errors
- URL has an invalid label.
- Files must be provided.
- Data must not be a string.
- Invalid URL {url!r}: No host supplied
- Invalid percent-escape sequence: '{h}'
AI-assisted analysis of psf/requests@414f0513c3 (2026-07-31).
Data as JSON: /data/errors/11675c841b2d515d.json.
Report an issue: GitHub ↗.