Metadata-Version: 2.4
Name: pybroswer
Version: 0.5.1
Summary: Headless Python browser for PyDroid. DOM, XPath, cookies, HTTP status, tabs. Not webbrowser.
Author: Hacker78
License: MIT
Project-URL: Homepage, https://github.com/prateeknishad305/Pybrowser
Keywords: playwright,chromium,browser,pydroid,remote,automation
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.10
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Programming Language :: Python :: 3.13
Classifier: Typing :: Typed
Requires-Python: >=3.10
Description-Content-Type: text/markdown
Requires-Dist: httpx>=0.27
Provides-Extra: chromium
Requires-Dist: playwright>=1.40; extra == "chromium"
Provides-Extra: dev
Requires-Dist: pytest>=8.0; extra == "dev"

# pybrowser

Python browser for **PyDroid**. No Chromium, Playwright, or PC host is required on the phone.

Fixes Python `webbrowser` gaps: click/fill/scrape, CSS + XPath, HTTP status, cookies, tab reuse/close, headless (no GUI). `Browser.launch()` fetches pages with httpx and parses HTML. Optional remote Chromium on PC.

## Install (PyDroid)

```bash
pip install -U pybroswer
```

Import name:

```python
from pybrowser import Browser
```

`from pybroswer import Browser` still works.

Check:

```python
import pybrowser
print(pybrowser.__version__, pybrowser.__file__)
```

## PyDroid usage

```python
from pybrowser import Browser

with Browser.launch() as browser:
    shot = browser.browse("https://example.com")
    print(shot.title, shot.url, shot.text)

    with browser.create_session(device="mobile") as page:
        page.goto("https://example.com")
        print(page.title(), page.url())
        print(page.text()[:200])
        print(page.links())
        print(page.cookies())

        # Click first real link, or pass CSS / visible text:
        # page.click()
        # page.click("a#login")
        # page.click(text="More information")
        # page.click("text=More information")
        # page.fill({"q": "hello"})
        # page.press("Enter", selector="input[name=q]")
```

`Browser()` with no URL also starts the local HTTP engine.

## Optional: PC Chromium

If you want real Chromium on a PC:

```bash
pip install "pybroswer[chromium]"
playwright install chromium
python -m pybrowser serve --port 5173
```

From PyDroid:

```python
from pybrowser import Browser
with Browser.connect("http://192.168.1.10:5173") as browser:
    ...
```

In-process on PC: `Browser.launch(engine="chromium")`.

## Limits (phone HTTP engine)

- JS-heavy SPAs are not rendered (you get the HTML the server sent)
- Screenshot is a 1x1 placeholder PNG
- `evaluate` only supports simple `document.title` / `querySelector` expressions
- Iframe contents are not fetched separately
- Click coordinates (`x, y`) require Chromium

Forms, links, cookies, downloads, type/press/select, headers, and redirects work.

Beyond `webbrowser.open(url)`:

```python
from pybrowser import Browser

browser = Browser.launch()
browser.open("https://example.com")   # webbrowser-compatible
with browser.create_session() as page:
    page.goto("https://httpbin.org/forms/post")
    page.fill({"custname": "Ada", "custtel": "123"})
    page.click("text=Submit")
    print(page.cookies())
    file = page.download("https://example.com/favicon.ico")
    print(file["filename"], file["bytes"])
```

## API

| Method | |
|--------|--|
| `Browser.launch()` | local HTTP engine (PyDroid default) |
| `Browser.launch(engine="chromium")` | Playwright Chromium (PC) |
| `Browser.connect(url)` | remote REST |
| `browser.browse(url)` | one-shot open |
| `page.goto` / `click` / `type` / `press` / `select` | session actions |
| `page.click(text="Login")` / `page.fill({...})` | text click, form fill |
| `page.cookies()` / `page.download(url)` | cookies and files |
| `page.links()` / `page.query(selector)` | page query |
| `page.xpath("//a")` / `page.scrape("a", attr="href")` | XPath and scrape |
| `page.status()` / `page.ok()` / `page.response_headers()` | HTTP response |
| `browser.open(url)` / `browser.open(url, new=0)` | reuse tab, no spam |
| `browser.new_tab(url)` / `browser.close_all()` | tab control |
| `page.evaluate("document.title")` | read page |
| `page.html()` / `page.inspect(selector)` | DOM |
