encode/httpx · error · TypeError

Invalid type for url. Expected str or httpx.URL, got {type(

Error message

Invalid type for url.  Expected str or httpx.URL, got {type(url)}: {url!r}

What it means

Raised by URL.__init__ when the first positional 'url' argument is neither a str nor an httpx.URL instance. The constructor only accepts those two types; anything else (int, dict, list, yarl.URL, urllib.parse.ParseResult, etc.) is rejected as TypeError before parsing.

Source

Thrown at httpx/_urls.py:121

                    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):
            self._uri_reference = urlparse(url, **kwargs)
        elif isinstance(url, URL):
            self._uri_reference = url._uri_reference.copy_with(**kwargs)
        else:
            raise TypeError(
                "Invalid type for url.  Expected str or httpx.URL,"
                f" got {type(url)}: {url!r}"
            )

    @property
    def scheme(self) -> str:
        """
        The URL scheme, such as "http", "https".
        Always normalised to lowercase.
        """
        return self._uri_reference.scheme

    @property
    def raw_scheme(self) -> bytes:
        """
        The raw bytes representation of the URL scheme, such as b"http", b"https".
        Always normalised to lowercase.
        """

View on GitHub (pinned to b5addb64f0)

Solutions

  1. Coerce to str first: httpx.URL(str(value)).
  2. If you have a urllib.parse result, pass .geturl() or reconstruct as a string.
  3. For cross-library code, convert foreign URL types (yarl.URL) via str() before httpx.URL.
  4. Add an isinstance(url, (str, httpx.URL)) guard at the boundary.

Example fix

// before
from urllib.parse import urlparse
parsed = urlparse("https://example.com")
url = httpx.URL(parsed)  # TypeError: invalid type

// after
url = httpx.URL(parsed.geturl())
Defensive patterns

Strategy: type-guard

Validate before calling

import httpx

def to_url(url) -> httpx.URL:
    if isinstance(url, httpx.URL):
        return url
    if isinstance(url, str):
        return httpx.URL(url)
    # urllib.parse.ParseResult, yarl.URL, etc.
    return httpx.URL(str(url))

url = to_url(foreign_url_object)

Type guard

def is_url_like(value) -> bool:
    return isinstance(value, (str, httpx.URL))

Try / catch

try:
    url = httpx.URL(value)
except TypeError as e:
    if "Invalid type for url" in str(e):
        url = httpx.URL(str(value))
    else:
        raise

Prevention

When it happens

Trigger: httpx.URL(123), httpx.URL(None), httpx.URL(some_dict), httpx.URL(urllib.parse.urlparse('...')) (a ParseResult, not a str), or passing a yarl.URL by mistake.

Common situations: Inter-library confusion (yarl vs httpx.URL); passing the result of urlparse() directly; treating an int/None as a URL; building URLs from untyped config values.

Related errors


AI-assisted analysis of encode/httpx@b5addb64f0 (2026-08-04). Data as JSON: /data/errors/6f4387e03c06f0e7.json. Report an issue: GitHub.