encode/httpx · error · TypeError
{key!r} is an invalid keyword argument for URL()
Error message
{key!r} is an invalid keyword argument for URL() What it means
Raised by URL.__init__ when a keyword argument name is not in the allowed set {scheme, username, password, userinfo, host, port, netloc, path, query, raw_path, fragment, params}. This is a strict constructor: any other kwarg is a programmer error and rejected as TypeError before any parsing.
Source
Thrown at httpx/_urls.py:98
"scheme": str,
"username": str,
"password": str,
"userinfo": bytes,
"host": str,
"port": int,
"netloc": bytes,
"path": str,
"query": bytes,
"raw_path": bytes,
"fragment": str,
"params": object,
}
# Perform type checking for all supported keyword arguments.
for key, value in kwargs.items():
if key not in allowed:
message = f"{key!r} is an invalid keyword argument for URL()"
raise TypeError(message)
if value is not None and not isinstance(value, allowed[key]):
expected = allowed[key].__name__
seen = type(value).__name__
message = f"Argument {key!r} must be {expected} but got {seen}"
raise TypeError(message)
if isinstance(value, bytes):
kwargs[key] = value.decode("ascii")
if "params" in kwargs:
# Replace any "params" keyword with the raw "query" instead.
#
# Ensure that empty params use `kwargs["query"] = None` rather
# than `kwargs["query"] = ""`, so that generated URLs do not
# include an empty trailing "?".
params = kwargs.pop("params")
kwargs["query"] = None if not params else str(QueryParams(params))
if isinstance(url, str):View on GitHub (pinned to b5addb64f0)
Solutions
- Check the allowed keys list and remove unsupported kwargs before construction.
- Pass request-level options (timeout, headers) to client.request()/client.get(), not to URL().
- Filter kwargs through an allowlist when spreading a dynamic dict.
- Use an IDE/linter to catch unknown kwargs at authoring time.
Example fix
// before
url = httpx.URL("https://example.com", timeout=5.0) # TypeError: invalid keyword
// after
url = httpx.URL("https://example.com")
client.get(url, timeout=5.0) Defensive patterns
Strategy: type-guard
Validate before calling
ALLOWED_URL_KWARGS = {
"scheme", "username", "password", "userinfo", "host", "port",
"netloc", "path", "query", "raw_path", "fragment", "params",
}
def filtered_url_kwargs(kwargs: dict) -> dict:
bad = set(kwargs) - ALLOWED_URL_KWARGS
if bad:
raise TypeError(f"Unsupported URL kwargs: {sorted(bad)}")
return kwargs
url = httpx.URL(base, **filtered_url_kwargs(user_kwargs)) Type guard
def are_valid_url_kwargs(kwargs: dict) -> bool:
allowed = {
"scheme", "username", "password", "userinfo", "host", "port",
"netloc", "path", "query", "raw_path", "fragment", "params",
}
return set(kwargs).issubset(allowed) Try / catch
try:
url = httpx.URL(base, **kwargs)
except TypeError as e:
if "invalid keyword argument for URL()" in str(e):
raise TypeError(f"Bad URL kwarg. Allowed: scheme/username/password/host/...") from e
raise Prevention
- Never spread unfiltered dicts into httpx.URL().
- Pass request options (timeout/headers/auth) to the request call, not URL().
- Use static typing/linters to catch unknown kwargs at authoring time.
When it happens
Trigger: httpx.URL('https://x', timeout=10), httpx.URL(method='GET'), httpx.URL(headers=...), or any typo like httpx.URL('https://x', passwrod='x').
Common situations: Confusing URL constructor kwargs with Client kwargs (timeout, headers, auth); spelling mistakes; passing through an unvalidated dict as **kwargs.
Related errors
- Invalid type for url. Expected str or httpx.URL, got {type(
- Argument {key!r} must be {expected} but got {seen}
- URL too long
- 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/cdc0614f164b3c00.json.
Report an issue: GitHub.