Sessions
Sessions keep a browser context open across multiple requests.
import asyncio
from pathlib import Path
from webskrap import SessionConfig, WebSkrapClient
async def main() -> None:
config = SessionConfig(
user_data_dir=Path(".webskrap/session"),
headless=True,
)
async with WebSkrapClient() as client:
session = await client.session("default", config=config)
first = await session.fetch("https://example.com")
second = await session.fetch("https://example.com/account")
print(first.status, second.status)
asyncio.run(main())Calling client.session() again with the same name returns the existing open
session:
session = await client.session("default")
same_session = await client.session("default")
assert session is same_sessionClose individual sessions when you are done with them, or let
WebSkrapClient.close() close all sessions:
await session.close()Persistent storage
Set user_data_dir to keep cookies, local storage, and browser profile state between runs.
config = SessionConfig(user_data_dir=Path(".webskrap/profile"))Use storage_state for a Playwright-style cookie/local-storage snapshot when
you do not need a full persistent browser profile:
config = SessionConfig(storage_state="state.json")storage_state is applied only for non-persistent contexts. If
user_data_dir is set, the persistent profile directory owns browser state.
Headed debugging
Set headless=False and keep a page open when you need to inspect behavior:
import asyncio
from pathlib import Path
from webskrap import SessionConfig, WebSkrapClient
async def main() -> None:
config = SessionConfig(
headless=False,
user_data_dir=Path(".webskrap/debug"),
slow_mo_ms=50,
)
async with WebSkrapClient() as client:
session = await client.session("debug", config=config)
page = await session.context.new_page()
await page.goto("https://example.com", wait_until="domcontentloaded")
input("Press Enter to close browser...")
asyncio.run(main())Human-like clicks
Sessions expose human_click for interactions that should behave more like a manual click
than a direct Playwright page.click.
async with WebSkrapClient() as client:
session = await client.session("default")
page = await session.context.new_page()
await page.goto("https://example.com", wait_until="domcontentloaded")
await session.human_click(page, "label[for='radio1']")Pass human=False to use the same helper while delegating directly to Playwright.
await session.human_click(page, "label[for='radio1']", human=False, timeout=5_000)Pass normal click options such as button, click_count, delay, modifiers,
position, strict, and trial:
await session.human_click(
page,
"button[type='submit']",
strict=True,
timeout=10_000,
modifiers=["Shift"],
)See the Humanizer guide for the focused behavior reference and safety boundaries.
Common options
config = SessionConfig(
browser="chromium",
channel="chrome",
headless=False,
navigation_timeout_ms=90_000,
default_timeout_ms=90_000,
slow_mo_ms=50,
launch_args=[
"--start-maximized",
"--no-first-run",
"--no-default-browser-check",
],
)Proxy example
from webskrap import ProxyConfig, SessionConfig
config = SessionConfig(
proxy=ProxyConfig(
server="http://127.0.0.1:8080",
username="user",
password="pass",
),
)Do not commit proxy credentials, cookies, storage-state files, or persistent session directories.