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.

Overview

The Evaluation API allows you to execute custom JavaScript in the context of a page. Use it to:
  • Extract data from the DOM
  • Modify page content
  • Check element states
  • Call JavaScript functions
  • Access window/document objects

Execute JavaScript

POST /tabs/{id}/evaluate
curl -X POST http://localhost:9867/tabs/tab_abc123/evaluate \
  -H "Content-Type: application/json" \
  -d '{"expression": "document.title"}'

Request Body

expression
string
required
JavaScript expression to evaluate

Response (200 OK)

{
  "result": "Example Domain"
}
The result field contains the return value of the JavaScript expression.

Examples

Get Page Title

curl -X POST http://localhost:9867/tabs/tab_abc123/evaluate \
  -d '{"expression": "document.title"}'
Response:
{
  "result": "Example Domain"
}

Count Elements

curl -X POST http://localhost:9867/tabs/tab_abc123/evaluate \
  -d '{"expression": "document.querySelectorAll(\"button\").length"}'
Response:
{
  "result": 5
}

Extract Text Content

curl -X POST http://localhost:9867/tabs/tab_abc123/evaluate \
  -d '{"expression": "document.body.innerText"}'
Response:
{
  "result": "Example Domain\nThis domain is for use in illustrative examples..."
}
curl -X POST http://localhost:9867/tabs/tab_abc123/evaluate \
  -d '{"expression": "Array.from(document.querySelectorAll(\"a\")).map(a => ({text: a.textContent, href: a.href}))"}'
Response:
{
  "result": [
    {"text": "More information...", "href": "https://www.iana.org/domains/example"}
  ]
}

Check Element Visibility

curl -X POST http://localhost:9867/tabs/tab_abc123/evaluate \
  -d '{"expression": "document.querySelector(\"#element\").offsetHeight > 0"}'
Response:
{
  "result": true
}

Get Computed Styles

curl -X POST http://localhost:9867/tabs/tab_abc123/evaluate \
  -d '{"expression": "getComputedStyle(document.querySelector(\"h1\")).color"}'
Response:
{
  "result": "rgb(0, 0, 0)"
}

Get Local Storage

curl -X POST http://localhost:9867/tabs/tab_abc123/evaluate \
  -d '{"expression": "JSON.stringify(localStorage)"}'
Response:
{
  "result": "{\"key\":\"value\"}"
}

Set Local Storage

curl -X POST http://localhost:9867/tabs/tab_abc123/evaluate \
  -d '{"expression": "localStorage.setItem(\"key\", \"value\")"}'

Data Extraction Example

import requests

BASE = "http://localhost:9867"
tab_id = "tab_abc123"

# Navigate to page
requests.post(f"{BASE}/tabs/{tab_id}/navigate",
    json={"url": "https://news.ycombinator.com"})

# Extract all story titles
resp = requests.post(f"{BASE}/tabs/{tab_id}/evaluate", json={
    "expression": """
        Array.from(document.querySelectorAll('.titleline > a'))
            .map(a => ({
                title: a.textContent,
                url: a.href
            }))
    """
})

stories = resp.json()["result"]

print(f"Found {len(stories)} stories:\n")
for i, story in enumerate(stories[:10], 1):
    print(f"{i}. {story['title']}")
    print(f"   {story['url']}\n")

Complex Evaluation Example

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

// Extract product data from e-commerce page
const resp = await fetch(`${BASE}/tabs/${tabId}/evaluate`, {
  method: "POST",
  headers: { "Content-Type": "application/json" },
  body: JSON.stringify({
    expression: `
      {
        title: document.querySelector('h1.product-title')?.textContent,
        price: document.querySelector('.price')?.textContent,
        inStock: document.querySelector('.in-stock') !== null,
        rating: parseFloat(document.querySelector('.rating')?.textContent),
        images: Array.from(document.querySelectorAll('.product-image img'))
                     .map(img => img.src),
        description: document.querySelector('.description')?.textContent.trim()
      }
    `
  })
});

const product = (await resp.json()).result;
console.log(product);

