Skip to main content

Browser Automation

Drive a real browser programmatically: step-based automation, persistent sessions, action recording, lazy-load / network capture, WebSocket and Server-Sent Events scraping, and screenshots.

What it automates

CapabilityDetails
Step-based automationnavigate, click, type, extract, wait, screenshot, scroll, submit, …
Persistent sessionsCreate/save/restore/destroy browser sessions with cookies + storage
Action recordingRecord browser actions into a reusable Playwright script
CaptureLazy-load/infinite-scroll detection, network API-call extraction
StreamingWebSocket + SSE data capture
ScreenshotsFull-page screenshots as base64 PNG

Endpoints

Routers: routers/automation.py (Automation), routers/sessions.py (Sessions), routers/recorder.py (Recorder), routers/scraping.py + routers/scraping_api.py (Capture), routers/advanced.py (WS/SSE)

MethodPathSummary
POST/v1/automateExecute browser automation steps (steps, session_id, headless, viewport)
POST/v1/screenshotScreenshot a URL → base64 PNG
POST/v1/session/createCreate a persistent session (url, persist default true)
POST/v1/session/destroyDestroy a session (save_state optional)
GET/v1/sessionsList active + saved sessions
POST/v1/session/saveSave current session state (cookies, storage) to disk
POST/v1/session/restoreRestore a saved session into a browser context
POST/v1/record/startStart recording browser actions
POST/v1/record/stepRecord one action step (action, selector, value)
POST/v1/record/exportExport recording as a script (fmt default json)
POST/v1/record/clearClear recorded actions
POST/v1/capture/lazyDetect lazy loading / infinite scroll, generate scroll scripts
POST/v1/capture/networkExtract API calls, GraphQL queries, JSON-LD, Next.js/Nuxt state
POST/v1/ws/scrapeCapture a WebSocket data stream (url, max_messages, message_filter)
POST/v1/sse/scrapeCapture Server-Sent Events (url, max_events, event_filter)

POST /v1/automate

Request body (AutomateRequest):

FieldTypeDefaultDescription
session_idstringReuse an existing browser session
stepsarrayRequired. Ordered list of steps
headlessbooleantrueRun headless
viewportobject{width, height} override

Step schema: action (required), selector, value, url, timeout (default 30000 ms), wait_until (default networkidle).

Example — login flow:

curl -X POST http://localhost:8005/v1/automate \
-H "Content-Type: application/json" \
-H "Authorization: Bearer <key>" \
-d '{
"steps": [
{"action": "navigate", "url": "https://login.example.com"},
{"action": "type", "selector": "#username", "value": "user"},
{"action": "type", "selector": "#password", "value": "pass"},
{"action": "click", "selector": "#login-btn"},
{"action": "extract", "selectors": {"title": "h1"}}
]
}'

Response (200): the extracted data from the final step, e.g. { "title": "Welcome, user" }.

Sessions

# Create a persistent session
curl -X POST http://localhost:8005/v1/session/create \
-H "Content-Type: application/json" \
-H "Authorization: Bearer <key>" \
-d '{"url": "https://example.com", "persist": true}'

# → { "success": true, "data": { "session_id": "sess_abc123", "persist": true } }

# Reuse it in automation
curl -X POST http://localhost:8005/v1/automate \
-H "Content-Type: application/json" \
-H "Authorization: Bearer <key>" \
-d '{
"session_id": "sess_abc123",
"steps": [{"action": "navigate", "url": "https://example.com"}]
}'

Saved sessions are stored in the sessions volume (/app/sessions in Docker, ~/.pry/sessions on bare metal) and survive restarts.

Recording

curl -X POST http://localhost:8005/v1/record/start \
-H "Content-Type: application/json" \
-H "Authorization: Bearer <key>" \
-d '{"session_id": "sess_abc123"}'

curl -X POST http://localhost:8005/v1/record/step \
-H "Content-Type: application/json" \
-H "Authorization: Bearer <key>" \
-d '{"session_id": "sess_abc123", "action": "click", "selector": "#checkout"}'

curl -X POST http://localhost:8005/v1/record/export \
-H "Content-Type: application/json" \
-H "Authorization: Bearer <key>" \
-d '{"session_id": "sess_abc123", "fmt": "json"}'

Capture

# Lazy-load / infinite scroll detection + generated scroll script
curl -X POST http://localhost:8005/v1/capture/lazy \
-H "Content-Type: application/json" \
-H "Authorization: Bearer <key>" \
-d '{"url": "https://app.example.com/feed", "auto_scroll": true, "max_scrolls": 5}'

# Network capture — find the hidden APIs a SPA calls
curl -X POST http://localhost:8005/v1/capture/network \
-H "Content-Type: application/json" \
-H "Authorization: Bearer <key>" \
-d '{"url": "https://app.example.com"}'

Response (/v1/capture/network):

{
"success": true,
"data": {
"url": "https://app.example.com",
"api_calls": ["https://api.example.com/v1/products"],
"graphql_queries": ["query Products { products { id name } }"],
"json_ld": [{"@type": "Product"}],
"nextjs_props": true,
"nuxt_state": false
}
}

WebSocket / SSE

# Capture WebSocket messages
curl -X POST http://localhost:8005/v1/ws/scrape \
-H "Content-Type: application/json" \
-H "Authorization: Bearer <key>" \
-d '{"url": "wss://stream.example.com/trades", "max_messages": 100, "timeout": 30}'

# Capture Server-Sent Events
curl -X POST http://localhost:8005/v1/sse/scrape \
-H "Content-Type: application/json" \
-H "Authorization: Bearer <key>" \
-d '{"url": "https://stream.example.com/events", "max_events": 50, "timeout": 30}'

Screenshots

curl -X POST http://localhost:8005/v1/screenshot \
-H "Content-Type: application/json" \
-H "Authorization: Bearer <key>" \
-d '{"url": "https://example.com"}'

Response (200):

{
"success": true,
"data": {
"screenshot": "data:image/png;base64,iVBORw0KGgoAAAANSUhEUg..."
}
}

MCP tools

ToolBacking endpoint
pry_screenshotPOST /v1/screenshot

For deeper automation from agents, compose pry_scrape (with bypassCloudflare) + pry_extract on rendered content.

Who uses this

  • Login-gated scraping — automate sign-in once, reuse the session for data extraction.
  • E2E QA — scripted flows with screenshots for visual verification.
  • SPA / hidden-API discoverycapture/network to find the JSON APIs behind a JavaScript app, then scrape those directly.
  • Real-time dataws/scrape / sse/scrape for live feeds (trades, notifications, events).
  • Workflow automation — record actions once, export as Playwright scripts, run in CI.

Next steps