API Structure
Overview
Resource Hierarchy
Profile ↓ (create instance with profile)Instance (orchestrator resource) ↓ (create tab in instance)Tab (primary resource - where all work happens) ├─ Navigate ├─ Snapshot ├─ Action / Actions ├─ Text ├─ Evaluate ├─ Screenshot ├─ PDF ├─ Cookies ├─ Lock / Unlock └─ Close
Complete Endpoint List
Profile Management
| Method | Path | Payload | Response | Purpose |
|---|---|---|---|---|
| GET | /profiles | - | [{id, name, createdAt, usedAt}] | List profiles |
| POST | /profiles | {name} | {id, name, createdAt} | Create profile |
| GET | /profiles/{id} | - | {id, name, createdAt, usedAt} | Get profile info |
| DELETE | /profiles/{id} | - | {id, deleted: true} | Delete profile |
Instance Management
| Method | Path | Payload | Response | Purpose |
|---|---|---|---|---|
| GET | /instances | - | [{id, profileId, port, mode, status, startTime}] | List instances |
| GET | /instances/{id} | - | {id, profileId, port, mode, status, startTime} | Get instance status (read-only) |
| POST | /instances/start | {profileId?, mode?, port?} | {id, profileId, port, mode, status} | Start instance |
| POST | /instances/{id}/start | - | {status: "chrome_ready"} or {id, profileId, port, mode, status} | Start browser for existing instance |
| POST | /instances/{id}/stop | - | {id, stopped: true} | Stop instance |
| GET | /instances/{id}/logs | - | text | Get instance logs |
Tab Management (NEW)
| Method | Path | Payload | Response | Purpose |
|---|---|---|---|---|
| POST | /tabs/new | {instanceId, url?} | {id, instanceId, url?, status} | Create tab |
| GET | /tabs | - | [{id, instanceId, url, title, type}] | List all tabs |
| GET | /tabs?instanceId={id} | - | [{id, instanceId, url, title}] | List instance tabs |
| GET | /tabs/{id} | - | {id, instanceId, url, title, type, status} | Get tab info |
| POST | /tabs/{id}/close | - | {id, closed: true} | Close tab |
Tab Operations (NEW - Replaces /instances/{id}/…)
| Method | Path | Query/Body | Response | Purpose |
|---|---|---|---|---|
| NAVIGATE | ||||
| POST | /tabs/{id}/navigate | {url, timeout?, blockImages?, blockAds?} | {url, status, title} | Navigate to URL |
| SNAPSHOT | ||||
| GET | /tabs/{id}/snapshot | ?interactive&compact&depth=3&maxTokens=2000 | {elements: [], tree: ...} | Page structure |
| ACTION | ||||
| POST | /tabs/{id}/action | {kind, ref?, text?, key?, value?, ...} | {kind, result?, error?} | Single action |
| POST | /tabs/{id}/actions | {actions: [{kind, ...}, ...]} | {results: [...]} | Multiple actions |
| TEXT & EVALUATION | ||||
| GET | /tabs/{id}/text | ?raw | {text: "...", elements: [...]} | Extract text |
| POST | /tabs/{id}/evaluate | {expression, await?} | {result: any, type: string} | Run JS |
| MEDIA | ||||
| GET | /tabs/{id}/screenshot | ?format=png&quality=80 | binary (PNG/JPEG) | Screenshot |
| GET | /tabs/{id}/pdf | ?landscape&margins=0.5&scale=1.0&pages=1-3 | binary (PDF) | PDF export |
| COOKIES | ||||
| GET | /tabs/{id}/cookies | - | [{name, value, domain, ...}] | Get cookies |
| POST | /tabs/{id}/cookies | `{action: “set" | "delete”, cookies: […]}` | {set: [...], deleted: [...]} |
| LOCKING | ||||
| POST | /tabs/{id}/lock | {owner: string, ttl: number} | {locked: true, owner, expiresAt} | Lock tab |
| POST | /tabs/{id}/unlock | {owner: string} | {unlocked: true} | Unlock tab |
| GET | /tabs/{id}/locks | - | {locked: bool, owner?, expiresAt?} | Check lock |
| FINGERPRINTING | ||||
| POST | /tabs/{id}/fingerprint/rotate | - | {rotated: true, userAgent, ...} | Rotate fingerprint |
| GET | /tabs/{id}/fingerprint/status | - | `{stealth: “light" | "full”, ua, …}` |
Comparison: Old vs New
Example 1: Click Element
OLD (instance-scoped):
curl -X POST http://localhost:9867/instances/inst_abc123/action \ -d '{"kind": "click", "ref": "e5"}'
- Requires instance ID
- Path has 3 segments
NEW (tab-scoped):
curl -X POST http://localhost:9867/tabs/tab_xyz789/action \ -d '{"kind": "click", "ref": "e5"}'
- Requires tab ID (which identifies instance)
- Path has 2 segments
- Cleaner for multi-tab workflows
Example 2: Navigate to URL
OLD:
curl -X POST http://localhost:9867/instances/inst_abc123/navigate \ -d '{"url": "https://example.com"}'
NEW:
curl -X POST http://localhost:9867/tabs/tab_xyz789/navigate \ -d '{"url": "https://example.com"}'
Example 3: Create Tab
OLD:
curl -X POST http://localhost:9867/instances/inst_abc123/tabs/open \ -d '{}'# Response: {id: "tab_xyz", ...}
NEW:
curl -X POST http://localhost:9867/tabs/new \ -d '{"instanceId": "inst_abc123"}'# Response: {id: "tab_xyz", ...}
Example 4: List tabs
OLD:
curl http://localhost:9867/instances/inst_abc123/tabs# Returns just tabs from that instance
NEW:
# All tabs (across instances)curl http://localhost:9867/tabs# Specific instancecurl http://localhost:9867/tabs?instanceId=inst_abc123
Query Parameters vs Body
Query Parameters (GET)
# Snapshot with optionscurl 'http://localhost:9867/tabs/tab_xyz/snapshot?interactive&compact&depth=2&maxTokens=2000'# Screenshot with formatcurl 'http://localhost:9867/tabs/tab_xyz/screenshot?format=jpeg&quality=85'# List with filtercurl 'http://localhost:9867/tabs?instanceId=inst_abc123'
Body (POST)
# Navigate with optionscurl -X POST http://localhost:9867/tabs/tab_xyz/navigate \ -d '{ "url": "https://example.com", "timeout": 30, "blockImages": true, "blockAds": false }'# Action (already body-based)curl -X POST http://localhost:9867/tabs/tab_xyz/action \ -d '{ "kind": "click", "ref": "e5", "timeout": 5 }'
HTTP Status Codes
| Code | Meaning | Example |
|---|---|---|
| 200 | Success (GET/action) | Snapshot returned, action completed |
| 201 | Created | Tab created, instance started |
| 204 | No content | Close successful |
| 400 | Bad request | Invalid action kind, malformed JSON |
| 404 | Not found | Tab ID doesn’t exist, instance stopped |
| 409 | Conflict | Tab locked by another agent, port in use |
| 500 | Server error | Chrome crashed, internal error |
| 503 | Unavailable | Chrome not initialized, instance starting |
Response Format
Success Response
{
"kind": "action",
"result": {
"text": "Element text",
"visible": true,
"rect": {...}
}
}
Error Response
{
"error": "tab not found",
"code": "ERR_TAB_NOT_FOUND",
"statusCode": 404
}
Snapshot Response
{
"elements": [
{
"ref": "e1",
"tag": "button",
"text": "Click me",
"interactive": true,
"rect": {"x": 100, "y": 50, "w": 80, "h": 30}
}
],
"tree": {...},
"meta": {"count": 45, "interactive": 12}
}
CLI Command Mapping
Profile Management
# Listpinchtab profiles# Createpinchtab profile create my-profile# Deletepinchtab profile delete my-profile
Instance Management
# Listpinchtab instances# Startpinchtab instance start --profile my-profile --mode headed --port 9868# Stoppinchtab instance stop inst_abc123# Logspinchtab instance logs inst_abc123
Tab Management
# List all tabspinchtab tabs# List instance tabspinchtab --instance inst_abc123 tabs# Create tabpinchtab --instance inst_abc123 tab new https://example.com# → tab_xyz789# Close tabpinchtab --tab tab_xyz789 close
Tab Operations
# Navigatepinchtab --tab tab_xyz789 nav https://example.com# Snapshotpinchtab --tab tab_xyz789 snap -i -c# Clickpinchtab --tab tab_xyz789 click e5# Get textpinchtab --tab tab_xyz789 text# Run actioncat << 'EOF' | pinchtab --tab tab_xyz789 action{ "kind": "actions", "actions": [ {"kind": "click", "ref": "e1"}, {"kind": "type", "ref": "e2", "text": "search"}, {"kind": "press", "key": "Enter"} ]}EOF# Lock tab (exclusive access)pinchtab --tab tab_xyz789 lock --owner my-agent --ttl 60# Unlockpinchtab --tab tab_xyz789 unlock --owner my-agent
Full Workflow Example
Setup
# 1. Create profilePROF=$(pinchtab profile create my-app | jq -r .id)# 2. Start instanceINST=$(pinchtab instance start --profile my-app --mode headed | jq -r .id)# 3. Create tabTAB=$(pinchtab --instance $INST tab new | jq -r .id)
Work
# 4. Navigatepinchtab --tab $TAB nav https://example.com# 5. Get page structurepinchtab --tab $TAB snap -i -c | jq .# 6. Interactpinchtab --tab $TAB click e5pinchtab --tab $TAB type e12 "search text"pinchtab --tab $TAB press Enter# 7. Check resultpinchtab --tab $TAB snap -d | jq .# 8. Extract datapinchtab --tab $TAB text
Cleanup
# 9. Close tab (optional, instance cleanup closes all)pinchtab --tab $TAB close# 10. Stop instancepinchtab instance stop $INST
Data Flow
Request Path
CLI Command ↓HTTP Request (curl or SDK) ↓Orchestrator Server (9867) ↓Tab Resolver (tab ID → instance ID) ↓Route to Instance (HTTP call to 9868+) ↓Bridge Server ↓Chrome (DevTools Protocol)
Response Path
Chrome responds ↓Bridge returns JSON ↓Instance Server returns JSON ↓Orchestrator aggregates/proxies ↓CLI/SDK receives JSON
Deprecation Timeline
Phase 1 (Now - v1.0)
- New tab endpoints available
- Old instance endpoints still work
- Deprecation headers on old endpoints
Phase 2 (v1.1)
- CLI prefers
--tabover--instance - Documentation focuses on new API
- Users migrated gradually
Phase 3 (v2.0)
- Old instance endpoints removed
- Only tab-centric API