Metadata-Version: 2.4
Name: pyfox-auto
Version: 0.1.0
Summary: Firefox browser automation via WebDriver BiDi with integrated ForgeAPI antidetect
Project-URL: Homepage, https://github.com/TDoomX/pyfox-auto
Project-URL: Issues, https://github.com/TDoomX/pyfox-auto/issues
License: MIT
License-File: LICENSE
Keywords: antidetect,automation,bidi,firefox,stealth,webdriver,websocket
Classifier: Development Status :: 3 - Alpha
Classifier: Framework :: AsyncIO
Classifier: Intended Audience :: Developers
Classifier: License :: OSI Approved :: MIT License
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.12
Classifier: Programming Language :: Python :: 3.13
Classifier: Topic :: Internet :: WWW/HTTP :: Browsers
Classifier: Topic :: Software Development :: Libraries
Requires-Python: >=3.12
Requires-Dist: aiofiles>=23.0
Requires-Dist: pydantic>=2.0
Requires-Dist: typing-extensions>=4.9
Requires-Dist: websockets>=12.0
Provides-Extra: dev
Requires-Dist: black>=24.0; extra == 'dev'
Requires-Dist: mypy>=1.10; extra == 'dev'
Requires-Dist: pytest-asyncio>=0.23; extra == 'dev'
Requires-Dist: pytest>=8.0; extra == 'dev'
Requires-Dist: ruff>=0.4; extra == 'dev'
Description-Content-Type: text/markdown

# pyfox

Async Firefox browser automation for Python, built on the W3C WebDriver BiDi protocol.

pyfox is designed for Firefox and Firefox-based browsers. It provides an asynchronous API for browser automation, including navigation, DOM interaction, network interception, downloads, Shadow DOM, browser contexts, humanized input, and structured data extraction.

