Quay combines Chrome DevTools Protocol with accessibility-tree semantics for browser automation using your authenticated Chrome sessions.
| Feature | Quay | Playwright | agent-browser | Raw CDP |
|---|---|---|---|---|
| Full AX tree (raw CDP nodes) | ✅ | ❌ Simplified snapshot only | ✅ | ❌ |
| AX ref targeting | ✅ | ❌ | ✅ | ❌ |
| Uses your logged-in Chrome | ✅ | ❌ | ❌ | ✅ |
| Connection pooling | ✅ | ✅ BrowserContext | ❌ | ❌ |
| Auto-reconnect | ✅ | ❌ | ❌ | ❌ |
| Python-native | ✅ | ✅ | ❌ JS/TS | ❌ |
| Session recording | ✅ | ✅ Codegen/trace | ❌ | ❌ |
| Package size | ~20KB | ~50MB | ~5MB | ~5KB |
Quay's niche: Full Chrome accessibility tree + your existing authenticated sessions.
pip install quayOr from source:
git clone https://github.com/sidonsoft/quay
cd quay
pip install -e .Chrome must be running with remote debugging enabled:
# macOS
/Applications/Google\ Chrome.app/Contents/MacOS/Google\ Chrome --remote-debugging-port=9222
# Linux
google-chrome --remote-debugging-port=9222
# Windows
"C:\Program Files\Google\Chrome\Application\chrome.exe" --remote-debugging-port=9222Or use the included launcher:
./scripts/chrome-debug.shfrom quay import Browser
browser = Browser()
browser.goto("https://gmail.com") # Uses your logged-in session
tree = browser.accessibility_tree()
print(tree.to_tree_str())
browser.click_by_text("Sign in")
browser.fill_form({"Email": "[email protected]"})# List tabs
quay list
# Open new tab
quay new https://example.com
# Get accessibility tree
quay snapshot
# Take screenshot
quay screenshot
# Click by text
quay click "Submit"| Feature | Description |
|---|---|
| Accessibility Tree | Navigate pages using AX nodes like agent-browser |
| Session Reuse | Uses your existing Chrome session (no separate browser) |
| Connection Pooling | WebSocket reuse across operations for speed |
| Auto-Reconnect | Automatically reconnects on connection drop |
| Session Recording | Record and replay browser actions |
| Form Filling | Fill forms by label text |
| Click by Text | Click elements matching visible text |
| JavaScript Eval | Run arbitrary JavaScript |
Quay automatically detects dropped connections and reconnects:
browser = Browser(reconnect=True, reconnect_max_retries=3)
# If connection drops during operation,
# Quay will attempt to reconnect automatically
tree = browser.accessibility_tree() # May auto-reconnect if neededMonitor reconnection with a callback:
def on_reconnect(msg):
print(f"Reconnecting: {msg}")
browser = Browser(reconnect_callback=on_reconnect)Quay uses a mixin-based architecture for maintainability:
class Browser(
BrowserCoreMixin, # Connection lifecycle
BrowserTabsMixin, # Tab management
BrowserCDPMixin, # Low-level CDP
BrowserNavigationMixin, # Navigation
BrowserWaitMixin, # Wait methods
BrowserAccessibilityMixin, # Accessibility tree
BrowserActionsMixin, # User actions
BrowserRecordingMixin, # Session recording
):
passSee docs/internals/ARCHITECTURE.md for details.
Apache-2.0 - See LICENSE for details.