HTTP client response objects
English | Русский
Wrappers around httpx.Response that know how to parse the response body.
A client method returns an object typed for the expected data instead of a plain Response from which you extract JSON manually. The type is visible in the method signature, parsing takes one line, and your IDE and mypy know the model fields.
Installation
Requires Python 3.13 or later.
pip install cloudru-qa-http-client-responses
Import the library as the http_client_responses module.
Skills for AI agents
The package includes the http-client-responses-usage skill
with examples and usage rules for AI agents. Install the library
in your project environment, then run this from its root (requires uv):
uvx library-skills install --skill http-client-responses-usage --yes
For Claude Code, add --claude. The instructions are shipped with the library version.
Usage
JsonResponse[PydanticModel]— response body described by a pydantic model. ReplacePydanticModelwith your model.GenericResponse[ReturnType]— body parsed by a supplied function.ResponseWrapper— no body parsing, for when you need only status, headers, and content.
from http_client import HttpClient
from httpx import Response
from pydantic import BaseModel
from http_client_responses import GenericResponse, JsonResponse
class ExampleRequest(BaseModel):
limit: int = 100
offset: int = 0
search: str | None = None
class User(BaseModel):
name: str
age: int
alive: bool
skills: list[str]
class ExampleResponse(BaseModel):
users: list[User]
total: int
class ExampleClient(HttpClient):
"""Test HTTP client."""
def get_users(self, request: ExampleRequest) -> JsonResponse[ExampleResponse]:
"""Send a simple GET request for a user list in JSON format."""
response = self.get(
url="/users",
params=request.model_dump(exclude_none=True),
)
return JsonResponse(
response=response,
schema=ExampleResponse,
)
def download_details(self, user_id: int) -> GenericResponse[dict[str, str]]:
"""Send a request for string data to convert into a dict."""
response = self.get(f"/user/{user_id}/details")
def parser(r: Response) -> dict[str, str]:
result = dict()
for line in r.text.split("\n"):
key, value = line.split(":", maxsplit=1)
result[key] = value.strip()
return result
return GenericResponse(
response=response,
parser=parser,
)
Parse the body explicitly: model() for JsonResponse, parse() for GenericResponse.
response = client.get_users(ExampleRequest(limit=10))
assert response.status_code == 200
assert response.model().total == 42
raise_for_status() returns the wrapper itself, making status checks easy to chain:
users = client.get_users(ExampleRequest()).raise_for_status().model()
Response attributes
| Attribute | Type | Notes |
|---|---|---|
status_code |
int |
|
reason_phrase |
str |
|
headers |
httpx.Headers |
get_list() returns all values for a repeated header |
raw_headers |
dict[str, str] |
one value per header |
cookies |
httpx.Cookies |
|
content / text |
bytes / str |
|
url |
str |
|
request |
httpx.Request |
|
elapsed |
timedelta |
|
is_success / is_error |
bool |
|
is_client_error / is_server_error |
bool |
4xx / 5xx |
raise_for_status() |
Self |
raises httpx.HTTPStatusError for any non-2xx status |
json() |
Any |
parse the body as JSON without schema validation |
For Set-Cookie and other repeated headers, use headers.get_list("set-cookie").
Parsing errors
If the body cannot be parsed, ResponseParseError is raised instead of a plain pydantic.ValidationError, showing which request failed and what the server returned:
Library-generated messages retain their original Russian text.
ResponseParseError: не удалось разобрать тело ответа
GET http://test.com/users -> 200
Body: {"users": [{"name": "John Doe"}], "total": "many"}
Причина: 1 validation error for ExampleResponse
total
Input should be a valid integer, unable to parse string as an integer
The original exception is available in error.cause and __cause__.
Asynchronous clients
from http_client import AsyncHttpClient
class AsyncExampleClient(AsyncHttpClient):
async def get_users(self, request: ExampleRequest) -> JsonResponse[ExampleResponse]:
response = await self.get(url="/users", params=request.model_dump(exclude_none=True))
return JsonResponse(response=response, schema=ExampleResponse)
Development
The library is developed in the qa-libraries monorepo
alongside the other cloudru-qa-* libraries. You need uv, GNU Make,
and checkmake.
Run commands from the repository root:
make sync # install dependencies for all libraries from uv.lock
make test-http-client-responses # tests for this library
make typecheck-http-client-responses # mypy for this library
make check # formatting, ruff, mypy, and tests for the entire workspace
Tests run on Python 3.13 and 3.14. Create a separate environment for another version:
make sync test-http-client-responses PYTHON_VERSION=3.14.
Publish a release with the git tag http-client-responses/v<version>. The tag version must match
the version in packages/http-client-responses/pyproject.toml.
Metadata
Release files for cloudru-qa-http-client-responses 1.0.0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | Provenance | Actions |
|---|---|---|---|---|
| cloudru_qa_http_client_responses-1.0.0.tar.gz | 18.4 kB | With provenance | Details for cloudru_qa_http_client_responses-1.0.0.tar.gz |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Actions Reset |
|---|---|---|---|---|
| cloudru_qa_http_client_responses-1.0.0-py3-none-any.whl | Python 3 | none | any | Details for cloudru_qa_http_client_responses-1.0.0-py3-none-any.whl |
Total release size: 37.2 kB
Release files / cloudru_qa_http_client_responses-1.0.0.tar.gz
| Download URL | cloudru_qa_http_client_responses-1.0.0.tar.gz |
|---|---|
| Size | 18.4 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
dccfa416fa0e6b48748aa2d22fcd8c9098de56eab539948dae3530462b362ca1
|
|
BLAKE2b-256 checksum How to use checksums |
29267d620247323d8eda2bc985df1741dc9ae738f58b5067228205d376665270
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.16
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Nov 14, 2026.
Transparency logRelease files / cloudru_qa_http_client_responses-1.0.0-py3-none-any.whl
| Download URL | cloudru_qa_http_client_responses-1.0.0-py3-none-any.whl |
|---|---|
| Size | 18.7 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
6b4db660b379082de78c7167badbc576ad0c2d9f88e6cb86ba26a4094ea2f2e7
|
|
BLAKE2b-256 checksum How to use checksums |
86f355663f85e5f3dd0b89215cf421766a887105612039987553be4d06aa4ce4
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.16
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Nov 14, 2026.
Transparency logSecurity for cloudru-qa-http-client-responses 1.0.0
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
Full provenance
Both files in this release have been uploaded with provenance metadata.
Attestation for cloudru_qa_http_client_responses-1.0.0.tar.gz
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Nov 14, 2026.
Transparency logA note on package security
PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.
To learn more about protecting yourself from malicious actors, visit our package security documentation.