Tabs API Reference

Tabs are individual browser windows/pages within an instance. Each tab has its own URL, content, and state. Tabs are the primary resource for browser operations in PinchTab.

Quick Start

List All Tabs

bash terminal
# CLIpinchtab tabs# Curlcurl http://localhost:9867/tabs | jq .# Response[  {    "id": "tab_abc123",    "instanceId": "inst_xyz",    "url": "https://example.com",    "title": "Example Domain",    "status": "ready"  }]

Open a New Tab

bash terminal
# CLI (create new tab in instance)pinchtab tab open inst_xyz https://example.com# Curlcurl -X POST http://localhost:9867/instances/{id}/tabs/open \  -H "Content-Type: application/json" \  -d '{"url": "https://example.com"}'# Response{  "tabId": "tab_abc123",  "url": "https://example.com",  "title": "Example Domain"}

Get Tab Info

bash terminal
# CLIpinchtab tab info tab_abc123# Curlcurl http://localhost:9867/tabs/tab_abc123# Response{  "id": "tab_abc123",  "instanceId": "inst_xyz",  "url": "https://example.com",  "title": "Example Domain",  "status": "ready"}

Close Tab

bash terminal
# CLIpinchtab tab close tab_abc123# Curlcurl -X POST http://localhost:9867/tabs/tab_abc123/close# Response{  "id": "tab_abc123",  "status": "closed"}

Tab ID Format

Tab IDs use a hash-based format: tab_XXXXXXXX (12 characters total).

Architecture Diagram ASCII
tab_abc12345        8-character hash (derived from internal Chrome target ID)   Prefix identifying resource type

Why Hash IDs?

  1. Security: Raw Chrome DevTools Protocol (CDP) target IDs are never exposed. This prevents:

    • Guessing/brute-forcing tab identifiers
    • Cross-instance tab access in multi-instance setups
    • Information leakage about Chrome internals
  2. Consistency: All PinchTab resources use the same format:

    • Profiles: prof_XXXXXXXX
    • Instances: inst_XXXXXXXX
    • Tabs: tab_XXXXXXXX
  3. Stability: Hash IDs remain stable for the tab’s lifetime

Important

  • Only hash-format IDs are accepted by the API
  • Raw CDP target IDs (32-character hex strings) are rejected with 404
  • Tab IDs are scoped to the instance that created them

Complete API Reference

1. Open Tab

Endpoint: POST /instances/{id}/tabs/open

CLI:

bash terminal
# Create tab in instance with URLpinchtab tab open inst_xyz https://example.com# Create tab without initial URLpinchtab tab open inst_xyz

Curl:

bash terminal
# Minimal (instanceId only, no URL)curl -X POST http://localhost:9867/instances/{id}/tabs/open \  -H "Content-Type: application/json" \  -d '{}'# With URLcurl -X POST http://localhost:9867/instances/{id}/tabs/open \  -H "Content-Type: application/json" \  -d '{"url": "https://example.com"}'

Request Body:

{
  "url": "https://example.com"
}

Parameters:

  • url (string, optional) — URL to navigate to after opening tab

Response: Tab object

{
  "tabId": "tab_abc123",
  "url": "https://example.com",
  "title": "Example Domain"
}

Defaults:

  • If url not provided, tab opens with blank page
  • Status is “ready” immediately after creation

2. List All Tabs

Endpoint: GET /tabs

CLI:

bash terminal
pinchtab tabs

Curl:

bash terminal
# List all tabs across all instancescurl http://localhost:9867/tabs | jq .# Filter by instancecurl 'http://localhost:9867/tabs?instanceId=inst_xyz' | jq .

Query Parameters:

  • instanceId (string, optional) — Filter tabs to specific instance

Response: Array of Tab objects

