encode/httpx · error · HTTPStatusError
{error_type} '{0.status_code} {0.reason_phrase}' for url '{0
Error message
{error_type} '{0.status_code} {0.reason_phrase}' for url '{0.url}'
Redirect location: '{0.headers[location]}'
For more information check: https://developer.mozilla.org/en-US/docs/Web/HTTP/Status/{0.status_code} What it means
The message format used by `raise_for_status` when the response has a redirect location (3xx with a `Location` header, as defined by `has_redirect_location`). It raises `HTTPStatusError` with the status code, reason, URL, and the redirect target, linking the MDN status reference. This is the 'redirect' variant of the two message branches in `raise_for_status`.
Source
Thrown at httpx/_models.py:829
"Redirect location: '{0.headers[location]}'\n"
"For more information check: https://developer.mozilla.org/en-US/docs/Web/HTTP/Status/{0.status_code}"
)
else:
message = (
"{error_type} '{0.status_code} {0.reason_phrase}' for url '{0.url}'\n"
"For more information check: https://developer.mozilla.org/en-US/docs/Web/HTTP/Status/{0.status_code}"
)
status_class = self.status_code // 100
error_types = {
1: "Informational response",
3: "Redirect response",
4: "Client error",
5: "Server error",
}
error_type = error_types.get(status_class, "Invalid status code")
message = message.format(self, error_type=error_type)
raise HTTPStatusError(message, request=request, response=self)
def json(self, **kwargs: typing.Any) -> typing.Any:
return jsonlib.loads(self.content, **kwargs)
@property
def cookies(self) -> Cookies:
if not hasattr(self, "_cookies"):
self._cookies = Cookies()
self._cookies.extract_cookies(self)
return self._cookies
@property
def links(self) -> dict[str | None, dict[str, str]]:
"""
Returns the parsed header links of the response, if any
"""
header = self.headers.get("link")
if header is None:View on GitHub (pinned to b5addb64f0)
Solutions
- Enable `follow_redirects=True` on the client or per-request if you want httpx to follow automatically.
- Inspect `response.headers['Location']` and `response.is_redirect` before calling `raise_for_status()` to handle redirects yourself.
- Wrap in `try/except httpx.HTTPStatusError as e:` and read `e.response.status_code` / `e.response.headers['Location']`.
- Verify the redirect target is the expected host to avoid open-redirect surprises.
Example fix
// before r = client.get(url, follow_redirects=False) r.raise_for_status() # HTTPStatusError on 302 // after r = client.get(url, follow_redirects=True) r.raise_for_status()
Defensive patterns
Strategy: try-catch
Validate before calling
if response.is_redirect and not response.is_success:
# handle redirect manually instead of raise_for_status()
loc = response.headers.get('Location') Type guard
import httpx
def is_unfollowed_redirect(resp: httpx.Response) -> bool:
return resp.has_redirect_location and not resp.is_success Try / catch
try:
response.raise_for_status()
except httpx.HTTPStatusError as e:
if e.response.has_redirect_location:
next_url = e.response.headers['Location']
# follow manually or surface to caller
else:
raise Prevention
- Set follow_redirects=True unless you intentionally inspect 3xx.
- Check response.is_redirect before calling raise_for_status().
- Validate the Location host against an allowlist to avoid open redirects.
When it happens
Trigger: Calling `response.raise_for_status()` on a 301/302/303/307/308 response whose `Location` header is present and `is_success` is False — typically because redirects were disabled (`follow_redirects=False`) or the redirect chain was halted.
Common situations: Passing `follow_redirects=False` to inspect a redirect manually; SSO/OAuth flows where you intentionally stop at the 302; debugging a redirect loop.
Related errors
- {error_type} '{0.status_code} {0.reason_phrase}' for url '{0
- Attempted to read or stream some content, but the content ha
- Cannot call `raise_for_status` as the request instance has n
AI-assisted analysis of encode/httpx@b5addb64f0 (2026-08-04).
Data as JSON: /data/errors/75dd8c8b76a71165.json.
Report an issue: GitHub.