Find what breaks when your Python stack moves from httpx to httpx2 (the pydantic fork; openai 3.x, anthropic 1.x, Starlette, the MCP SDK and huggingface_hub already switched). Pure stdlib, Python 3.9+ (it analyses code, it does not import httpx), no network except the optional TLS probe.
Unofficial community tool, not affiliated with httpx, httpx2 or pydantic. State as of 2026-10-18.
The move breaks things silently: import httpx fails once an SDK stops pulling it in; respx and
pytest-httpx mocks stop intercepting, so tests hit the live API; except httpx.ConnectError no longer
catches errors raised by httpx2 code; httpx clients passed as http_client= are the wrong type; TLS switches
from the certifi bundle to the OS trust store.
pip install httpx2-audit # or: pip install git+https://github.com/rafal-one/httpx2-audit
$ httpx2-audit check src/
src/app.py:1:1: HX001 imports httpx; httpx2 is a separate package with its own module name [info]
src/app.py:4:36: HX004 httpx object or http_client passed on; an httpx2-based SDK needs httpx2 objects (http_client) [warning]
src/app.py:7:8: HX003 except clause names an httpx exception; errors raised by httpx2-based code are not caught (httpx.ConnectError) [warning]
| Rule | Severity | Meaning |
|---|---|---|
| HX001 | info | import httpx / from httpx import ... |
| HX002 | error | httpx imported but not declared in pyproject/requirements (transitive install is gone) |
| HX003 | warning | except httpx.X (also aliases and tuples) |
| HX004 | warning | http_client= or any httpx object (httpx.Timeout, httpx.Limits, ...) passed to a non-httpx call |
| HX005 | warning | isinstance/issubclass against httpx classes |
| HX006 | warning | import httpcore (httpx2 uses httpcore2) |
| HX007 | warning | respx / pytest_httpx imports: they do not mock httpx2 |
| HX008 | info | certifi.where() passed explicitly while httpx is in use |
| HX010 | warning | file imports both httpx and httpx2 |
Options: --format text|json|sarif (SARIF for GitHub code scanning), --min-severity, --fail-on info|warning|error|never (default warning), -q (no footer). Exit codes: 0 nothing at or above
--fail-on, 1 findings, 2 bad usage or missing path. Directories like .venv, node_modules, build
are skipped; files that do not parse are reported on stderr and skipped. Imports already wrapped in
try: import httpx2 ... except ImportError: import httpx are treated as handled.
CI: httpx2-audit check . --format sarif > audit.sarif, or just httpx2-audit check . --fail-on error.
Dry run by default (prints a unified diff); --write applies it.
httpx2-audit fix . # diff
httpx2-audit fix . --write # apply
httpx2-audit fix . --dual --write # libraries: try httpx2, fall back to httpx
import httpx->import httpx2 as httpx(so the rest of the file keeps working),from httpx import X->from httpx2 import X; same forhttpcore->httpcore2andpytest_httpx->pytest_httpx2.requirements*.txtandpyproject.tomlrequirement strings:httpx->httpx2>=2.0,httpcore,pytest-httpx(extras and markers are kept).--dualwraps each import in atry/except ImportErrorand leaves dependencies alone.- Private modules (
httpx._models) and dotted imports are reported asmanual:and left untouched. - It does not touch
exceptclauses,respxmocks or TLS settings; runcheckafterwards. httpx2 needs Python 3.10+.
$ httpx2-audit env --probe api.openai.com --probe intranet.corp:8443
installed:
httpx 0.28.1
httpx2 2.14.0
depend on httpx: respx
depend on httpx2: pytest-httpx2
tls intranet.corp:8443: openssl-default=ok, certifi=FAIL: CERTIFICATE_VERIFY_FAILED, truststore=ok
WARNING: TLS trust differs for intranet.corp:8443: ...
Lists the relevant installed distributions, which installed packages require httpx or httpx2 (a mixed
environment cannot pass clients between them), and compares what the system store, certifi and truststore
(if installed) accept for the hosts you probe. Exit code 1 when warnings are printed.
pytest (37 tests). Tested on Python 3.9 and 3.14; clean installs of wheel and sdist checked.
If this saved your migration a day: https://paypal.me/RafalBaranowski
MIT licensed.