[
  {
    "id": "tab_abc123",
    "instanceId": "inst_xyz",
    "url": "https://example.com",
    "title": "Example Domain",
    "status": "ready",
    "createdAt": "2026-03-01T05:25:30Z"
  },
  {
    "id": "tab_def456",
    "instanceId": "inst_xyz",
    "url": "https://google.com",
    "title": "Google",
    "status": "ready",
    "createdAt": "2026-03-01T05:26:00Z"
  }
]

Tab Status Values:

  • ready — Tab is loaded and ready to accept commands
  • loading — Tab is navigating to URL
  • error — Tab failed to load

3. Get Tab Info

Endpoint: GET /tabs/{id}

CLI:

bash terminal
pinchtab tab info tab_abc123

Curl:

bash terminal
curl http://localhost:9867/tabs/tab_abc123 | jq .

Response: Single Tab object

{
  "id": "tab_abc123",
  "instanceId": "inst_xyz",
  "url": "https://example.com",
  "title": "Example Domain",
  "status": "ready",
  "createdAt": "2026-03-01T05:25:30Z"
}

Notes:

  • Returns 404 if tab not found
  • Provides full tab state information

4. Close Tab

Endpoint: POST /tabs/{id}/close

CLI:

bash terminal
pinchtab tab close tab_abc123

Curl:

bash terminal
curl -X POST http://localhost:9867/tabs/tab_abc123/close

Response:

{
  "id": "tab_abc123",
  "status": "closed"
}

Notes:

  • Gracefully closes tab
  • Tab removed from instance
  • Returns 404 if tab already closed/not found

Complete Workflow Examples

Example 1: Multi-Tab Workflow

bash terminal
#!/bin/bash# Start instanceINST=$(pinchtab instance start --mode headed | jq -r .id)echo "Instance: $INST"# Open first tabTAB1=$(pinchtab tab open $INST https://example.com | jq -r .id)echo "Tab 1: $TAB1"# Open second tabTAB2=$(pinchtab tab open $INST https://google.com | jq -r .id)echo "Tab 2: $TAB2"# List all tabs in instanceecho -e "\nTabs in instance:"curl -s "http://localhost:9867/tabs?instanceId=$INST" | jq '.[] | {id, url}'# Get info on tab 1echo -e "\nTab 1 info:"pinchtab tab info $TAB1# Close tab 1echo -e "\nClosing tab 1..."pinchtab tab close $TAB1# Verify closedecho "Remaining tabs:"curl -s "http://localhost:9867/tabs?instanceId=$INST" | jq 'length' | xargs echo "Count:"# Cleanuppinchtab instance stop $INST

Example 2: Batch Tab Operations

bash terminal
#!/bin/bashINST=$1URLS=(  "https://example.com"  "https://google.com"  "https://github.com"  "https://stackoverflow.com")echo "Opening $((${#URLS[@]})) tabs in instance $INST..."TABS=()for url in "${URLS[@]}"; do  TAB=$(curl -s -X POST "http://localhost:9867/instances/$INST/tabs/open" \    -d "{\"url\":\"$url\"}" | jq -r .tabId)  TABS+=($TAB)  echo "Opened: $TAB"done# Wait for loadingsleep 3# Show all tabsecho -e "\nAll tabs:"curl -s "http://localhost:9867/tabs?instanceId=$INST" | jq '.[] | {id, title}'# Close allecho -e "\nClosing all tabs..."for tab in "${TABS[@]}"; do  curl -s -X POST http://localhost:9867/tabs/$tab/close > /dev/null  echo "Closed: $tab"done

Example 3: Sequential Tab Navigation

bash terminal
#!/bin/bash# Start instance with specific profilePROF="my-profile"INST=$(curl -s -X POST http://localhost:9867/instances/start \  -d "{\"profileId\":\"$PROF\"}" | jq -r .id)echo "Started: $INST"# Create single tab (will be used for all navigation)TAB=$(pinchtab tab open $INST | jq -r .id)echo "Tab: $TAB"# Navigate through multiple sitesSITES=("example.com" "google.com" "github.com")for site in "${SITES[@]}"; do  echo "Navigating to $site..."  curl -s -X POST http://localhost:9867/tabs/$TAB/navigate \    -d "{\"url\":\"https://$site\"}" > /dev/null  sleep 2done# Cleanuppinchtab tab close $TABpinchtab instance stop $INST

