Params, headers and request bodies

HTTPX · Essentials · 10 min

Every API expects data in a specific format, and HTTPX separates the options more strictly than Requests.

Request options in HTTPX:

  • params=: query parameters as a dict (list values repeat the key) or list of tuples. They are encoded and merged into the URL.
  • headers=: a dict of headers.
  • json=: any JSON-serialisable object, sent with Content-Type: application/json.
  • data=: a dict sent as an HTML form (application/x-www-form-urlencoded), or, together with files=, as multipart.
  • files=: uploads, as {"field": file_obj} or {"field": (filename, file_obj, content_type)}.
  • content=: raw bytes or str (or an iterator for streaming) sent as is. Set your own Content-Type.
  • cookies=: cookies for this request (setting them per request is deprecated in favour of client cookies).

A difference from Requests: raw bytes and strings go in content=, not data=. Passing bytes to data= is deprecated and warns.

Also, httpx.get and httpx.delete do not accept a body argument, because bodies on GET and DELETE are unusual. If an API really requires a DELETE with JSON, use the generic form: httpx.request("DELETE", url, json={...}) or client.request(...).

You can build requests explicitly too: client.build_request("POST", url, json=...) returns an httpx.Request you can inspect, modify and send with client.send(request).

To check what was sent, look at r.request.headers, r.request.url and r.request.content.

Example

import httpx

base = "https://httpbin.org"
r = httpx.get(f"{base}/get", params={"tag": ["a", "b"], "n": 3},
              headers={"X-Client": "demo"})
print(r.request.url.query)            # b'tag=a&tag=b&n=3'
print(r.json()["headers"]["X-Client"])  # demo

r = httpx.post(f"{base}/post", data={"name": "Ada"},
               files={"doc": ("a.txt", b"hello", "text/plain")})
print(r.json()["form"], r.json()["files"])  # {'name': 'Ada'} {'doc': 'hello'}

r = httpx.post(f"{base}/post", content=b"<x/>", headers={"Content-Type": "application/xml"})
print(r.json()["data"])               # <x/>

r = httpx.request("DELETE", f"{base}/delete", json={"id": 7})
print(r.json()["json"])               # {'id': 7}

Remember

  • params, headers, json, data, files: same ideas as Requests
  • Raw bytes or text go in content=, not data=
  • Use request('DELETE', ..., json=...) for bodies on DELETE

Watch out for

  • Passing bytes to data= as in Requests; HTTPX expects content=.

Check yourself

  1. How do you send a raw XML string as the request body in HTTPX?

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

Official docs: www.python-httpx.org/quickstart/#sending-form-encoded-data