License
- OSI Approved :: MIT License
Programming Language
- Python :: 3
- Python :: 3.8
- Python :: 3.9
- Python :: 3.10
- Python :: 3.11
- Python :: 3.12
- Python :: 3.13
- Python :: 3.14
Hyperbrowser Python SDK
Checkout the full documentation here
Installation
Currently Hyperbrowser supports creating a browser session in two ways:
- Async Client
- Sync Client
It can be installed from pypi by running :
pip install hyperbrowser
The browser-control examples below also use Playwright:
pip install playwright
Configuration
Both the sync and async client follow similar configuration params
API Key
The API key can be configured either from the constructor arguments or environment variables using HYPERBROWSER_API_KEY
If no API key is provided, the client falls back to a saved OAuth session created by hx auth login. By default it reads ~/.hx_config/auth/default.json, or ~/.hx_config/auth/<profile>.json when HYPERBROWSER_PROFILE or ClientConfig(profile=...) is set.
Profile names must match ^[A-Za-z0-9._-]+$.
base_url and HYPERBROWSER_BASE_URL accept either https://host or https://host/api. The client normalizes both to the same control-plane base URL.
Usage
Hyperbrowser 1.0 accepts plain dictionaries for request parameters. Method
signatures use TypedDict definitions, so editors can autocomplete keys at
every nested level:
from hyperbrowser import Hyperbrowser
client = Hyperbrowser(api_key="test-key")
# Preferred in 1.0: autocomplete works directly in the dictionary.
session = client.sessions.create(
{
"use_stealth": True,
"screen": {"width": 1920, "height": 1080},
}
)
Browser sessions can also use an outbound network policy. Omitting these fields keeps the default unrestricted behavior:
session = client.sessions.create(
{
"allow_internet_access": False,
"allow_out": ["example.com"],
"deny_out": ["0.0.0.0/0"],
}
)
Direct browser policies accept domains, IPv4 addresses, and CIDR ranges in
allow_out; deny_out accepts IPv4 addresses and CIDR ranges. With a proxy,
allow rules must be domains and the only supported deny rule is 0.0.0.0/0.
Existing Pydantic request classes remain accepted, so upgrading does not require an immediate rewrite:
from hyperbrowser.models import CreateSessionParams, ScreenConfig
session = client.sessions.create(
CreateSessionParams(
use_stealth=True,
screen=ScreenConfig(width=1920, height=1080),
)
)
Import request annotations from hyperbrowser.types when a named variable is
useful. The same names under hyperbrowser.models refer to the legacy Pydantic
request classes. Responses remain Pydantic models.
JSON Schema fields accept raw schema values, including object schemas with
$defs, $ref, or custom keywords, and boolean schemas where the API supports
them. Those schemas and other user-owned mappings are preserved as data; only
SDK-owned request keys are translated to their API aliases. Schema fields
documented as accepting a model class can also generate a schema from a Pydantic
model.
See the Hyperbrowser Python SDK 1.0 migration guide for the complete compatibility details and migration checklist.
Async
import asyncio
from hyperbrowser import AsyncHyperbrowser
from playwright.async_api import async_playwright
HYPERBROWSER_API_KEY = "test-key"
async def main():
async with AsyncHyperbrowser(api_key=HYPERBROWSER_API_KEY) as client:
session = await client.sessions.create()
try:
async with async_playwright() as playwright:
browser = await playwright.chromium.connect_over_cdp(
session.ws_endpoint
)
context = browser.contexts[0]
page = context.pages[0]
print("Navigating to Hacker News...")
await page.goto("https://news.ycombinator.com/")
print("Page title:", await page.title())
finally:
await client.sessions.stop(session.id)
# Run the asyncio event loop
asyncio.run(main())
Sync
from playwright.sync_api import sync_playwright
from hyperbrowser import Hyperbrowser
HYPERBROWSER_API_KEY = "test-key"
def main():
client = Hyperbrowser(api_key=HYPERBROWSER_API_KEY)
session = client.sessions.create()
ws_endpoint = session.ws_endpoint
# Launch Playwright and connect to the remote browser
with sync_playwright() as p:
browser = p.chromium.connect_over_cdp(ws_endpoint)
context = browser.new_context()
# Get the first page or create a new one
if len(context.pages) == 0:
page = context.new_page()
else:
page = context.pages[0]
# Navigate to a website
print("Navigating to Hacker News...")
page.goto("https://news.ycombinator.com/")
page_title = page.title()
print("Page title:", page_title)
page.close()
browser.close()
print("Session completed!")
client.sessions.stop(session.id)
# Run the asyncio event loop
main()
Sandboxes
The sync and async clients expose the same sandbox APIs through client.sandboxes.
Create a sandbox with pre-exposed ports
from hyperbrowser import Hyperbrowser
client = Hyperbrowser(api_key="test-key")
sandbox = client.sandboxes.create(
{
"image_name": "node",
"cpu": 2,
"memory_mib": 2048,
"disk_mib": 8192,
"exposed_ports": [{"port": 3000, "auth": True}],
}
)
print(sandbox.exposed_ports[0].browser_url)
print(sandbox.cpu, sandbox.memory_mib, sandbox.disk_mib)
sandbox.stop()
client.close()
cpu, memory_mib, and disk_mib are only supported for image launches.
Manage volumes and mount them in a sandbox
from hyperbrowser import Hyperbrowser
client = Hyperbrowser(api_key="test-key")
volume = client.volumes.create({"name": "project-cache"})
all_volumes = client.volumes.list()
same_volume = client.volumes.get(volume.id)
sandbox = client.sandboxes.create(
{
"image_name": "node",
"mounts": {
"/workspace/cache": {
"id": same_volume.id,
"type": "rw",
"shared": True,
}
},
}
)
sandbox.stop()
client.close()
List sandboxes with filters
from hyperbrowser import Hyperbrowser
client = Hyperbrowser(api_key="test-key")
result = client.sandboxes.list(
{
"status": "active",
"search": "sandbox",
"start": 1711929600000,
"end": 1712016000000,
"limit": 20,
}
)
for sandbox in result.sandboxes:
print(sandbox.id, sandbox.status)
List snapshots for a specific image
from hyperbrowser import Hyperbrowser
client = Hyperbrowser(api_key="test-key")
snapshots = client.sandboxes.list_snapshots(
{"image_name": "node", "status": "created", "limit": 10}
)
Expose and unexpose ports
from hyperbrowser import Hyperbrowser
client = Hyperbrowser(api_key="test-key")
sandbox = client.sandboxes.create(
{"image_name": "node", "cpu": 2, "memory_mib": 2048, "disk_mib": 8192}
)
result = sandbox.expose({"port": 8080, "auth": True})
print(result.url, result.browser_url)
sandbox.unexpose(8080)
Batch file writes with per-file options
from hyperbrowser import Hyperbrowser
client = Hyperbrowser(api_key="test-key")
sandbox = client.sandboxes.create({"image_name": "node"})
sandbox.files.write(
[
{
"path": "/tmp/config.json",
"data": '{"debug":true}\n',
"append": True,
"mode": "600",
},
{"path": "/tmp/blob.bin", "data": b"\x00\x01\x02"},
]
)
Resume terminal output after reconnect
from hyperbrowser import Hyperbrowser
client = Hyperbrowser(api_key="test-key")
sandbox = client.sandboxes.create({"image_name": "node"})
terminal = sandbox.terminal.create({"command": "bash"})
connection = terminal.attach(cursor=10)
for event in connection.events():
print(event)
License
This project is licensed under the MIT License - see the LICENSE file for details.