encode/httpx · error · InvalidURL
Invalid URL component '{key}'
Error message
Invalid URL component '{key}' What it means
Raised during the kwargs validation loop when a component value fails to fully match its COMPONENT_REGEX. Each component has its own grammar (e.g. path must match '[^?#]*', scheme must match '([a-zA-Z][a-zA-Z0-9+.-]*)?'); a mismatch means the supplied value cannot be a valid component at all.
Source
Thrown at httpx/_urlparse.py:286
if len(value) > MAX_URL_LENGTH:
raise InvalidURL(f"URL component '{key}' too long")
# If a component includes any ASCII control characters including \t, \r, \n,
# then treat it as invalid.
if any(char.isascii() and not char.isprintable() for char in value):
char = next(
char for char in value if char.isascii() and not char.isprintable()
)
idx = value.find(char)
error = (
f"Invalid non-printable ASCII character in URL {key} component, "
f"{char!r} at position {idx}."
)
raise InvalidURL(error)
# Ensure that keyword arguments match as a valid regex.
if not COMPONENT_REGEX[key].fullmatch(value):
raise InvalidURL(f"Invalid URL component '{key}'")
# The URL_REGEX will always match, but may have empty components.
url_match = URL_REGEX.match(url)
assert url_match is not None
url_dict = url_match.groupdict()
# * 'scheme', 'authority', and 'path' may be empty strings.
# * 'query' may be 'None', indicating no trailing "?" portion.
# Any string including the empty string, indicates a trailing "?".
# * 'fragment' may be 'None', indicating no trailing "#" portion.
# Any string including the empty string, indicates a trailing "#".
scheme = kwargs.get("scheme", url_dict["scheme"]) or ""
authority = kwargs.get("authority", url_dict["authority"]) or ""
path = kwargs.get("path", url_dict["path"]) or ""
query = kwargs.get("query", url_dict["query"])
frag = kwargs.get("fragment", url_dict["fragment"])
# The AUTHORITY_REGEX will always match, but may have empty components.View on GitHub (pinned to b5addb64f0)
Solutions
- Split mixed input into the correct components (use raw_path= to pass '/p?x=1' rather than path=).
- Validate the component against its expected grammar before constructing the URL.
- For scheme, ensure it starts with a letter and contains only [a-zA-Z0-9+.-].
- Use httpx.URL('full-string') and let httpx parse, rather than hand-building components.
Example fix
// before url = httpx.URL(scheme="https", host="api.example.com", path="/items?page=1") # Invalid URL component 'path' // after url = httpx.URL(scheme="https", host="api.example.com", raw_path="/items?page=1")
Defensive patterns
Strategy: validation
Validate before calling
import re
COMPONENT_REGEX = {
"scheme": re.compile(r"([a-zA-Z][a-zA-Z0-9+.-]*)?"),
"path": re.compile(r"[^?#]*"),
"query": re.compile(r"[^#]*"),
# ... etc
}
def validate_component(key: str, value: str) -> str:
if not COMPONENT_REGEX[key].fullmatch(value):
raise ValueError(f"Invalid URL component {key!r}")
return value Type guard
import re
def path_is_valid(path: str) -> bool:
return re.fullmatch(r"[^?#]*", path) is not None Try / catch
from httpx import InvalidURL
try:
url = httpx.URL(scheme="https", host="x", raw_path=mixed)
except InvalidURL as e:
if "Invalid URL component" in str(e):
# split raw_path into path+query yourself, or use full-string URL
url = httpx.URL(f"https://x{mixed}")
else:
raise Prevention
- Use raw_path= (not path=) when the value may include a '?'.
- Validate scheme starts with a letter and uses only [a-zA-Z0-9+.-].
- Where possible, pass a complete URL string instead of hand-built components.
When it happens
Trigger: httpx.URL(scheme='123bad') (scheme must start with a letter); httpx.URL(path='/a?b') (path must not contain '?'); httpx.URL(fragment='a#b') (fragment must not contain '#' as a sub-token... actually fragment regex is '.*' so any char passes, but other components are stricter).
Common situations: Programmatically building components without sanitization; passing a path that already includes a querystring instead of using raw_path/query; user input that breaks the scheme grammar.
Related errors
- URL too long
- Invalid port: {port!r}
- Proxy protocol must be either 'http', 'https', 'socks5', or
- Invalid non-printable ASCII character in URL, {char!r} at po
- URL component '{key}' too long
AI-assisted analysis of encode/httpx@b5addb64f0 (2026-08-04).
Data as JSON: /data/errors/815e262992b8b8d0.json.
Report an issue: GitHub.