Skip to main content

Documentation Index

Fetch the complete documentation index at: https://mintlify.com/pinchtab/pinchtab/llms.txt

Use this file to discover all available pages before exploring further.

Installation

Choose your preferred installation method:

5-Minute Quick Start

1

Start the Orchestrator

Open your first terminal and start the PinchTab orchestrator:
pinchtab
Expected output:
🦀 Pinchtab Dashboard port=9867
dashboard ready url=http://localhost:9867/dashboard
The orchestrator runs on http://127.0.0.1:9867 and manages all instances, profiles, and tabs. Open the dashboard in your browser to see real-time status.
2

Create an Instance

Open a second terminal and create a headless Chrome instance:
# Create headless instance (background Chrome)
INST=$(pinchtab instance launch --mode headless | jq -r '.id')
echo "Instance created: $INST"

# Wait for Chrome to initialize (~2-5 seconds)
sleep 3
Instances are auto-allocated unique ports (9868-9968). Chrome initializes lazily on first request.
3

Navigate to a Website

Create a tab and navigate to a website:
# Create tab and navigate
TAB_ID=$(curl -s -X POST http://localhost:9867/instances/$INST/tabs/open \
  -H "Content-Type: application/json" \
  -d '{"url":"https://example.com"}' | jq -r '.id')

echo "Tab created: $TAB_ID"
4

Extract Page Content

Get the page structure and text content:
# Get page structure with interactive elements
curl http://localhost:9867/tabs/$TAB_ID/snapshot | jq '.nodes | map({ref, role, name}) | .[0:5]'

# Extract text content
curl http://localhost:9867/tabs/$TAB_ID/text | jq '.text'
[
  {"ref": "e0", "role": "link", "name": "More information..."},
  {"ref": "e1", "role": "heading", "name": "Example Domain"},
  {"ref": "e2", "role": "paragraph", "name": "This domain is for use..."},
  {"ref": "e3", "role": "button", "name": "Accept"}
]
You’re running PinchTab! Continue below for common workflows.

Common First Commands

Take a Screenshot

# Save screenshot for a specific tab
curl "http://localhost:9867/tabs/$TAB_ID/screenshot" -o page.png

# View the screenshot
open page.png  # macOS
xdg-open page.png  # Linux

Export as PDF

# Save PDF
curl "http://localhost:9867/tabs/$TAB_ID/pdf?landscape=true" -o output.pdf

# View the PDF
open output.pdf  # macOS

Interact with the Page

