Python
pip install swiftbrowseThe swiftbrowse package uses the standard library only and needs Python 3.8+. The platform wheels include the native binary. It works with pytest, unittest or plain scripts.
A test with pytest
import pytest
from swiftbrowse import launch
@pytest.fixture(scope="session")
def browser():
with launch() as b:
yield b
@pytest.fixture
def page(browser):
with browser.new_session() as s:
yield s
def test_adds_a_todo(page):
page.navigate("http://localhost:3000/")
page.fill("New todo", "Write docs")
page.press_key("Enter", expect={"type": "text_visible", "text": "Write docs"})
page.expect([
{"type": "count", "target": {"by": "role", "role": "listitem"}, "count": 1},
{"type": "no_console_errors"},
])Each new_session() is isolated: its own cookies, storage and tabs. It attaches to the warm browser daemon, so creating one per test is cheap.
API
launch(executable=None, *, ...) → Browser
| Keyword | Default | Meaning |
|---|---|---|
test_defaults |
True |
No approval prompts for "Delete" or "Pay" clicks, evaluate allowed, uploads from the working directory. Set it to False for the agent-safe policy. |
headed |
False |
Show browser windows. |
no_daemon |
False |
Launch a browser for this process instead of attaching to the warm daemon. |
chromium |
discovered | Path to a Chromium binary. |
evidence_dir |
temp directory | Where screenshots, videos and saved states go. |
timeout_ms |
10000 | How long actions wait for their target, in ms. |
allow_hosts / block_hosts |
Restrict navigation. | |
upload_dirs |
Extra directories upload_file may read from. |
|
allow_file_urls |
False |
Permit file:// navigation. |
throw_on_error |
True |
Raise SwiftBrowseError when an operation fails. |
Browser and Session are context managers, so with closes them.
browser.new_session(*, headless=None, viewport=None, throw_on_error=None) → Session
viewport is (width, height); the default is (1280, 800).
Session methods
Every operation is a method with its documented signature: required arguments positionally, the rest by keyword.
page.navigate(url, wait_until="network_idle")
page.click("Save", expect={"type": "text_visible", "text": "Saved"}, timeout_ms=10000)
page.fill({"by": "label", "text": "Email"}, "ada@example.com")
page.select_option("Country", "Norway")
page.check("I agree")
page.upload_file("Documents", ["fixtures/notes.txt"])
page.route(url="**/api/todos", json=[])
page.switch_tab(url_contains="checkout")
page.switch_frame(name="payment")
page.save_storage_state("member")
shot = page.get_screenshot(full_page=True)Plus:
page.expect(condition_or_list, *, timeout_ms=5000, name=None): an auto-waiting assertion. See Assertions.page.text(): the page as compact text.page.run(op, args): any operation by name.
Results and errors
Methods return the ActionResult as a dict. If the operation failed, they raise SwiftBrowseError instead (unless throw_on_error=False), with .kind and the full .result.
from swiftbrowse import SwiftBrowseError
try:
page.click("Missing", timeout_ms=500)
except SwiftBrowseError as e:
assert e.kind == "not_found"Threads
A Browser sends one request at a time; calls from several threads are serialized. For parallel tests, use pytest-xdist: each worker process gets its own launch().
The binary
The SDK uses, in order: the executable argument, $SWIFTBROWSE_BIN, the binary inside the installed wheel, then swiftbrowse on PATH. The package also installs the swiftbrowse command (swiftbrowse test, swiftbrowse mcp, …), and python -m swiftbrowse works too.