๐ŸŒŠ Chrome DevTools Protocol + Accessibility Tree ยท v0.2.8

Quay

Chrome DevTools Protocol with accessibility-tree semantics for browser automation using your authenticated Chrome sessions. v0.2.8 (Oct 2026) adds an MCP server โ€” drive your real logged-in Chrome from Claude Code, Codex, or OpenClaw over stdio.

Why Quay?

Feature Quay Playwright agent-browser Raw CDP
Full AX tree (raw CDP nodes) โœ… โŒ Simplified snapshot only โœ… โŒ
AX ref targeting โœ… Full CDP refs โš ๏ธ aria-snapshot refs, v1.64+ (get_by_ref) โœ… โŒ
MCP server โœ… quay mcp โœ… โœ… โŒ
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.

Installation

Install Quay via pip:

$ pip install quay

With the MCP server (for Claude Code, Codex, OpenClaw):

$ pip install "quay[mcp]"

Or from source:

$ git clone https://github.com/sidonsoft/quay
$ cd quay
$ pip install -e .

Prerequisites

Chrome must be running with remote debugging enabled:

# macOS
/Applications/Google\\ Chrome.app/Contents/MacOS/Google\\ Chrome --remote-debugging-port=9222 --user-data-dir="$HOME/.quay/chrome-debug-profile"

# Linux
google-chrome --remote-debugging-port=9222 --user-data-dir="$HOME/.quay/chrome-debug-profile"

# Windows
"C:\Program Files\Google\Chrome\Application\chrome.exe" --remote-debugging-port=9222 --user-data-dir="%USERPROFILE%\.quay\chrome-debug-profile"

Chrome 136+: the --remote-debugging-port flag is ignored on the default profile โ€” you must pass a separate --user-data-dir. Sign in once in that debug profile and your session persists.

Chrome 144+: Google added a consent prompt when attaching to a running Chrome. If you attach to a normal running Chrome (without the flags above), enable remote debugging at chrome://inspect/#remote-debugging and approve the per-connection prompt โ€” it currently can't be persisted. Launching Chrome with the flags above skips the prompt entirely.

Or use the included launcher (uses a persistent ~/.quay/chrome-debug-profile by default):

$ ./scripts/chrome-debug.sh

Quick Start

Python API

from 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": "user@example.com"})

CLI

# 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"

MCP Server

Expose Quay to MCP-capable agents (Claude Code, Codex, OpenClaw, โ€ฆ) driving your real logged-in Chrome over stdio:

$ pip install "quay[mcp]"
$ quay mcp --port 9222   # serves over stdio

10 tools: browser_status, open_tab, navigate, snapshot, click_text, click_ref, fill_form, evaluate, screenshot, close_tabs. The server instructions teach agents the status โ†’ snapshot โ†’ act-by-ref โ†’ verify loop.

Example Claude Code config entry:

{
  "mcpServers": {
    "quay": { "command": "quay", "args": ["mcp", "--port", "9222"] }
  }
}

See the MCP guide โ€” including the five-minute Quay + OpenClaw setup guide โ€” and the v0.2.8 release notes.

Features

  • โœ“
    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
  • โœ“
    MCP Server ยท new in v0.2.8
    quay mcp โ€” drive your real Chrome from any MCP agent (10 tools, stdio)

Automatic Reconnection

Quay automatically detects dropped connections and reconnects:

from quay import Browser

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 needed

Monitor reconnection with a callback:

def on_reconnect(msg):
    print(f"Reconnecting: {msg}")

browser = Browser(reconnect_callback=on_reconnect)

Architecture

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 ): pass

See docs/internals/ARCHITECTURE.md for details.

License

Quay is open source and available under the Apache 2.0 License. Current release: v0.2.8 (Oct 2026) โ€” see the full changelog.