CLI Examples

Quick Start with CLI

bash terminal
# List instances firstpinchtab instances# Open tab in instancepinchtab tab open inst_abc123 https://example.com# List all tabspinchtab tabs# List tabs in specific instancepinchtab tabs inst_abc123# Get tab infopinchtab tab info tab_xyz789# Close tabpinchtab tab close tab_xyz789# Open multiple tabsfor url in example.com google.com github.com; do  pinchtab tab open inst_abc123 https://$urldone

Integration Examples

With Bash

bash terminal
# Get instance, create tabs, list themINST=$(pinchtab instance start --mode headed | jq -r .id)TAB1=$(curl -s -X POST "http://localhost:9867/instances/$INST/tabs/open" \  -d "{\"url\":\"https://example.com\"}" | jq -r .tabId)TAB2=$(curl -s -X POST "http://localhost:9867/instances/$INST/tabs/open" \  -d "{\"url\":\"https://google.com\"}" | jq -r .tabId)# List tabscurl -s http://localhost:9867/tabs | jq '.[] | {id, url}'

With Python

import requests
import json

BASE = "http://localhost:9867"

# Start instance
inst_resp = requests.post(f"{BASE}/instances/start", json={"mode": "headed"})
inst_id = inst_resp.json()["id"]
print(f"Instance: {inst_id}")

# Open tabs
for url in ["https://example.com", "https://google.com"]:
  resp = requests.post(f"{BASE}/instances/{inst_id}/tabs/open",
    json={"url": url})
  tab = resp.json()
  print(f"Tab: {tab['tabId']} → {url}")

# List tabs
tabs = requests.get(f"{BASE}/tabs").json()
print(f"\nTotal tabs: {len(tabs)}")
for tab in tabs:
  print(f"  {tab['id']}: {tab['url']}")

# Close first tab
first_tab = tabs[0]["id"]
requests.post(f"{BASE}/tabs/{first_tab}/close")
print(f"\nClosed: {first_tab}")

With JavaScript/Node.js

const BASE = "http://localhost:9867";

async function tabWorkflow() {
  // Start instance
  const instResp = await fetch(`${BASE}/instances/start`, {
    method: "POST",
    headers: { "Content-Type": "application/json" },
    body: JSON.stringify({ mode: "headed" })
  });
  const inst = await instResp.json();
  console.log(`Instance: ${inst.id}`);

  // Open tabs
  const urls = ["https://example.com", "https://google.com"];
  const tabs = [];

  for (const url of urls) {
    const resp = await fetch(`${BASE}/instances/${inst.id}/tabs/open`, {
      method: "POST",
      headers: { "Content-Type": "application/json" },
      body: JSON.stringify({ url })
    });
    const tab = await resp.json();
    tabs.push(tab);
    console.log(`Tab: ${tab.tabId} → ${url}`);
  }

  // List all tabs
  const listResp = await fetch(`${BASE}/tabs`);
  const allTabs = await listResp.json();
  console.log(`\nTotal tabs: ${allTabs.length}`);

  // Close first tab
  const closeResp = await fetch(`${BASE}/tabs/${tabs[0].id}/close`, {
    method: "POST"
  });
  console.log(`Closed: ${tabs[0].id}`);
}

tabWorkflow().catch(console.error);

Error Handling

Instance Not Found (404)

bash terminal
curl -X POST http://localhost:9867/instances/{id}/tabs/open \  -d '{"url":"https://example.com"}'# Response (404){  "error": "instance not found",  "statusCode": 404}

Tab Not Found (404)

bash terminal
curl http://localhost:9867/tabs/nonexistent# Response (404){  "error": "tab not found",  "statusCode": 404}

Invalid JSON (400)

