Control a headless or headed Chrome browser via Pinchtab's HTTP API. Use for web automation, scraping, form filling, navigation, and multi-tab workflows. Pinchtab exposes the accessibility tree as flat JSON with stable refs — optimized for AI agents (low token cost, fast). Use when the task involves: browsing websites, filling forms, clicking buttons, extracting page text, taking screenshots, or any browser-based automation. Requires a running Pinchtab instance (Go binary).
Installer avec Codex ou Claude Copiez ce prompt, collez-le dans Codex, Claude ou un autre assistant, puis laissez-le vérifier la page du skill et l'installer pour vous.
Une commande directe contourne le prompt de vérification. Examinez la source avant de l'exécuter.
Control a headless or headed Chrome browser via Pinchtab's HTTP API. Use for web automation, scraping, form filling, navigation, and multi-tab workflows. Pinchtab exposes the accessibility tree as flat JSON with stable refs — optimized for AI agents (low token cost, fast). Use when the task involves: browsing websites, filling forms, clicking buttons, extracting page text, taking screenshots, or any browser-based automation. Requires a running Pinchtab instance (Go binary).
homepage
https://pinchtab.com
metadata
{"openclaw":{"emoji":"🦀","requires":{"bins":["pinchtab"],"env":[{"name":"BRIDGE_TOKEN","secret":true,"optional":true,"description":"Bearer auth token for Pinchtab API"},{"name":"BRIDGE_BIND","optional":true,"description":"Bind address (default: 127.0.0.1, set 0.0.0.0 for network access)"},{"name":"BRIDGE_PORT","optional":true,"description":"HTTP port (default: 9867)"},{"name":"BRIDGE_HEADLESS","optional":true,"description":"Run Chrome headless (true/false)"},{"name":"BRIDGE_PROFILE","optional":true,"description":"Chrome profile directory (default: ~/.pinchtab/chrome-profile)"},{"name":"BRIDGE_STATE_DIR","optional":true,"description":"State/session storage directory (default: ~/.pinchtab)"},{"name":"BRIDGE_NO_RESTORE","optional":true,"description":"Skip restoring tabs from previous session (true/false)"},{"name":"BRIDGE_STEALTH","optional":true,"description":"Stealth level: light (default, basic) or full (canvas/WebGL/font spoofing)"},{"name":"BRIDGE_MAX_TABS","optional":true,"description":"Maximum number of open tabs (default: 20, 0 = unlimited)"},{"name":"BRIDGE_BLOCK_IMAGES","optional":true,"description":"Block image loading for faster, lower-bandwidth browsing (true/false)"},{"name":"BRIDGE_BLOCK_MEDIA","optional":true,"description":"Block all media: images + fonts + CSS + video (true/false)"},{"name":"BRIDGE_NO_ANIMATIONS","optional":true,"description":"Disable CSS animations/transitions globally (true/false)"},{"name":"BRIDGE_TIMEZONE","optional":true,"description":"Force browser timezone (IANA tz, e.g. Europe/Rome)"},{"name":"BRIDGE_CHROME_VERSION","optional":true,"description":"Chrome version string used by fingerprint rotation profiles"},{"name":"CHROME_BINARY","optional":true,"description":"Path to Chrome/Chromium binary (auto-detected if not set)"},{"name":"CHROME_FLAGS","optional":true,"description":"Extra Chrome flags, space-separated"},{"name":"BRIDGE_CONFIG","optional":true,"description":"Path to config JSON file (default: ~/.pinchtab/config.json)"},{"name":"BRIDGE_TIMEOUT","optional":true,"description":"Action timeout in seconds (default: 15)"},{"name":"BRIDGE_NAV_TIMEOUT","optional":true,"description":"Navigation timeout in seconds (default: 30)"},{"name":"CDP_URL","optional":true,"description":"Connect to existing Chrome DevTools instead of launching"},{"name":"BRIDGE_NO_DASHBOARD","optional":true,"description":"Disable dashboard/orchestrator endpoints on instance processes"},{"name":"PINCHTAB_AUTO_LAUNCH","optional":true,"description":"Dashboard mode: auto-launch default profile instance on startup"},{"name":"PINCHTAB_DEFAULT_PROFILE","optional":true,"description":"Dashboard mode: default profile name for auto-launch"},{"name":"PINCHTAB_DEFAULT_PORT","optional":true,"description":"Dashboard mode: default port for auto-launched profile"},{"name":"PINCHTAB_HEADED","optional":true,"description":"Dashboard mode: when set, auto-launched profile runs headed"},{"name":"PINCHTAB_DASHBOARD_URL","optional":true,"description":"Base dashboard URL used by `pinchtab connect` helper"}]}}}
Pinchtab
Fast, lightweight browser control for AI agents via HTTP + accessibility tree.
Setup
Start Pinchtab in one of these modes:
# Headless (default) — no UI, pure automation (lowest token cost when using /text and filtered snapshots)
pinchtab &
# Headed — visible Chrome for human + agent workflows
BRIDGE_HEADLESS=false pinchtab &
# Dashboard/orchestrator — profile manager + launcher, no browser in dashboard process
pinchtab dashboard &
Default port: 9867. Override with BRIDGE_PORT=9868.
Auth: set BRIDGE_TOKEN=<secret> and pass Authorization: Bearer <secret>.
Base URL for all examples: http://localhost:9867
Token savings come from the API shape (/text, /snapshot?filter=interactive&format=compact), not from headless vs headed alone.
Headed mode definition
Headed mode means a real visible Chrome window managed by Pinchtab.
Human can open profile(s), log in, pass 2FA/captcha, and validate page state
Agent then calls Pinchtab HTTP APIs against that same running profile instance
Session state persists in the profile directory, so follow-up runs reuse cookies/storage
In dashboard workflows, the dashboard process itself does not launch Chrome; it launches profile instances that run Chrome (headed or headless).
To resolve a running profile endpoint from dashboard state:
When running pinchtab dashboard, profiles are managed via the dashboard API on port 9867.
List profiles
curl http://localhost:9867/profiles
Returns array of profiles with id, , , , etc.
name
accountEmail
useWhen
Start a profile by ID
# Auto-allocate port (recommended)
curl -X POST http://localhost:9867/profiles/278be873adeb/start
# With specific port and headless mode
curl -X POST http://localhost:9867/profiles/278be873adeb/start \
-H 'Content-Type: application/json' \
-d '{"port": "9868", "headless": true}'# Short alias (same behavior)
curl -X POST http://localhost:9867/start/278be873adeb
Returns the instance info including the allocated port. Use that port for all subsequent API calls (navigate, snapshot, action, etc.).
Stop a profile by ID
curl -X POST http://localhost:9867/profiles/278be873adeb/stop
# Short alias
curl -X POST http://localhost:9867/stop/278be873adeb
Check profile instance status
# By profile ID (recommended)
curl http://localhost:9867/profiles/278be873adeb/instance
# By profile name (also works)
curl http://localhost:9867/profiles/Pinchtab%20org/instance
# 1. List profiles to find the right one
PROFILES=$(curl -s http://localhost:9867/profiles)
# Pick the profile ID you need (12-char hex, e.g. "278be873adeb")# 2. Start the profile (auto-allocates port)
INSTANCE=$(curl -s -X POST http://localhost:9867/profiles/$PROFILE_ID/start)
PORT=$(echo$INSTANCE | jq -r .port)
# 3. Use the instance (all API calls go to the instance port)
curl -X POST http://localhost:$PORT/navigate -H 'Content-Type: application/json' \
-d '{"url": "https://mail.google.com"}'
curl http://localhost:$PORT/snapshot?maxTokens=4000
# 4. Check instance status
curl http://localhost:9867/profiles/$PROFILE_ID/instance
# 5. Stop when done
curl -s -X POST http://localhost:9867/profiles/$PROFILE_ID/stop
Profile IDs
Each profile gets a stable 12-char hex ID (SHA-256 of name, truncated) stored in profile.json. The ID is generated at creation time and never changes. Use IDs instead of names in automation — they're URL-safe and stable.
Core Workflow
The typical agent loop:
Navigate to a URL
Snapshot the accessibility tree (get refs)
Act on refs (click, type, press)
Snapshot again to see results
Refs (e.g. e0, e5, e12) are cached per tab after each snapshot — no need to re-snapshot before every action unless the page changed significantly.
API Reference
Navigate
curl -X POST http://localhost:9867/navigate \
-H 'Content-Type: application/json' \
-d '{"url": "https://example.com"}'# With options: custom timeout, block images, open in new tab
curl -X POST http://localhost:9867/navigate \
-H 'Content-Type: application/json' \
-d '{"url": "https://example.com", "timeout": 60, "blockImages": true, "newTab": true}'
Snapshot (accessibility tree)
# Full tree
curl http://localhost:9867/snapshot
# Interactive elements only (buttons, links, inputs) — much smaller
curl "http://localhost:9867/snapshot?filter=interactive"# Limit depth
curl "http://localhost:9867/snapshot?depth=5"# Smart diff — only changes since last snapshot (massive token savings)
curl "http://localhost:9867/snapshot?diff=true"# Text format — indented tree, ~40-60% fewer tokens than JSON
curl "http://localhost:9867/snapshot?format=text"# Compact format — one-line-per-node, 56-64% fewer tokens than JSON (recommended)
curl "http://localhost:9867/snapshot?format=compact"# YAML format
curl "http://localhost:9867/snapshot?format=yaml"# Scope to CSS selector (e.g. main content only)
curl "http://localhost:9867/snapshot?selector=main"# Truncate to ~N tokens
curl "http://localhost:9867/snapshot?maxTokens=2000"# Combine for maximum efficiency
curl "http://localhost:9867/snapshot?format=compact&selector=main&maxTokens=2000&filter=interactive"# Disable animations before capture
curl "http://localhost:9867/snapshot?noAnimations=true"# Write to file
curl "http://localhost:9867/snapshot?output=file&path=/tmp/snapshot.json"
Returns flat JSON array of nodes with ref, role, name, depth, value, nodeId.
Token optimization: Use ?format=compact for best token efficiency. Add ?filter=interactive for action-oriented tasks (~75% fewer nodes). Use ?selector=main to scope to relevant content. Use ?maxTokens=2000 to cap output. Use ?diff=true on multi-step workflows to see only changes. Combine all params freely.
Act on elements
# Click by ref
curl -X POST http://localhost:9867/action \
-H 'Content-Type: application/json' \
-d '{"kind": "click", "ref": "e5"}'# Type into focused element (click first, then type)
curl -X POST http://localhost:9867/action \
-H 'Content-Type: application/json' \
-d '{"kind": "click", "ref": "e12"}'
curl -X POST http://localhost:9867/action \
-H 'Content-Type: application/json' \
-d '{"kind": "type", "ref": "e12", "text": "hello world"}'# Press a key
curl -X POST http://localhost:9867/action \
-H 'Content-Type: application/json' \
-d '{"kind": "press", "key": "Enter"}'# Focus an element
curl -X POST http://localhost:9867/action \
-H 'Content-Type: application/json' \
-d '{"kind": "focus", "ref": "e3"}'# Fill (set value directly, no keystrokes)
curl -X POST http://localhost:9867/action \
-H 'Content-Type: application/json' \
-d '{"kind": "fill", "selector": "#email", "text": "user@example.com"}'# Hover (trigger dropdowns/tooltips)
curl -X POST http://localhost:9867/action \
-H 'Content-Type: application/json' \
-d '{"kind": "hover", "ref": "e8"}'# Select dropdown option (by value or visible text)
curl -X POST http://localhost:9867/action \
-H 'Content-Type: application/json' \
-d '{"kind": "select", "ref": "e10", "value": "option2"}'# Scroll to element
curl -X POST http://localhost:9867/action \
-H 'Content-Type: application/json' \
-d '{"kind": "scroll", "ref": "e20"}'# Scroll by pixels (infinite scroll pages)
curl -X POST http://localhost:9867/action \
-H 'Content-Type: application/json' \
-d '{"kind": "scroll", "scrollY": 800}'# Click and wait for navigation (link clicks)
curl -X POST http://localhost:9867/action \
-H 'Content-Type: application/json' \
-d '{"kind": "click", "ref": "e5", "waitNav": true}'
Returns {url, title, text}. Cheapest option (~1K tokens for most pages).
Download files
# Download using browser session (preserves cookies, auth, stealth)# Returns base64 JSON by default
curl "http://localhost:9867/download?url=https://site.com/report.pdf"# Raw bytes (pipe to file)
curl "http://localhost:9867/download?url=https://site.com/image.jpg&raw=true" -o image.jpg
# Save directly to disk
curl "http://localhost:9867/download?url=https://site.com/export.csv&output=file&path=/tmp/export.csv"
Key use case: downloading files from authenticated sites — the browser's cookies and stealth settings are used automatically. No need to extract cookies and use curl separately.
Upload files
# Upload a local file to a file input
curl -X POST "http://localhost:9867/upload?tabId=TAB_ID" \
-H "Content-Type: application/json" \
-d '{"selector": "input[type=file]", "paths": ["/tmp/photo.jpg"]}'# Upload base64-encoded data
curl -X POST "http://localhost:9867/upload" \
-H "Content-Type: application/json" \
-d '{"selector": "#avatar-input", "files": ["data:image/png;base64,iVBOR..."]}'# Combine both — local files + base64
curl -X POST "http://localhost:9867/upload" \
-H "Content-Type: application/json" \
-d '{"selector": "input[type=file]", "paths": ["/tmp/doc.pdf"], "files": ["data:image/png;base64,..."]}'
Sets files on <input type=file> elements via CDP. The browser fires change events as if the user picked files. Selector defaults to input[type=file] if omitted. Supports base64 data URLs, raw base64 strings, and local file paths.
Screenshot
# Raw JPEG bytes
curl "http://localhost:9867/screenshot?raw=true" -o screenshot.jpg
# With quality setting (default 80)
curl "http://localhost:9867/screenshot?raw=true&quality=50" -o screenshot.jpg
# List tabs
curl http://localhost:9867/tabs
# Open new tab
curl -X POST http://localhost:9867/tab \
-H 'Content-Type: application/json' \
-d '{"action": "new", "url": "https://example.com"}'# Close tab
curl -X POST http://localhost:9867/tab \
-H 'Content-Type: application/json' \
-d '{"action": "close", "tabId": "TARGET_ID"}'
Multi-tab: pass ?tabId=TARGET_ID to snapshot/screenshot/text, or "tabId" in POST body.
Tab locking (multi-agent)
# Lock a tab (default 30s timeout, max 5min)
curl -X POST http://localhost:9867/tab/lock \
-H 'Content-Type: application/json' \
-d '{"tabId": "TARGET_ID", "owner": "agent-1", "timeoutSec": 60}'# Unlock
curl -X POST http://localhost:9867/tab/unlock \
-H 'Content-Type: application/json' \
-d '{"tabId": "TARGET_ID", "owner": "agent-1"}'
Locked tabs show owner and lockedUntil in /tabs. Returns 409 on conflict.
Batch actions
# Execute multiple actions in sequence
curl -X POST http://localhost:9867/actions \
-H 'Content-Type: application/json' \
-d '{"actions":[{"kind":"click","ref":"e3"},{"kind":"type","ref":"e3","text":"hello"},{"kind":"press","key":"Enter"}]}'# Stop on first error (default: false, continues through all)
curl -X POST http://localhost:9867/actions \
-H 'Content-Type: application/json' \
-d '{"tabId":"TARGET_ID","actions":[...],"stopOnError":true}'
Cookies
# Get cookies for current page
curl http://localhost:9867/cookies
# Set cookies
curl -X POST http://localhost:9867/cookies \
-H 'Content-Type: application/json' \
-d '{"url":"https://example.com","cookies":[{"name":"session","value":"abc123"}]}'
Stealth
# Check stealth status and score
curl http://localhost:9867/stealth/status
# Rotate browser fingerprint
curl -X POST http://localhost:9867/fingerprint/rotate \
-H 'Content-Type: application/json' \
-d '{"os":"windows"}'# os: "windows", "mac", or omit for random
Health check
curl http://localhost:9867/health
Token Cost Guide
Method
Typical tokens
When to use
/text
~800
Reading page content
/snapshot?filter=interactive
~3,600
Finding buttons/links to click
/snapshot?diff=true
varies
Multi-step workflows (only changes)
/snapshot?format=compact
~56-64% less
One-line-per-node, best token efficiency
/snapshot?format=text
~40-60% less
Indented tree, cheaper than JSON
/snapshot
~10,500
Full page understanding
/screenshot
~2K (vision)
Visual verification
Strategy: Start with /snapshot?filter=interactive. Use ?diff=true on subsequent snapshots in multi-step tasks. Use /text when you only need the readable content. Use ?format=text to cut token costs further. Use full /snapshot only for complete page understanding.
Environment Variables
Core runtime
Var
Default
Description
BRIDGE_BIND
127.0.0.1
Bind address — localhost only by default. Set 0.0.0.0 for network access
BRIDGE_PORT
9867
HTTP port
BRIDGE_HEADLESS
true
Run Chrome headless
BRIDGE_TOKEN
(none)
Bearer auth token (recommended when using BRIDGE_BIND=0.0.0.0)
BRIDGE_PROFILE
~/.pinchtab/chrome-profile
Chrome profile dir
BRIDGE_STATE_DIR
~/.pinchtab
State/session storage
BRIDGE_NO_RESTORE
false
Skip tab restore on startup
BRIDGE_STEALTH
light
Stealth level: light or full
BRIDGE_MAX_TABS
20
Max open tabs (0 = unlimited)
BRIDGE_BLOCK_IMAGES
false
Block image loading
BRIDGE_BLOCK_MEDIA
false
Block all media (images + fonts + CSS + video)
BRIDGE_NO_ANIMATIONS
false
Disable CSS animations/transitions
BRIDGE_TIMEZONE
(none)
Force browser timezone (IANA tz)
BRIDGE_CHROME_VERSION
144.0.7559.133
Chrome version string used by fingerprint rotation
CHROME_BINARY
(auto)
Path to Chrome/Chromium binary
CHROME_FLAGS
(none)
Extra Chrome flags (space-separated)
BRIDGE_CONFIG
~/.pinchtab/config.json
Path to config JSON file
BRIDGE_TIMEOUT
15
Action timeout (seconds)
BRIDGE_NAV_TIMEOUT
30
Navigation timeout (seconds)
CDP_URL
(none)
Connect to existing Chrome DevTools
BRIDGE_NO_DASHBOARD
false
Disable dashboard/orchestrator endpoints on instance processes
Dashboard mode (pinchtab dashboard)
Var
Default
Description
PINCHTAB_AUTO_LAUNCH
false
Auto-launch a default profile at dashboard startup
PINCHTAB_DEFAULT_PROFILE
default
Profile name for auto-launch
PINCHTAB_DEFAULT_PORT
9867
Port for auto-launched profile
PINCHTAB_HEADED
(unset)
If set, auto-launched profile is headed; unset means headless
PINCHTAB_DASHBOARD_URL
http://localhost:$BRIDGE_PORT
CLI helper base URL for pinchtab connect
Tips
Always pass tabId explicitly when working with multiple tabs — active tab tracking can be unreliable
Refs are stable between snapshot and actions — no need to re-snapshot before clicking
After navigation or major page changes, take a new snapshot to get fresh refs
Use filter=interactive by default, fall back to full snapshot when needed
Pinchtab persists sessions — tabs survive restarts (disable with BRIDGE_NO_RESTORE=true)
Chrome profile is persistent — cookies/logins carry over between runs
Chrome uses its native User-Agent by default — BRIDGE_CHROME_VERSION only affects fingerprint rotation
Use BRIDGE_BLOCK_IMAGES=true or "blockImages": true on navigate for read-heavy tasks — reduces bandwidth and memory