Quick Start¶
Installation¶
Install the package and browser runtime:
pip install human-requests
playwright install chromium
If you prefer Camoufox, install it separately:
pip install camoufox
camoufox fetch
Basic Usage¶
human-requests wraps Playwright objects in runtime with typed extensions.
The standard entrypoint is:
launch a Playwright browser;
wrap it with
HumanBrowser;create
HumanContextandHumanPage.
import asyncio
from playwright.async_api import async_playwright
from human_requests import HumanBrowser
async def main() -> None:
async with async_playwright() as p:
raw_browser = await p.chromium.launch(headless=True)
browser = HumanBrowser.replace(raw_browser)
ctx = await browser.new_context()
page = await ctx.new_page()
await page.goto("https://example.com", wait_until="domcontentloaded")
print(page.url)
await browser.close()
asyncio.run(main())
HTTP from Page Context¶
Use fetch() to perform direct HTTP
requests from the current page context and receive a
FetchResponse.
resp = await page.fetch("https://httpbin.org/json")
print(resp.status_code)
print(resp.json())
Render an Existing Response¶
Use goto_render() to render a
previously fetched payload (for example, HTML with JS challenge logic) without
making another upstream request.
challenge_resp = await page.fetch("https://example.com/challenge")
await page.goto_render(challenge_resp, wait_until="networkidle")
State Helpers¶
Cookies and storage helpers are available on both context and page levels:
cookies = await page.cookies()
ctx_storage = await ctx.local_storage() # all origins in context
page_storage = await page.local_storage() # current page origin only
print(len(cookies))
print(ctx_storage.keys())
print(page_storage)
Fingerprint Snapshot¶
fingerprint() collects a
normalized runtime/browser fingerprint snapshot.
fp = await ctx.fingerprint(origin="https://example.com")
print(fp.user_agent)
print(fp.browser_name, fp.browser_version)
API Tree Boilerplate Helper¶
For SDK-like API trees you can avoid repetitive parent wiring with
ApiChild, ApiParent and api_child_field.
from dataclasses import dataclass
from human_requests import ApiChild, ApiParent, api_child_field
class ClassCatalog(ApiChild["ShopApi"]):
async def tree(self):
...
class ClassGeolocation(ApiChild["ShopApi"]):
async def cities_list(self):
...
@dataclass
class ShopApi(ApiParent):
Catalog: ClassCatalog = api_child_field(ClassCatalog)
Geolocation: ClassGeolocation = api_child_field(ClassGeolocation)
ApiParent initializes all api_child_field(...) attributes in
__post_init__ automatically.
Nested chains are also supported (Root -> Child -> Child):
@dataclass
class BranchApi(ApiChild["RootApi"], ApiParent):
Catalog: ClassCatalog = api_child_field(ClassCatalog)
@dataclass
class RootApi(ApiParent):
Branch: BranchApi = api_child_field(BranchApi)