bash terminal
curl -X POST http://localhost:9867/instances/{id}/tabs/open -d 'invalid'# Response (400){  "error": "invalid JSON",  "statusCode": 400}

Best Practices

Tab Lifecycle

bash terminal
# 1. Open tabTAB=$(pinchtab tab open $INST | jq -r .id)# 2. Do work (navigate, interact, etc.)pinchtab tab navigate $TAB https://example.com# 3. Get resultspinchtab tab snapshot $TAB# 4. Close tabpinchtab tab close $TAB

Resource Management

bash terminal
# Always close tabs when donefor tab_id in $(pinchtab tabs | jq -r '.[].id'); do  pinchtab tab close $tab_iddone# Stop instancespinchtab instance stop $INSTANCE_ID

Error Handling

bash terminal
# Check if tab exists before operatingif ! pinchtab tab info $TAB_ID > /dev/null 2>&1; then  echo "Tab not found: $TAB_ID"  exit 1fi# Handle navigation errorsif ! curl -s -X POST http://localhost:9867/tabs/$TAB_ID/navigate \  -d "{\"url\":\"$url\"}" | jq -e .error > /dev/null; then  echo "Navigation failed"fi

Status Codes

CodeMeaningExample
200Success (GET)Tab info retrieved
201CreatedTab opened
204No contentTab closed
400Bad requestInvalid JSON, missing instanceId
404Not foundTab/instance not found
500Server errorInternal error

Tab Lifecycle Diagram

Architecture Diagram ASCII
OPEN (POST /instances/{id}/tabs/open)  [status: "ready"]  Ready for commands  Can navigate, interact, snapshot, etc.  CLOSE (POST /tabs/{id}/close)  [status: "closed"]  Tab removed

Summary Table

OperationMethodEndpointCLI
OpenPOST/instances/{id}/tabs/openpinchtab tab open <inst> [url]
List AllGET/tabspinchtab tabs
Get InfoGET/tabs/{id}pinchtab tab info <id>
ClosePOST/tabs/{id}/closepinchtab tab close <id>

FAQ

Q: How many tabs can I open in an instance? A: Technically unlimited, limited only by system resources (memory).

Q: What happens when I navigate to a new URL in a tab? A: URL loads in the same tab. Use a new tab if you want to keep the old page.

Q: Can I close all tabs at once? A: No, close individually. You can script it with a loop.

Q: What happens to tabs when I stop an instance? A: All tabs are closed automatically when instance stops.

Q: How do I know when a tab is ready after opening? A: Check status via GET /tabs/{id} or GET /tabs?instanceId=…

Q: Can I reopen a closed tab? A: No, create a new tab instead.



Tab Operations (Phase 4)

Once you have a tab ID, you can perform full browser control operations on it.

Endpoint: POST /tabs/{id}/navigate

CLI:

bash terminal
pinchtab tab navigate <tab-id> https://example.compinchtab tab navigate <tab-id> https://example.com --timeout 30

Curl:

bash terminal
curl -X POST http://localhost:9867/tabs/tab_abc/navigate \  -d '{"url":"https://example.com","timeout":30,"blockImages":true}'

Get Snapshot

Endpoint: GET /tabs/{id}/snapshot

CLI:

bash terminal
pinchtab tab snapshot <tab-id>pinchtab tab snapshot <tab-id> --interactive --compactpinchtab tab snapshot <tab-id> -i -c

Curl:

bash terminal
curl 'http://localhost:9867/tabs/tab_abc/snapshot?interactive=true&compact=true'

Take Screenshot

Endpoint: GET /tabs/{id}/screenshot

CLI:

bash terminal
pinchtab tab screenshot <tab-id> -o screenshot.pngpinchtab tab screenshot <tab-id> -o out.jpg -q 85

Curl:

bash terminal
curl http://localhost:9867/tabs/tab_abc/screenshot > screenshot.png

Execute Action

Endpoint: POST /tabs/{id}/action

CLI:

