Working with responses

HTTPX · Essentials · 9 min

Correctly checking status and decoding bodies is the core of every client call.

An httpx.Response exposes the body as:

  • r.content: raw bytes,
  • r.text: decoded string, using the charset from Content-Type and otherwise UTF-8 (configurable with default_encoding on the client),
  • r.json(): parsed JSON, raising json.JSONDecodeError on invalid content.

Status helpers make intent clear: r.is_success (2xx), r.is_redirect, r.is_client_error (4xx), r.is_server_error (5xx), r.is_error. httpx.codes holds named constants, so r.status_code == httpx.codes.NOT_FOUND reads better than a bare 404. r.reason_phrase gives the text, like "Not Found".

r.raise_for_status() raises httpx.HTTPStatusError for 4xx and 5xx responses and returns the response otherwise, so you can chain it:

data = client.get(url).raise_for_status().json()

The exception has .request and .response attributes for logging and branching.

Other useful attributes: r.headers (case-insensitive, multi-value aware), r.url (an httpx.URL object with .host, .path, .params), r.request (what was sent), r.elapsed, r.http_version and r.history for redirects that were followed.

Note that raise_for_status only raises for 4xx and 5xx. A 3xx redirect that was not followed comes back as a normal response with r.is_redirect true and the next hop prepared in r.next_request.

Example

import httpx

r = httpx.get("https://httpbin.org/json")
print(r.is_success, r.status_code == httpx.codes.OK)   # True True
print(type(r.content).__name__, type(r.text).__name__)  # bytes str
print(r.json()["slideshow"]["title"])    # Sample Slide Show
print(r.url.host, r.headers["content-type"])  # httpbin.org application/json

title = httpx.get("https://httpbin.org/json").raise_for_status().json()["slideshow"]["author"]
print(title)                             # Yours Truly

try:
    httpx.get("https://httpbin.org/status/418").raise_for_status()
except httpx.HTTPStatusError as e:
    print(e.response.status_code, e.response.is_client_error)  # 418 True

Remember

  • content is bytes, text is str, json() parses
  • is_success, is_client_error, is_server_error and httpx.codes clarify intent
  • raise_for_status() raises HTTPStatusError or returns the response for chaining

Watch out for

  • Calling r.json() on an error page without checking the status first.

Check yourself

  1. What does r.raise_for_status() return for a 200 response?

Sign in to answer, see the explanations, and get this lesson back as a quick review later.

Official docs: www.python-httpx.org/quickstart/#response-status-codes