Asynchronous library for browser‑like HTTP scenarios with controlled offline rendering and two‑way state transfer.
- HTTP by default. Direct requests via
curl_cffiin impersonate mode + real browser headers generation. - Browser on demand. Offline render of an already received response (no repeated HTTP) and JS execution.
- Unified state. Two‑way transfer of cookies and
localStoragebetween HTTP and the browser (storage_state ⇄ session). - Async by design. Native
asynciofor predictable concurrency.
pip install human-requests[playwright-stealth]
playwright installimport asyncio
from human_requests import Session, HttpMethod
async def main():
async with Session(headless=True, browser="camoufox") as s:
resp = await s.request(HttpMethod.GET, "https://target.example/")
print(resp.status_code, len(resp.text))
asyncio.run(main())# resp — the result of an HTTP request
async with resp.render(wait_until="networkidle") as page:
await page.wait_for_selector("#content")
# after exiting:
# - cookies and localStorage are synced back into the sessionorigin = "https://target.example"
async with Session(headless=True, browser="camoufox") as s:
# prepare storage_state in advance
s.local_storage.setdefault(origin, {})
s.local_storage[origin]["seen"] = "1"
s.local_storage[origin]["ab_variant"] = "B"
# the browser starts with the required values already in place
async with s.goto_page(f"{origin}/", wait_until="networkidle"):
pass# Cookies:
print(s.cookies.storage)
# LocalStorage:
print(s.local_storage.get("https://target.example", {}))- HTTP impersonation:
curl_cffi+ browser‑grade headers on every request. - Offline render: first response interception (fulfill) and soft reloads without recreating contexts.
- State as a first‑class citizen: cookies and
localStoragesync both ways. - Unified proxy layer: single proxy format → for
curl_cffiand Playwright. - Clean stack: no external Go binaries.
| Aspect | human-requests | hrequests |
|---|---|---|
| Execution model | asyncio (native) |
sync + threads/gevent |
| HTTP impersonation | curl_cffi impersonate + per‑request browser headers |
tls-client (Go backend) |
Offline Response render |
Yes (fulfill + soft‑reload; no repeated HTTP) | Yes (post‑render with cookies/content update) |
| Cookies ↔ HTTP/Browser | Two‑way transfer | Two‑way transfer |
localStorage ↔ HTTP/Browser |
First‑class (storage_state ⇄ session) | Via page.evaluate(...) |
| Typing | mypy‑friendly | — |
| Dependencies | No Go binaries | Go backend (tls-client) |
| Built‑in HTML parser | — | selectolax |
The focus of human-requests is a controlled anti‑bot pipeline in
asyncio: HTTP by default, a browser only where needed, with state hand‑off.
git clone https://github.com/Miskler/human-requests.git
cd human-requests
python -m venv .venv
source .venv/bin/activate # Windows: .venv\Scripts\activate
make build
make install-dev# Checks
pytest # tests + coverage
make lint # ruff/flake8/isort/black (if enabled)
make type-check # mypy/pyright
# Actions
make format # formatting
make docs # build documentation# from the test_server/ folder
make serve # foreground (Ctrl+C to stop)
make stop # stop background process