bash terminal
# Click elementpinchtab tab click <tab-id> e5# Type textpinchtab tab type <tab-id> e12 "hello world"# Press keypinchtab tab press <tab-id> Enter# Fill inputpinchtab tab fill <tab-id> e12 "value"# Hover elementpinchtab tab hover <tab-id> e5# Scrollpinchtab tab scroll <tab-id> down# Select dropdownpinchtab tab select <tab-id> e3 "option2"# Focus elementpinchtab tab focus <tab-id> e5

Curl:

bash terminal
curl -X POST http://localhost:9867/tabs/tab_abc/action \  -d '{"kind":"click","ref":"e5"}'

Execute Multiple Actions

Endpoint: POST /tabs/{id}/actions

CLI:

bash terminal
# Piped JSONcat actions.json | pinchtab tab actions <tab-id># Inline JSONpinchtab tab actions <tab-id> --json '[{"kind":"click","ref":"e5"},...]'

Curl:

bash terminal
curl -X POST http://localhost:9867/tabs/tab_abc/actions \  -d '{    "actions": [      {"kind":"click","ref":"e5"},      {"kind":"type","ref":"e12","text":"search"},      {"kind":"press","key":"Enter"}    ]  }'

Get Page Text

Endpoint: GET /tabs/{id}/text

CLI:

bash terminal
pinchtab tab text <tab-id>pinchtab tab text <tab-id> --raw

Curl:

bash terminal
curl http://localhost:9867/tabs/tab_abc/text

Evaluate JavaScript

Endpoint: POST /tabs/{id}/evaluate

CLI:

bash terminal
pinchtab tab eval <tab-id> "document.title"pinchtab tab eval <tab-id> "document.querySelectorAll('a').length"

Curl:

bash terminal
curl -X POST http://localhost:9867/tabs/tab_abc/evaluate \  -d '{"expression":"document.title"}'

Export to PDF

Endpoint: GET /tabs/{id}/pdf

CLI:

bash terminal
pinchtab tab pdf <tab-id> -o output.pdfpinchtab tab pdf <tab-id> -o out.pdf --landscape

Curl:

bash terminal
curl 'http://localhost:9867/tabs/tab_abc/pdf?landscape=true' > output.pdf

Manage Cookies

Endpoint: GET /tabs/{id}/cookies and POST /tabs/{id}/cookies

CLI:

bash terminal
pinchtab tab cookies <tab-id>  # Get cookies

Curl:

bash terminal
curl http://localhost:9867/tabs/tab_abc/cookies

Lock Tab

Endpoint: POST /tabs/{id}/lock

CLI:

bash terminal
pinchtab tab lock <tab-id> --owner my-agent --ttl 60

Curl:

bash terminal
curl -X POST http://localhost:9867/tabs/tab_abc/lock \  -d '{"owner":"my-agent","ttl":60}'

Unlock Tab

Endpoint: POST /tabs/{id}/unlock

CLI:

bash terminal
pinchtab tab unlock <tab-id> --owner my-agent

Complete Tab Operation Example

bash terminal
#!/bin/bash# Start instanceINST=$(pinchtab instance start --mode headed)echo "Instance: $INST"# Create tabTAB=$(pinchtab tab new $INST | jq -r .id)echo "Tab: $TAB"# Navigatepinchtab tab navigate $TAB https://example.comsleep 2# Get snapshotpinchtab tab snapshot $TAB -i -c | jq .# Click elementpinchtab tab click $TAB e5sleep 1# Get resultpinchtab tab snapshot $TAB -d# Extract textpinchtab tab text $TAB | jq .text# Take screenshotpinchtab tab screenshot $TAB -o result.png# Export PDFpinchtab tab pdf $TAB -o result.pdf# Cleanuppinchtab tab close $TABpinchtab instance stop $INST

  • Instance API (docs/references/instance-api.md) — Manage instances
  • Profile API (docs/references/profile-api.md) — Manage profiles
  • CLI Design (docs/references/cli-design.md) — CLI command patterns