Quick Start¶
Installation¶
Choose one of the options that best suits your requirements:
pip install human-requests[playwright]
playwright install
Standard Playwright with a set of browsers (Chrome, Firefox, WebKit). Not recommended to use in a “bare” form.
pip install human-requests[playwright-stealth]
playwright install
Standard Playwright with a JS stealth patch that hides some automation signatures.
pip install human-requests[camoufox]
camoufox fetch
Playwright browser based on Firefox. The main feature is signature spoofing, which allows sending more traffic and bypassing bans based on fingerprints.
pip install human-requests[patchright]
patchright install chromium
An alternative to playwright-stealth that attempts to achieve similar results without JS injections. In my tests it performed poorly, essentially hiding only the WebDriver flag.
pip install human-requests[all]
You can install everything at once.
Usage¶
Example of reversing the website 5ka.ru
I chose this site because it was the reason I started developing this library. The point is that impersonation in hrequests is poor — or even absent (cannot say for sure). As a result, the site easily detected the bot.
from network_manager import Session, ImpersonationConfig, Policy, HttpMethod
import asyncio
import json
async def main():
# Session initialization
s = Session(headless=True, # False is useful for debugging
browser="camoufox", # camoufox is best for large-scale requests, but may be less stable
# For non-camoufox (it already supports this by default), hides some automation signatures
# Recommended to enable for standard Playwright browsers
playwright_stealth=False,
spoof=ImpersonationConfig(
policy=Policy.INIT_RANDOM,
geo_country="RU",
sync_with_engine=False
))
# Warm up the session (cookies + default local storage)
async with s.goto_page("https://5ka.ru/", wait_until="networkidle") as page:
await page.wait_for_selector(selector="next-route-announcer", state="attached")
# Parse the default store location
default_store_location = json.loads(s.local_storage["https://5ka.ru"]["DeliveryPanelStore"])
# Cookies are attached automatically
resp = await s.request(
HttpMethod.GET, # Equivalent of "GET"
# Fetch the default store from local storage
f"https://5d.5ka.ru/api/catalog/v2/stores/{default_store_location['selectedAddress']['sapCode']}/categories?mode=delivery",
headers={ # Static headers, without them you’ll get a 400
"X-PLATFORM": "webapp",
# Device ID saved by site JS during warm-up
"X-DEVICE-ID": s.local_storage["https://5ka.ru"]["deviceId"],
"X-APP-VERSION": "0.1.1.dev"
}
)
# If while parsing the response you encounter, for example:
# a JS challenge that must be solved to get the data,
# you can render the result directly in the browser (without a duplicate request).
# Advantage: no duplicate requests (less suspicious, saves rate limit).
# async with resp.render() as p:
# await p.wait_for_load_state("networkidle")
# print(await p.content())
# Don’t forget to close the session (in a `with` context it would close automatically)
await s.close()
# Verify result
assert resp.status_code == 200
# Parse body
json_result = json.loads(resp.body)
# Process further as you wish
names = []
for element in json_result:
names.append(element["name"])
from pprint import pprint
pprint(names)
if __name__ == "__main__":
asyncio.run(main())
For more details, also see:
For choosing the right browser, see Browser Selection Recommendations