Treq
Treq is a high-level HTTP client library for Python, inspired by the popular `requests` library but built upon Twisted's asynchronous networking framework. It simplifies making HTTP requests within Twisted applications by providing a familiar, easy-to-use API for various HTTP methods, JSON handling, and cookie management. The library is actively maintained, currently at version 25.5.0, with a regular release cadence to support new Python and Twisted versions.
Common errors
-
TypeError: mixing 'json' with 'files' or 'data' is not allowed
cause Attempting to send both a JSON payload and form data (or files) in a single HTTP request, which is a breaking change introduced in treq 24.9.0.fixChoose only one method for sending the request body: either `json={...}` for a JSON payload, or `data={...}` for form-encoded data, or `files={...}` for multipart file uploads. Do not combine them. -
twisted.internet.error.HostnameResolutionError: DNS lookup failed
cause The Twisted reactor (event loop) was not started or stopped prematurely, preventing network operations from completing.fixEnsure your application runs within the Twisted reactor. Use `twisted.internet.task.react(your_main_function)` to properly start and stop the reactor for your asynchronous code. -
UnicodeEncodeError: 'ascii' codec can't encode character...
cause Sending non-ASCII characters in URLs or query parameters with older versions of treq (prior to 20.4.0) that had encoding issues.fixUpgrade treq to version 20.4.0 or newer. If stuck on an older version, manually encode URL components using `urllib.parse.quote` or `hyperlink` before passing them to treq. -
AttributeError: 'bytes' object has no attribute 'decode'
cause Attempting to call `.decode()` on a response body that might already be a string (e.g., from `response.text()` or `response.json()`), or forgetting to await `response.text()`/`response.json()` and operating on a Deferred.fixEnsure you are awaiting the content retrieval methods (e.g., `body = await response.text()`) and only `decode()` raw `bytes` objects obtained from `await response.content()`.
Warnings
- breaking Mixing the `json` argument with `files` or `data` in a single request is no longer allowed and will raise a `TypeError`.
- deprecated Support for Python 3.6 was dropped in treq 22.2.0. Support for Python 3.7 and PyPy 3.7/3.8 was deprecated and subsequently removed in later releases (e.g., 23.11.0, 25.5.0). The minimum supported Twisted version has also been incremented over time, currently requiring >=22.10.0 for treq 25.5.0.
- gotcha A security vulnerability (CVE-2022-23607) in versions prior to 22.1.0 caused cookies provided as a dictionary to be sent to *all* domains on redirect, potentially exposing sensitive information.
- gotcha Prior to version 20.4.0, the `params` argument had issues with URL-encoding characters like `&` or `#`, and non-ASCII URLs/parameters could lead to `UnicodeEncodeError`.
Install
-
pip install treq
Imports
- get
import treq # ... await treq.get(...)
- post
import treq # ... await treq.post(...)
- react
from twisted.internet import reactor; reactor.run()
from twisted.internet.task import react
- HTTPClient
from treq.client import HTTPClient
Quickstart
from twisted.internet.task import react
import treq
import os
async def fetch_and_print(reactor):
# Using httpbin.org for a simple test endpoint
response = await treq.get("https://httpbin.org/get", reactor=reactor)
print(f"Status: {response.code} {response.phrase.decode()}")
print("Headers:")
for k, v in response.headers.getAllRawHeaders():
print(f" {k.decode()}: {', '.join(map(bytes.decode, v))}")
body = await response.text()
print("Body:")
print(body)
if __name__ == '__main__':
react(fetch_and_print)