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 Downloads API provides endpoints for:
  • Triggering and monitoring file downloads
  • Uploading files to the browser
  • Managing download state
  • Retrieving downloaded files
Downloads are initiated by user actions (clicking download links) or triggered programmatically via JavaScript evaluation.

Download File

Trigger a file download from a tab.
GET /tabs/{id}/download
curl "http://localhost:9867/tabs/tab_abc123/download?url=https://example.com/file.pdf" > file.pdf

Query Parameters

url
string
required
URL of the file to download
filename
string
Suggested filename (optional, defaults from URL or Content-Disposition header)
timeout
integer
default:"60"
Download timeout in seconds

Response

Returns file binary data with appropriate Content-Type and Content-Disposition headers.

Upload File

Upload a file to a file input element in the browser.
POST /tabs/{id}/upload
curl -X POST http://localhost:9867/tabs/tab_abc123/upload \
  -F "file=@/path/to/local/file.pdf" \
  -F "selector=#file-input"

Form Data

file
file
required
File to upload (multipart/form-data)
selector
string
required
CSS selector for file input element
ref
string
Element reference from snapshot (alternative to selector)

Response (200 OK)

{
  "success": true,
  "filename": "document.pdf",
  "size": 125678,
  "selector": "#file-input"
}

Download via Click

Trigger downloads by clicking download links:
import requests
import time

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

# Navigate to page with download link
requests.post(f"{BASE}/tabs/{tab_id}/navigate",
    json={"url": "https://example.com/downloads"})

time.sleep(2)

# Get page structure
snapshot = requests.get(
    f"{BASE}/tabs/{tab_id}/snapshot?filter=interactive"
).json()

# Find download link
download_ref = None
for node in snapshot["nodes"]:
    if "download" in node.get("name", "").lower():
        download_ref = node["ref"]
        break

if download_ref:
    # Click download link
    requests.post(f"{BASE}/tabs/{tab_id}/action",
        json={"kind": "click", "ref": download_ref})
    
    print("Download initiated via click")
    
    # Give download time to start
    time.sleep(2)
    
    # Download may save to profile's download directory

Programmatic Download

Trigger downloads via JavaScript:
import requests
import base64

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

# Generate download via JavaScript
resp = requests.post(f"{BASE}/tabs/{tab_id}/evaluate", json={
    "expression": """
        (function() {
            const text = "Hello, World!";
            const blob = new Blob([text], { type: 'text/plain' });
            const url = URL.createObjectURL(blob);
            
            const a = document.createElement('a');
            a.href = url;
            a.download = 'hello.txt';
            document.body.appendChild(a);
            a.click();
            document.body.removeChild(a);
            URL.revokeObjectURL(url);
            
            return 'Download triggered';
        })()
    """
})

print(resp.json()["result"])

Upload to Form Example

import requests
import time

BASE = "http://localhost:9867"

# Start instance
inst = requests.post(f"{BASE}/instances/start",
    json={"mode": "headed"}).json()

# Open tab with upload form
tab = requests.post(f"{BASE}/instances/{inst['id']}/tabs/open",
    json={"url": "https://example.com/upload-form"}).json()

tab_id = tab["tabId"]
time.sleep(2)

# Get form structure
snapshot = requests.get(
    f"{BASE}/tabs/{tab_id}/snapshot?filter=interactive"
).json()

# Find file input
file_input_ref = None
for node in snapshot["nodes"]:
    if node.get("role") == "textbox" and "file" in node.get("name", "").lower():
        file_input_ref = node["ref"]
        break

if file_input_ref:
    # Upload file
    files = {"file": open("document.pdf", "rb")}
    data = {"ref": file_input_ref}
    
    resp = requests.post(
        f"{BASE}/tabs/{tab_id}/upload",
        files=files,
        data=data
    )
    
    result = resp.json()
    print(f"Uploaded: {result['filename']}")
    
    # Find submit button
    submit_ref = None
    for node in snapshot["nodes"]:
        if node.get("role") == "button" and "submit" in node.get("name", "").lower():
            submit_ref = node["ref"]
            break
    
    if submit_ref:
        # Submit form
        requests.post(f"{BASE}/tabs/{tab_id}/action",
            json={"kind": "click", "ref": submit_ref})
        
        print("Form submitted")

# Cleanup
requests.post(f"{BASE}/instances/{inst['id']}/stop")

Bulk Download Example

import requests
import os

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

download_urls = [
    "https://example.com/file1.pdf",
    "https://example.com/file2.pdf",
    "https://example.com/file3.pdf"
]

os.makedirs("downloads", exist_ok=True)

for url in download_urls:
    filename = url.split("/")[-1]
    
    print(f"Downloading {filename}...")
    
    resp = requests.get(
        f"{BASE}/tabs/{tab_id}/download",
        params={"url": url}
    )
    
    filepath = os.path.join("downloads", filename)
    with open(filepath, "wb") as f:
        f.write(resp.content)
    
    print(f"  Saved to {filepath} ({len(resp.content)} bytes)")

print(f"\nDownloaded {len(download_urls)} files")

Upload Multiple Files

import requests

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

files_to_upload = [
    ("document1.pdf", "#file-input-1"),
    ("document2.pdf", "#file-input-2"),
    ("image.jpg", "#file-input-3")
]