# Get page structure (snapshot)
SNAPSHOT=$(curl http://localhost:9867/tabs/$TAB_ID/snapshot)

# Extract a reference (e.g., first button)
BUTTON_REF=$(echo "$SNAPSHOT" | jq -r '.nodes[] | select(.role=="button") | .ref' | head -1)

# Click the button
curl -X POST http://localhost:9867/tabs/$TAB_ID/action \
  -H "Content-Type: application/json" \
  -d '{"kind":"click","ref":"'$BUTTON_REF'"}'

# Fill a form input
curl -X POST http://localhost:9867/tabs/$TAB_ID/action \
  -H "Content-Type: application/json" \
  -d '{"kind":"fill","ref":"e3","text":"user@example.com"}'

Open Multiple Tabs

# Create new tab in same instance
curl -X POST http://localhost:9867/instances/$INST/tabs/open \
  -H "Content-Type: application/json" \
  -d '{"url":"https://github.com"}'

# List all tabs in instance
curl http://localhost:9867/instances/$INST/tabs | jq .

# Get specific tab info
curl http://localhost:9867/tabs/$TAB_ID | jq .

Understanding the Workflow

Here’s a typical automation workflow with PinchTab:
1

Create Instance

Chrome starts lazily on first request
INST=$(pinchtab instance launch | jq -r '.id')
sleep 2
2

Navigate

Create tab and navigate to page
TAB_ID=$(curl -s -X POST http://localhost:9867/instances/$INST/tabs/open \
  -d '{"url":"https://example.com"}' | jq -r '.id')
3

Get Structure

See buttons, links, inputs with stable refs
curl http://localhost:9867/tabs/$TAB_ID/snapshot
4

Interact

Click, type, fill using element refs
curl -X POST http://localhost:9867/tabs/$TAB_ID/action \
  -d '{"kind":"click","ref":"e5"}'
5

Verify

Check page changes
curl http://localhost:9867/tabs/$TAB_ID/snapshot
6

Capture Result

Take screenshot or export PDF
curl "http://localhost:9867/tabs/$TAB_ID/screenshot" -o page.png
curl "http://localhost:9867/tabs/$TAB_ID/pdf" -o report.pdf
7

Clean Up

Stop instance when done
curl -X POST http://localhost:9867/instances/$INST/stop

Using with Different Languages

PinchTab is HTTP-first, so you can use pure curl:
# Health check
curl http://localhost:9867/health

# Create instance
INST=$(curl -s -X POST http://localhost:9867/instances/launch | jq -r '.id')
sleep 2

# Navigate
curl -X POST http://localhost:9867/instances/$INST/tabs/open \
  -H "Content-Type: application/json" \
  -d '{"url":"https://example.com"}'

# Get snapshot
curl http://localhost:9867/tabs/$TAB_ID/snapshot

# Extract text
curl http://localhost:9867/tabs/$TAB_ID/text

# Stop instance
curl -X POST http://localhost:9867/instances/$INST/stop

Common Scenarios

# Create instance
INST=$(pinchtab instance launch | jq -r '.id')
sleep 2

# Navigate
TAB_ID=$(curl -s -X POST http://localhost:9867/instances/$INST/tabs/open \
  -d '{"url":"https://example.com/article"}' | jq -r '.id')

# Extract text
curl http://localhost:9867/tabs/$TAB_ID/text | jq '.text'

# Save to file
curl http://localhost:9867/tabs/$TAB_ID/text | jq -r '.text' > article.txt

# Stop instance
curl -X POST http://localhost:9867/instances/$INST/stop
# Create instance
INST=$(pinchtab instance launch | jq -r '.id')
sleep 2

# Navigate to form
TAB_ID=$(curl -s -X POST http://localhost:9867/instances/$INST/tabs/open \
  -d '{"url":"https://example.com/contact"}' | jq -r '.id')

# Get form structure
SNAP=$(curl http://localhost:9867/tabs/$TAB_ID/snapshot)

# Fill fields (get refs from snapshot)
curl -X POST http://localhost:9867/tabs/$TAB_ID/action \
  -d '{"kind":"fill","ref":"e3","text":"John Doe"}'

curl -X POST http://localhost:9867/tabs/$TAB_ID/action \
  -d '{"kind":"fill","ref":"e5","text":"john@example.com"}'

curl -X POST http://localhost:9867/tabs/$TAB_ID/action \
  -d '{"kind":"fill","ref":"e7","text":"My message here"}'

# Click submit
curl -X POST http://localhost:9867/tabs/$TAB_ID/action \
  -d '{"kind":"click","ref":"e10"}'

# Verify success
curl http://localhost:9867/tabs/$TAB_ID/snapshot | jq '.nodes | length'
# Create persistent profile
pinchtab profile create mylogin
PROF_ID=$(pinchtab profiles | jq -r '.[] | select(.name=="mylogin") | .id')

# Start instance with profile
INST=$(curl -s -X POST http://localhost:9867/instances/start \
  -d '{"profileId":"'$PROF_ID'"}' | jq -r '.id')
sleep 2

# Login
TAB_ID=$(curl -s -X POST http://localhost:9867/instances/$INST/tabs/open \
  -d '{"url":"https://example.com/login"}' | jq -r '.id')

curl -X POST http://localhost:9867/tabs/$TAB_ID/action \
  -d '{"kind":"fill","ref":"e3","text":"user@example.com"}'

curl -X POST http://localhost:9867/tabs/$TAB_ID/action \
  -d '{"kind":"fill","ref":"e5","text":"password"}'

curl -X POST http://localhost:9867/tabs/$TAB_ID/action \
  -d '{"kind":"click","ref":"e7"}'

# Stop instance (profile saved)
curl -X POST http://localhost:9867/instances/$INST/stop

# Later: restart with same profile (already logged in!)
INST=$(curl -s -X POST http://localhost:9867/instances/start \
  -d '{"profileId":"'$PROF_ID'"}' | jq -r '.id')
sleep 2

# Navigate to dashboard (cookies preserved)
curl -X POST http://localhost:9867/instances/$INST/tabs/open \
  -d '{"url":"https://example.com/dashboard"}'
# Create instance
INST=$(pinchtab instance launch | jq -r '.id')
sleep 2

TAB_ID=$(curl -s -X POST http://localhost:9867/instances/$INST/tabs/open \
  -d '{"url":"https://reports.example.com/monthly"}' | jq -r '.id')

# Export PDF
curl "http://localhost:9867/tabs/$TAB_ID/pdf?landscape=true" -o report.pdf

Troubleshooting

Problem: Orchestrator not runningSolution:
# Terminal 1: Start orchestrator
pinchtab

# Terminal 2: Check health (once running)
curl http://localhost:9867/health
Problem: Chrome takes time to initialize (8-20 seconds)Solution:
# Poll instance status
INST=$(pinchtab instance launch | jq -r '.id')

# Wait until 'running'
while [ "$(curl -s http://localhost:9867/instances/$INST | jq -r '.status')" != "running" ]; do
  sleep 0.5
done

# Now safe to use
curl -X POST http://localhost:9867/instances/$INST/tabs/open \
  -d '{"url":"https://example.com"}'
Problem: Port 9867 (or instance port) is takenSolution:
# Use different orchestrator port
BRIDGE_PORT=9868 pinchtab

# Or kill the process using 9867
lsof -i :9867
kill -9 <PID>

# Instance ports auto-allocated from 9868-9968, no manual config needed
Problem: Chrome/Chromium not installedSolution:
# macOS
brew install chromium

# Linux (Ubuntu/Debian)
sudo apt install chromium-browser

# Or specify custom Chrome
CHROME_BIN=/path/to/chrome pinchtab

Quick Reference

TaskCommand
Start orchestratorpinchtab
Health checkcurl http://localhost:9867/health
Create instanceINST=$(pinchtab instance launch | jq -r '.id')
Navigatecurl -X POST http://localhost:9867/instances/$INST/tabs/open -d '{"url":"..."}'
See structurecurl http://localhost:9867/tabs/$TAB_ID/snapshot
Get textcurl http://localhost:9867/tabs/$TAB_ID/text
Click elementcurl -X POST http://localhost:9867/tabs/$TAB_ID/action -d '{"kind":"click","ref":"e5"}'
Type textcurl -X POST http://localhost:9867/tabs/$TAB_ID/action -d '{"kind":"type","ref":"e3","text":"hello"}'
Screenshotcurl "http://localhost:9867/tabs/$TAB_ID/screenshot" -o page.png
PDF exportcurl http://localhost:9867/tabs/$TAB_ID/pdf -o out.pdf
List instancescurl http://localhost:9867/instances
Stop instancecurl -X POST http://localhost:9867/instances/$INST/stop

Next Steps

Core Concepts

Understand orchestrator, instances, profiles, and tabs

API Reference

Complete HTTP API documentation

Configuration

Environment variables and advanced settings

Examples

Real-world automation examples

Getting Help

Happy automating! 🦀