Error Handling

JavaScript Error (500)

curl -X POST http://localhost:9867/tabs/tab_abc123/evaluate \
  -d '{"expression": "nonexistent.property"}'
Response:
{
  "error": "evaluate: ReferenceError: nonexistent is not defined",
  "statusCode": 500
}

Syntax Error (400)

curl -X POST http://localhost:9867/tabs/tab_abc123/evaluate \
  -d '{"expression": "document.querySelector("}'
Response:
{
  "error": "invalid expression syntax",
  "statusCode": 400
}

Tab Not Found (404)

curl -X POST http://localhost:9867/tabs/nonexistent/evaluate \
  -d '{"expression": "document.title"}'
Response:
{
  "error": "tab not found",
  "statusCode": 404
}

Best Practices

Return Simple Data Types

JavaScript objects are serialized to JSON. Stick to simple types:
# ✅ Good: Returns array of strings
curl -X POST $BASE/tabs/$TAB/evaluate \
  -d '{"expression": "Array.from(document.querySelectorAll(\"h2\")).map(h => h.textContent)"}'

# ❌ Bad: Returns DOM nodes (can't serialize)
curl -X POST $BASE/tabs/$TAB/evaluate \
  -d '{"expression": "document.querySelectorAll(\"h2\")"}'

Use JSON.stringify for Objects

curl -X POST http://localhost:9867/tabs/tab_abc123/evaluate \
  -d '{"expression": "JSON.stringify({title: document.title, url: location.href})"}'
Then parse on the client side:
resp = requests.post(f"{BASE}/tabs/{tab_id}/evaluate",
    json={"expression": "JSON.stringify({title: document.title, url: location.href})"})

data = json.loads(resp.json()["result"])
print(data["title"])

Handle Null/Undefined

// Use optional chaining and defaults
const expression = `
  {
    title: document.querySelector('h1')?.textContent || 'No title',
    price: document.querySelector('.price')?.textContent || 'N/A'
  }
`;

Extract Complex Data

# Extract table data
expression = """
Array.from(document.querySelectorAll('table tr')).map(row => 
  Array.from(row.querySelectorAll('td')).map(cell => cell.textContent.trim())
)
"""

resp = requests.post(f"{BASE}/tabs/{tab_id}/evaluate",
    json={"expression": expression})

table_data = resp.json()["result"]

Use Cases

Check Login State

# Check if user is logged in
resp = requests.post(f"{BASE}/tabs/{tab_id}/evaluate", json={
    "expression": "document.querySelector('.logout-button') !== null"
})
is_logged_in = resp.json()["result"]

Wait for Element

import time

# Poll for element to appear
for _ in range(10):
    resp = requests.post(f"{BASE}/tabs/{tab_id}/evaluate", json={
        "expression": "document.querySelector('#result') !== null"
    })
    if resp.json()["result"]:
        break
    time.sleep(0.5)

Modify Page Content

# Hide ads
curl -X POST http://localhost:9867/tabs/tab_abc123/evaluate \
  -d '{"expression": "document.querySelectorAll(\".ad\").forEach(el => el.style.display = \"none\")"}'

# Change page title
curl -X POST http://localhost:9867/tabs/tab_abc123/evaluate \
  -d '{"expression": "document.title = \"New Title\""}'

Get Form Values

# Get all form input values
resp = requests.post(f"{BASE}/tabs/{tab_id}/evaluate", json={
    "expression": """
        Object.fromEntries(
            Array.from(document.querySelectorAll('input, select, textarea'))
                .map(el => [el.name || el.id, el.value])
                .filter(([name]) => name)
        )
    """
})
form_data = resp.json()["result"]

Limitations

  • Cannot return DOM nodes or functions (must serialize to JSON)
  • Long-running scripts may timeout
  • Page must be fully loaded before evaluation
  • Cross-origin restrictions apply (same as browser)

Next Steps

Snapshot API

Get structured page data

Actions API

Interact with page elements

Navigation

Navigate before evaluation

Cookies

Manage cookies and storage