pybridge-browser
Take over and control your already-open browser — no debug port, no browser restart. Playwright-style API backed by a lightweight Chrome extension.
[!IMPORTANT] This Python package requires the PyBridge browser extension to work. Download it here: PyBridge - Python WebSocket Bridge
Why pybridge-browser?
Traditional browser automation (Selenium, Playwright, Puppeteer) launches a new browser instance or connects via --remote-debugging-port. That means:
- ❌ You lose your login sessions, cookies, and extensions.
- ❌ You need to restart the browser with special flags.
- ❌ Anti-bot detection flags automated fingerprints.
pybridge-browser takes a different approach: it uses a Chrome extension (chrome.debugger API) to attach to your already-running browser — keeping everything intact.
| Feature | pybridge-browser | Playwright | Selenium |
|---|---|---|---|
| Keeps login state | ✅ | ❌ | ❌ |
| Keeps extensions | ✅ | ❌ | ❌ |
| No browser restart | ✅ | ❌ | ❌ |
| No debug port | ✅ | ❌ | ❌ |
| Playwright-style API | ✅ | ✅ | ❌ |
Installation
pip install pybridge-browser
Prerequisites (one-time setup)
⚠️ Required companion extension: This package does NOT work standalone. You must first install the PyBridge browser extension: PyBridge - Python WebSocket Bridge
-
Load the PyBridge extension — download the extension from PyBridge - Python WebSocket Bridge, then open
chrome://extensions, enable Developer mode (top-right toggle), click Load unpacked, and select the downloaded PyBridge extension directory. -
Keep your browser open with at least one normal web page tab.
Quick Start
import pybridge_browser
# Connect to the PyBridge extension and auto-attach to the active tab
browser = pybridge_browser.connect()
page = browser.page
# Navigate
page.goto("https://example.com")
# Interact
page.click("button#submit")
page.fill("#username", "hello")
page.fill("#password", "world")
# Screenshot
page.screenshot("screenshot.png")
# Get page info
print(page.title) # "Example Domain"
print(page.url) # "https://example.com"
# Execute JavaScript
result = page.evaluate("document.querySelectorAll('a').length")
# Disconnect (browser stays open)
browser.close()
Context manager
with pybridge_browser.connect() as browser:
page = browser.page
page.goto("https://example.com")
print(page.title)
# browser.close() called automatically
API Reference
pybridge_browser.connect(port=8765, hello_timeout=100, verbose=True, auto_attach=True, tab_id=None)
Connect to the PyBridge extension. Returns a Browser object.
| Parameter | Default | Description |
|---|---|---|
port |
8765 |
WebSocket bridge port (must match extension config) |
hello_timeout |
100 |
Max seconds to wait for the extension handshake |
verbose |
True |
Print progress info |
auto_attach |
True |
Auto-attach to the active tab on connect |
tab_id |
None |
Specific tab to attach to (default: active tab) |
Browser
| Method / Property | Description |
|---|---|
browser.page |
Get the current attached Page object |
browser.pages |
List of attached pages (always length 1) |
browser.list_tabs() |
List attachable tabs: [{tabId, url, title, active}] |
browser.attach(tab_id) |
Attach to a specific tab |
browser.detach() |
Detach from current tab (browser stays connected) |
browser.close() |
Detach + shut down bridge (browser stays open) |
Page
| Method / Property | Description |
|---|---|
page.goto(url, timeout=60) |
Navigate and wait for load |
page.click(selector, timeout=30) |
Click element (mouse + JS fallback) |
page.fill(selector, value, timeout=30) |
Fill input (React-compatible) |
page.type_text(selector, text, timeout=30) |
Type text via CDP (keystroke-level) |
page.press(selector, key, timeout=30) |
Press a key on an element |
page.key_press(key) |
Send key to focused element |
page.inner_text(selector, timeout=30) |
Get element's visible text |
page.text_content(selector, timeout=30) |
Get element's textContent |
page.get_attribute(selector, name, timeout=30) |
Get element attribute |
page.select_option(selector, value, timeout=30) |
Set <select> value |
page.is_visible(selector, timeout=5) |
Check if element is visible |
page.wait_for_selector(selector, timeout=30) |
Wait for element to appear |
page.wait_for_load_state(state="load", timeout=60) |
Wait for page load |
page.screenshot(path=None, full_page=False) |
Take screenshot (PNG) |
page.evaluate(js, timeout=30) |
Execute JavaScript |
page.content() |
Get page HTML |
page.title |
Page title (property) |
page.url |
Page URL (property) |
Exceptions
| Exception | Description |
|---|---|
PyBridgeError |
Base exception |
PyBridgeTimeoutError |
Operation timed out |
TimeoutError |
Alias for PyBridgeTimeoutError |
ElementNotFoundError |
Element not found within timeout |
CLI Usage
# Connect and enter interactive console
pybridge-browser
# Or via module
python -m pybridge_browser
# List attachable tabs
python -m pybridge_browser --list
# Open URL then enter console
python -m pybridge_browser --url https://example.com
# Attach to specific tab
python -m pybridge_browser --tab 123
# Direct URL (positional argument)
python -m pybridge_browser https://example.com
Console commands
tabs List tabs
attach <id> Attach to tab
nav <url> Navigate
eval <js> Execute JavaScript
click <sel> Click element
fill <sel> <value> Fill input
shot [path] Screenshot
title Print page title
url Print page URL
detach Detach from tab
quit Exit
How It Works
┌─────────────┐ WebSocket (ws://127.0.0.1:8765) ┌──────────────────┐
│ Python │◄──────────────────────────────────────►│ Chrome Extension │
│ pybridge_ │ │ (chrome.debugger)│
│ browser │ CDP commands / responses │ │
│ │◄──────────────────────────────────────►│ ▼ │
└─────────────┘ │ Active Tab │
│ (your webpage) │
└──────────────────┘
- Python starts a local WebSocket server on port 8765.
- The Chrome extension connects to it.
- Python sends CDP (Chrome DevTools Protocol) commands through the extension's
chrome.debuggerAPI. - The extension forwards commands to the tab and returns results.
No remote debugging port is opened. No new browser is launched.
Dependencies
- Python 3.8+
websockets>= 12.0
License
Author
Walker Deng — walker.deng@acqu.co
中文文档
为什么用 pybridge-browser?
传统浏览器自动化(Selenium、Playwright、Puppeteer)需要启动新浏览器或通过 --remote-debugging-port 连接,这意味着:
- ❌ 丢失登录状态、Cookie 和扩展
- ❌ 需要重启浏览器并加特殊参数
- ❌ 容易被反爬检测
pybridge-browser 通过 Chrome 扩展(chrome.debugger API)直接接管已打开的浏览器,保留一切现场。
安装
pip install pybridge-browser
前置条件(一次性)
⚠️ 必须搭配浏览器插件才能正常使用:本包不能独立工作,需要先安装 PyBridge 浏览器扩展: PyBridge - Python WebSocket Bridge
-
加载 PyBridge 扩展 — 从 PyBridge - Python WebSocket Bridge 下载扩展,然后打开
chrome://extensions,开启右上角开发者模式,点击加载已解压的扩展程序,选择下载好的 PyBridge 扩展目录。 -
保持浏览器打开,且至少有一个普通网页标签页。
快速上手
import pybridge_browser
browser = pybridge_browser.connect()
page = browser.page
page.goto("https://example.com")
page.click("button#submit")
page.fill("#username", "hello")
page.screenshot("shot.png")
print(page.title, page.url)
browser.close() # 断开接管,浏览器保持打开
工作原理
Python 启动本地 WebSocket 服务 → Chrome 扩展连接 → 通过 chrome.debugger API 转发 CDP 命令到标签页。不开调试端口、不重启浏览器。
依赖
- Python 3.8+
websockets>= 12.0
许可证
Release files for pybridge-browser 0.1.0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| pybridge_browser-0.1.0.tar.gz | 20.0 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| pybridge_browser-0.1.0-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 39.6 kB
Release files / pybridge_browser-0.1.0.tar.gz
| Download URL | pybridge_browser-0.1.0.tar.gz |
|---|---|
| Size | 20.0 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
c36b9a0f9f373804e4949f6513c291482e88e734e608cb2ab72601541662d3ec
|
|
BLAKE2b-256 checksum How to use checksums |
d641cdaea55b0921214ca7204671dfc43d488fdbdb830b3b3dffe6edf0cc39d9
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
python-requests/2.34.2
|
Release files / pybridge_browser-0.1.0-py3-none-any.whl
| Download URL | pybridge_browser-0.1.0-py3-none-any.whl |
|---|---|
| Size | 19.6 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
3915ac40f1792d5843b0d70e6c0089316939694a381ec28d830eaa1f126157d8
|
|
BLAKE2b-256 checksum How to use checksums |
77bc385b1483b54344281494a01cf9b22ebe6d1b12c2fa9c2f44b4aa433a408d
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
python-requests/2.34.2
|