Skip to main content

Playwright+curl_cffi traffic orchestrator

Project description

🧰 Human Requests

logo.webp

Asynchronous library for browser‑like HTTP scenarios with controlled offline rendering and two‑way state transfer.

Tests Coverage Python PyPI - Package Version License BlackCode mypy Discord Telegram

⭐ Star us on GitHub | 📚 Read the Docs | 🐛 Report a Bug

✨ Features

  • HTTP by default. Direct requests via curl_cffi in 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 localStorage between HTTP and the browser (storage_state ⇄ session).
  • Async by design. Native asyncio for predictable concurrency.

🚀 Quick Start

Installation

pip install human-requests[playwright-stealth]
playwright install

Direct request (pretend to be a browser)

import 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())

Render an already received response (without another request)

# 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 session

Warm‑up: inject localStorage BEFORE page start

origin = "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

Accessing state

# Cookies:
print(s.cookies.storage)

# LocalStorage:
print(s.local_storage.get("https://target.example", {}))

Key Characteristics

  • 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 localStorage sync both ways.
  • Unified proxy layer: single proxy format → for curl_cffi and Playwright.
  • Clean stack: no external Go binaries.

Comparison: human-requests vs hrequests

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.

🛠️ Development

Setup

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

Commands

# 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

Dev: local test server

# from the test_server/ folder
make serve  # foreground (Ctrl+C to stop)
make stop   # stop background process

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

human_requests-0.1.1.tar.gz (32.5 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

human_requests-0.1.1-py3-none-any.whl (33.8 kB view details)

Uploaded Python 3

File details

Details for the file human_requests-0.1.1.tar.gz.

File metadata

  • Download URL: human_requests-0.1.1.tar.gz
  • Upload date:
  • Size: 32.5 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.7

File hashes

Hashes for human_requests-0.1.1.tar.gz
Algorithm Hash digest
SHA256 5344323f788a4ab082e43889bb650f26510c5204674e14199febe8b09fc073c4
MD5 d63d3f9355ef52b2de0bd608479d0455
BLAKE2b-256 81053576ee751d68b11404c7d92ace21c38998332865509e60165d066011a35a

See more details on using hashes here.

Provenance

The following attestation bundles were made for human_requests-0.1.1.tar.gz:

Publisher: release.yml on Miskler/human-requests

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file human_requests-0.1.1-py3-none-any.whl.

File metadata

  • Download URL: human_requests-0.1.1-py3-none-any.whl
  • Upload date:
  • Size: 33.8 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.7

File hashes

Hashes for human_requests-0.1.1-py3-none-any.whl
Algorithm Hash digest
SHA256 790e1ee13ded57ea6dc54b8d0362fbb4011941341348efe35df4abc9fc419257
MD5 82033cbfcb1ea304f40639c756ad7ff8
BLAKE2b-256 9ed6c4cdd7f5b050ea2615536bf6ed9b3f859f711711e33b01149e1ce3c15e43

See more details on using hashes here.

Provenance

The following attestation bundles were made for human_requests-0.1.1-py3-none-any.whl:

Publisher: release.yml on Miskler/human-requests

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page