Metadata-Version: 2.4
Name: browserfabric
Version: 1.1.0
Summary: BrowserFabric — the cloud browser for AI agents. Observe, act, verify, and manage remote browser sessions.
Author-email: Raphael Shu <raphael@uaca.com>
License: MIT
Project-URL: Homepage, https://github.com/acenta-ai/browserfabric
Project-URL: Documentation, https://browserfabric.com/docs
Project-URL: Repository, https://github.com/acenta-ai/browserfabric
Project-URL: Issues, https://github.com/acenta-ai/browserfabric/issues
Keywords: browser,automation,api,web,crawling,sdk,client,playwright,cdp,headless
Classifier: Development Status :: 4 - Beta
Classifier: Intended Audience :: Developers
Classifier: License :: OSI Approved :: MIT License
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.9
Classifier: Programming Language :: Python :: 3.10
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Topic :: Software Development :: Libraries :: Python Modules
Classifier: Topic :: Internet :: WWW/HTTP :: Browsers
Requires-Python: >=3.9
Description-Content-Type: text/markdown
Requires-Dist: httpx>=0.25.0
Provides-Extra: dev
Requires-Dist: pytest>=7.4.0; extra == "dev"
Requires-Dist: pytest-asyncio>=0.21.0; extra == "dev"
Requires-Dist: black>=23.9.0; extra == "dev"
Requires-Dist: isort>=5.12.0; extra == "dev"
Requires-Dist: mypy>=1.6.0; extra == "dev"

# BrowserFabric

Python SDK for **BrowserFabric** — the cloud browser for AI agents. Run remote sessions with saved context, live human takeover, and tools to observe, act, and verify.

## Install

```bash
pip install browserfabric
```

## Quick Start

```python
import browserfabric
import asyncio

async def main():
    async with browserfabric.browser() as session:
        await session.navigate("https://example.com")
        state = await session.observe_page()
        print(state["elements"])

asyncio.run(main())
```

## Agent interface (1.1.0+)

After navigating to your form, use the names in the current observation:

```python
state = await session.observe_page()
submit = next(e["ref"] for e in state["elements"] if e["name"] == "Continue")
result = await session.act(
    state["tab_id"], state["observation_id"],
    [{"type": "click", "ref": submit}],
    wait_for={"text": "Welcome"},
)
print(result["status"])
```

The sync session exposes the same methods. Use `tabs()` for explicit tab control,
`observe_page(since=...)` for a diff, `browser_screenshot(tab_id)` for base64 PNG,
and `cancel()` to interrupt running work.

`act` preserves recovery observations on tool failures. Check `status`:
`verified` means your condition matched; `completed` means actions ran without
an outcome check. On failure or interruption, inspect the current page and
completed steps before retrying. Transport errors still raise.

SDK-generated request IDs stay the same across transport retries. Explicit IDs
must be unique per operation and reused only with identical payloads. Deduplication
covers the last 64 requests in the live session, not a backend restart.

[Complete interface contract](https://www.browserfabric.com/agent-browser-interface.md).

## Authentication

Set your API key as an environment variable or pass it directly:

```python
# Via environment variable
export BROWSERFABRIC_API_KEY=bf_your_key_here

# Or pass directly
async with browserfabric.browser(api_key="bf_...") as session:
    ...
```

## Persistent Sessions

Save and restore browser state (cookies, localStorage) across sessions:

```python
# Save state on close
async with browserfabric.browser(persist=True) as session:
    await session.navigate("https://app.example.com/login")
    await session.type("#email", "user@example.com")
    await session.type("#password", "secret")
    await session.click("#submit")
    ctx = await session.save_context("my-app-login")

# Restore later
async with browserfabric.browser(context_id=ctx["context_id"]) as session:
    # Already logged in
    await session.navigate("https://app.example.com/dashboard")
```

## CDP WebSocket

Connect with Playwright directly for full browser control:

```python
from playwright.async_api import async_playwright

# Get the CDP WebSocket URL from session info
info = await session.session_info()
ws_url = info["ws_url"]

# Connect with Playwright
pw = await async_playwright().start()
browser = await pw.chromium.connect_over_cdp(ws_url)
page = browser.contexts[0].pages[0]
await page.goto("https://example.com")
```

## Available Methods

| Method | Description |
|--------|-------------|
| `navigate(url)` | Go to a URL |
| `click(selector)` | Click an element |
| `type(selector, text)` | Type into an input |
| `find(selector)` | Find elements |
| `screenshot(filename)` | Take a screenshot |
| `observe()` | Get interactive DOM elements |
| `snapshot()` | Get accessibility tree |
| `page_info()` | Get page URL and title |
| `session_info()` | Get session metadata + CDP URL |
| `save_context(name)` | Save browser state |
| `close()` | Close the session |

## Self-Hosted

Point to your own BrowserFabric instance:

```python
async with browserfabric.browser(base_url="http://your-server:9000") as session:
    ...
```

## License

MIT
