The Response object

Requests · Essentials · 9 min

Getting data out of a response correctly, including encoding and JSON errors, is half of every HTTP task.

A Response gives you the body in three forms:

  • r.content: raw bytes. Use it for images, archives and any binary data.
  • r.text: the body decoded to str using r.encoding, which Requests takes from the Content-Type header's charset. If the header has no charset, Requests guesses (for text/* it defaults to ISO-8859-1 per the old HTTP spec). Set r.encoding = "utf-8" before reading r.text if you know better.
  • r.json(): parses the body as JSON. If the body is not valid JSON (an HTML error page, an empty 204 response), it raises requests.exceptions.JSONDecodeError.

Headers live in r.headers, a case-insensitive dict: r.headers["content-type"] and r.headers["Content-Type"] are the same entry.

Other useful attributes:

  • r.url: the final URL after redirects. r.history lists the redirect responses that led there. Requests follows redirects automatically for all methods except HEAD; pass allow_redirects=False to stop that.
  • r.elapsed: a timedelta from sending the request until the response headers arrived.
  • r.request: the PreparedRequest that was actually sent, with its final URL, headers and body, which is great for debugging.
  • r.reason: the status text, like "Not Found".
  • r.cookies: cookies the server set.

Check the status before trusting the body: an error page parsed with r.json() is a common source of confusing exceptions.

Example

import requests

r = requests.get("https://httpbin.org/redirect/2", timeout=10)
print(r.status_code, r.url)          # 200 https://httpbin.org/get
print([h.status_code for h in r.history])  # [302, 302]
print(r.headers["content-type"])     # application/json  (case-insensitive)
print(type(r.content).__name__, type(r.text).__name__)  # bytes str
print(r.request.method, r.request.url)   # GET https://httpbin.org/get

html = requests.get("https://httpbin.org/html", timeout=10)
try:
    html.json()
except requests.exceptions.JSONDecodeError:
    print("not JSON")                # not JSON

r2 = requests.get("https://httpbin.org/redirect/1", allow_redirects=False, timeout=10)
print(r2.status_code, r2.headers["Location"])  # 302 /get

Remember

  • content is bytes, text is decoded str, json() parses JSON
  • headers is case-insensitive; url and history show redirects
  • r.request shows exactly what was sent

Watch out for

  • Reading r.text for binary data such as images; use r.content.

Check yourself

  1. Which attribute should you use to save a downloaded PNG to disk?

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

Official docs: requests.readthedocs.io/en/latest/user/quickstart/#response-content