psf/requests · error · InvalidURL
URL has an invalid label.
Error message
URL has an invalid label.
What it means
An `InvalidURL` raised in `prepare_url` when the hostname contains non-ASCII characters and IDNA encoding fails. Requests attempts to convert internationalized domain names to punycode via `_get_idna_encoded_host`; if the idna library raises (label too long, empty label, disallowed code points), the host cannot form a valid DNS name and the URL is rejected.
Source
Thrown at src/requests/models.py:532
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 += host
if port:
netloc += f":{port}"
# Bare domains aren't valid URLs.
if not path:
path = "/"
if isinstance(params, (str, bytes)):
params = to_native_string(params)
View on GitHub ↗ (pinned to 414f0513c3)
Solutions
- Inspect the hostname bytes: `print(ascii(urlparse(url).hostname))` to reveal hidden unicode characters, then strip or fix them.
- Sanitize input URLs (strip whitespace and zero-width/invisible characters) before requesting.
- If the domain is genuinely internationalized, pre-encode it yourself with `idna.encode(host)` to get a specific error explaining which label is invalid.
Example fix
# before (host contains a zero-width space)
requests.get('https://exam\u200bple.com')
# after
url = raw_url.replace('\u200b', '').strip()
requests.get(url) Defensive patterns
Strategy: validation
Validate before calling
from urllib.parse import urlparse
host = urlparse(url).hostname or ""
# each DNS label must be 1-63 chars
if not all(0 < len(label) <= 63 for label in host.split(".")):
raise ValueError(f"invalid hostname in {url!r}")
host.encode("idna") # raises UnicodeError for invalid IDNA labels Try / catch
from requests.exceptions import InvalidURL
try:
resp = requests.get(url)
except InvalidURL as e:
if "invalid label" in str(e).lower():
... # non-ASCII host failed IDNA encoding
raise Prevention
- Pre-encode internationalized hostnames with hostname.encode('idna') to surface bad labels early
- Reject hostnames with empty labels (leading/trailing/double dots) or labels over 63 chars
- Sanitize user-entered hostnames before building URLs
When it happens
Trigger: Requesting a URL whose host has a non-ASCII label that violates IDNA rules — e.g. a label over 63 characters, an empty label ('http://exämple..com'), disallowed characters or misplaced combining marks. Only reached when `unicode_is_ascii(host)` is False (src/requests/models.py:528).
Common situations: URLs scraped from web pages or user input containing lookalike/unicode characters; invisible characters (zero-width space, non-breaking space) pasted into a hostname from a document or chat; malformed internationalized domains in datasets.
Related errors
- Invalid URL {url!r}: No scheme supplied. Perhaps you meant h
- 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/3ff3be6e08ec3d99.json.
Report an issue: GitHub ↗.