for filepath, selector in files_to_upload:
    print(f"Uploading {filepath}...")
    
    files = {"file": open(filepath, "rb")}
    data = {"selector": selector}
    
    resp = requests.post(
        f"{BASE}/tabs/{tab_id}/upload",
        files=files,
        data=data
    )
    
    result = resp.json()
    if result["success"]:
        print(f"  ✓ Uploaded {result['filename']}")
    else:
        print(f"  ✗ Failed to upload")

print("All files uploaded")

Error Handling

Tab Not Found (404)

curl "http://localhost:9867/tabs/nonexistent/download?url=https://example.com/file.pdf"
Response:
{
  "error": "tab not found",
  "statusCode": 404
}

Download Timeout (500)

curl "http://localhost:9867/tabs/tab_abc123/download?url=https://slow-server.com/large-file.zip&timeout=5"
Response:
{
  "error": "download timeout after 5 seconds",
  "statusCode": 500
}

Invalid File Input (400)

curl -X POST http://localhost:9867/tabs/tab_abc123/upload \
  -F "file=@document.pdf" \
  -F "selector=#nonexistent"
Response:
{
  "error": "file input not found: #nonexistent",
  "statusCode": 400
}

Best Practices

Set Appropriate Timeouts

# For large files, increase timeout
resp = requests.get(
    f"{BASE}/tabs/{tab_id}/download",
    params={
        "url": "https://example.com/large-file.zip",
        "timeout": 300  # 5 minutes
    }
)

Check File Size

resp = requests.get(
    f"{BASE}/tabs/{tab_id}/download",
    params={"url": url},
    stream=True
)

# Check Content-Length header
file_size = int(resp.headers.get('Content-Length', 0))
print(f"File size: {file_size / 1024 / 1024:.2f}MB")

# Stream download for large files
with open("large_file.zip", "wb") as f:
    for chunk in resp.iter_content(chunk_size=8192):
        f.write(chunk)

Validate Upload Success

# Upload file
resp = requests.post(
    f"{BASE}/tabs/{tab_id}/upload",
    files={"file": open("document.pdf", "rb")},
    data={"selector": "#file-input"}
)

result = resp.json()

if not result["success"]:
    raise Exception("Upload failed")

# Verify via JavaScript
verify = requests.post(f"{BASE}/tabs/{tab_id}/evaluate", json={
    "expression": "document.querySelector('#file-input').files.length > 0"
})

if verify.json()["result"]:
    print("File successfully attached to input")

Handle Download Directories

import os

# Create organized download structure
def download_organized(tab_id, url, category):
    download_dir = os.path.join("downloads", category)
    os.makedirs(download_dir, exist_ok=True)
    
    filename = url.split("/")[-1]
    filepath = os.path.join(download_dir, filename)
    
    resp = requests.get(
        f"http://localhost:9867/tabs/{tab_id}/download",
        params={"url": url}
    )
    
    with open(filepath, "wb") as f:
        f.write(resp.content)
    
    return filepath

# Usage
pdf_path = download_organized(tab_id, "https://example.com/doc.pdf", "pdfs")
image_path = download_organized(tab_id, "https://example.com/img.jpg", "images")

Use Cases

Automated Report Downloads

# Login and download reports
def download_monthly_reports(tab_id):
    # Navigate to reports page
    requests.post(f"{BASE}/tabs/{tab_id}/navigate",
        json={"url": "https://example.com/reports"})
    
    time.sleep(2)
    
    # Get download links
    snapshot = requests.get(
        f"{BASE}/tabs/{tab_id}/snapshot?filter=interactive"
    ).json()
    
    # Download each report
    for node in snapshot["nodes"]:
        if "report" in node.get("name", "").lower() and node.get("role") == "link":
            # Click download link
            requests.post(f"{BASE}/tabs/{tab_id}/action",
                json={"kind": "click", "ref": node["ref"]})
            
            time.sleep(1)

download_monthly_reports(tab_id)

Bulk File Uploads

# Upload multiple files to form
def upload_batch(tab_id, files_dir):
    import glob
    
    files = glob.glob(os.path.join(files_dir, "*.pdf"))
    
    for filepath in files:
        print(f"Uploading {os.path.basename(filepath)}...")
        
        resp = requests.post(
            f"{BASE}/tabs/{tab_id}/upload",
            files={"file": open(filepath, "rb")},
            data={"selector": "#file-input"}
        )
        
        if resp.json()["success"]:
            # Click upload button
            requests.post(f"{BASE}/tabs/{tab_id}/action",
                json={"kind": "click", "ref": "upload_btn"})
            
            time.sleep(2)

upload_batch(tab_id, "documents/")

Download with Authentication

# Download protected files
def download_authenticated(tab_id, url, cookies):
    # Set cookies first
    requests.post(f"{BASE}/tabs/{tab_id}/cookies", json={
        "url": url,
        "cookies": cookies
    })
    
    # Then download
    resp = requests.get(
        f"{BASE}/tabs/{tab_id}/download",
        params={"url": url}
    )
    
    return resp.content

# Usage
session_cookies = [
    {"name": "session_id", "value": "abc123"}
]

file_data = download_authenticated(
    tab_id,
    "https://example.com/protected/file.pdf",
    session_cookies
)

Next Steps

Cookies API

Manage authentication cookies

Actions API

Click download links

Navigation

Navigate to download pages

Evaluation

Trigger downloads via JavaScript