The API is inspired by the developer experience of [Pydoll](https://github.com/autoscrape-labs/pydoll), but built around WebDriver BiDi rather than Chrome DevTools Protocol.

---

## Why WebDriver BiDi?

WebDriver BiDi is the W3C protocol for bidirectional browser automation, natively supported by modern Firefox releases.

pyfox connects to Firefox directly through BiDi over WebSocket. No Selenium, no geckodriver, no Playwright underneath. This keeps the API fully asynchronous and removes the need for any external WebDriver binary.

---

## Features

- Async API built around `asyncio`
- Direct WebDriver BiDi communication over WebSocket
- Multiple tabs and isolated browser contexts
- CSS, XPath, ID, class, name, tag, text, and attribute selectors
- Iframe and Shadow DOM traversal
- Humanized mouse movement and keyboard input
- Screenshots and PDF generation
- Cookie management
- Network monitoring and interception
- Request and response modification, mocking, and failure
- Response body capture during interception
- HAR 1.2 recording
- Download handling with `expect_download()`
- Browser dialogs and network logs
- Pydantic-based structured extraction
- Async retry decorator
- ForgeAPI integrated fingerprint controls
- Cloudflare Turnstile interaction support

---

## Installation

```bash
pip install pyfox-auto
```

**Requirements**

- Python 3.12+
- Firefox 128+

Firefox 130+ is recommended when using download functionality. Firefox-based browsers with WebDriver BiDi support also work.

---

## Getting Started

```python
import asyncio
from pyfox import Firefox, FirefoxOptions


async def main():
    options = FirefoxOptions()
    # Point to any Firefox-based browser binary:
    # options.binary_path = "/path/to/firefox-based-browser"

    async with Firefox(options=options) as browser:
        tab = await browser.new_tab()
        await tab.navigate("https://www.google.com")

        search = await tab.find_or_wait_element("input[name='q']", timeout=10)
        await search.type_text("pyfox automation")
        await tab.screenshot("screenshot.png")


asyncio.run(main())
```

---

## Browser and Tab Management

```python
async with Firefox(options=options) as browser:
    tab = await browser.new_tab()
    await tab.navigate("https://example.com")
    print(await tab.title)
```

For isolated sessions, create a browser context:

```python
context_id = await browser.create_context()
tab = await browser.new_tab(context_id=context_id)
```

Each context maintains its own browser state, allowing multiple independent sessions within the same Firefox instance.

---

## Finding Elements

Supported selector types: CSS, XPath, ID, class, name, tag, text, and attributes. Elements can also be searched across iframes.

```python
element = await tab.find_or_wait_element("button.submit", timeout=10)
```

`WebElement` exposes click, type, scroll, get attribute, screenshot, and Shadow DOM access.

---

## Humanized Input

Mouse movement uses cubic Bézier curves, Fitts's Law timing, Gaussian tremor, and overshoot correction.

```python
await tab.mouse.move(500, 300, humanize=True)
await tab.mouse.click(500, 300, humanize=True)
```

Keyboard input supports variable per-character delays and QWERTY-based typo simulation.

```python
await element.type_text("pyfox automation", humanize=True)
```

---

## Shadow DOM

```python
shadow_roots = await tab.find_shadow_roots(deep=True)

for shadow_root in shadow_roots:
    button = await shadow_root.query(".internal-button", raise_exc=False)
    if button:
        await button.click()
```

Shadow roots expose the same element-finding API used elsewhere in the library.

---

## Network Interception

Monitor and intercept browser network traffic through WebDriver BiDi.

Supported operations: request and response interception, request modification, response handling, mocking, failure, authentication, and network logging.

### Capturing Response Bodies

```python
async with tab.capture_response_body(url_pattern="api/data") as capture:
    await tab.navigate("https://example.com")
    response = capture.get("api/data")
```

> WebDriver BiDi does not provide direct response body access outside an active interception workflow, unlike CDP.

---

## HAR Recording

Network activity can be recorded and exported as HAR 1.2. Useful for keeping a complete trace of requests and responses during a session.

---

## Cookies

```python
cookies = await tab.get_cookies()
```

Setting and deleting cookies is also supported through the BiDi storage API.

---

## Downloads

```python
async with tab.expect_download() as download:
    await element.click()

file = await download.value
```

Firefox 130+ is recommended for download functionality.

---

## Structured Extraction

Define a Pydantic model and extract typed data directly from the page:

```python
from pyfox.extractor import ExtractionModel, Field


class Quote(ExtractionModel):
    text: str = Field(selector=".text")
    author: str = Field(selector=".author")


quote = await tab.extract(Quote)
print(quote.author)

quotes = await tab.extract_all(Quote, scope=".quote")
```

---

## [ForgeAPI](README_FORGEAPI.md)

ForgeAPI provides browser fingerprint controls via `script.addPreloadScript`. It requires no browser extension and no mandatory proxy.

Controllable properties: canvas, WebGL, AudioContext, fonts, navigator, screen, hardware concurrency, timezone, permissions, battery.

```python
from pyfox.antidetect import forge_check

result = await forge_check(tab)
```

ForgeAPI can also be enabled at the browser level so every new tab gets it automatically:

```python
async with Firefox(options=options, antidetect=True) as browser:
    tab = await browser.new_tab()
```

---

## Cloudflare Turnstile

```python
async with tab.expect_and_bypass_cloudflare_captcha():
    await tab.navigate("https://site-with-turnstile.com")
```

> This is not a guaranteed bypass. Results depend on browser environment, network, IP reputation, and the challenge itself.

---

## Retry Decorator

```python
from pyfox.decorators import retry


@retry(max_retries=3, exponential_backoff=True)
async def scrape():
    ...
```

Custom recovery logic can be executed between attempts.

---

## Supported Browsers

pyfox targets Firefox and Firefox-based browsers with WebDriver BiDi support.

Tested or targeted: Firefox, Zen Browser, Floorp, LibreWolf, and Waterfox. Any Firefox-based browser with WebDriver BiDi support should work.

---

## Architecture

pyfox uses a single WebSocket connection per browser instance, shared across all tabs.

```
Firefox
   │
WebDriver BiDi (WebSocket)
   │
ConnectionHandler
   ├── Tab ── WebElement
   ├── Tab ── WebElement
   └── Tab ── WebElement
```

```
pyfox/
├── antidetect/    # ForgeAPI and preload scripts
├── browser/       # Firefox, Tab, FirefoxOptions, downloads, requests
├── connection/    # ConnectionHandler, CommandsManager, EventsManager
├── elements/      # WebElement, ShadowRoot, FindElementsMixin
├── extractor/     # Pydantic structured extraction
├── interactions/  # Mouse, Keyboard, Scroll
└── protocol/      # WebDriver BiDi protocol builders
```

---

## Dependencies

```
websockets>=12.0
aiofiles>=23.0
pydantic>=2.0
typing-extensions>=4.9
```

---

## Pydoll

pyfox follows a similar API philosophy to Pydoll, targeting Firefox via WebDriver BiDi instead of Chromium via CDP.

| Feature               | Pydoll   | pyfox      |
|-----------------------|----------|----------------|
| Browser               | Chromium | Firefox        |
| Protocol              | CDP      | WebDriver BiDi |
| Async API             | ✓        | ✓              |
| WebDriver binary      | ✗        | ✗              |
| Multiple tabs         | ✓        | ✓              |
| Browser contexts      | ✓        | ✓              |
| Shadow DOM            | ✓        | ✓              |
| Network interception  | ✓        | ✓              |
| HAR recording         | ✓        | ✓              |
| Humanized mouse       | ✓        | ✓              |
| Humanized keyboard    | ✓        | ✓              |
| Structured extraction | ✓        | ✓              |
| Retry decorator       | ✓        | ✓              |
| Downloads             | ✓        | ✓              |
| Firefox support       | ✗        | ✓              |
| Chromium support      | ✓        | ✗              |

---

## Limitations

These are protocol-level differences, not missing wrappers:

- Chromium and Chrome are not supported
- `navigator.webdriver` remains `true` under Firefox WebDriver BiDi (W3C spec behavior)
- No direct equivalent to CDP's file chooser APIs
- Response bodies are only accessible during an active network interception workflow

---

## Project Status

Version `0.1.0` - 119 unit tests, 204 integration tests (run against real Firefox on Windows).

---

## Contributing

Issues and pull requests are welcome. When reporting a bug, include enough information to reproduce it - browser version, OS, and a minimal script if possible.

---

## License

MIT
