Run Task
curl --request POST \
--url https://api.example.com/browser/sessions/{id}/tasks \
--header 'Content-Type: application/json' \
--data '
{
"url": "<string>",
"waitUntil": "<string>",
"actions": [
{}
],
"screenshot": {},
"pdf": {},
"content": true,
"filename": "<string>",
"credentialId": "<string>",
"mode": "<string>",
"selectors": {},
"success": {},
"pauseTimeoutMs": 123
}
'import requests
url = "https://api.example.com/browser/sessions/{id}/tasks"
payload = {
"url": "<string>",
"waitUntil": "<string>",
"actions": [{}],
"screenshot": {},
"pdf": {},
"content": True,
"filename": "<string>",
"credentialId": "<string>",
"mode": "<string>",
"selectors": {},
"success": {},
"pauseTimeoutMs": 123
}
headers = {"Content-Type": "application/json"}
response = requests.post(url, json=payload, headers=headers)
print(response.text)const options = {
method: 'POST',
headers: {'Content-Type': 'application/json'},
body: JSON.stringify({
url: '<string>',
waitUntil: '<string>',
actions: [{}],
screenshot: {},
pdf: {},
content: true,
filename: '<string>',
credentialId: '<string>',
mode: '<string>',
selectors: {},
success: {},
pauseTimeoutMs: 123
})
};
fetch('https://api.example.com/browser/sessions/{id}/tasks', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));<?php
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => "https://api.example.com/browser/sessions/{id}/tasks",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "POST",
CURLOPT_POSTFIELDS => json_encode([
'url' => '<string>',
'waitUntil' => '<string>',
'actions' => [
[
]
],
'screenshot' => [
],
'pdf' => [
],
'content' => true,
'filename' => '<string>',
'credentialId' => '<string>',
'mode' => '<string>',
'selectors' => [
],
'success' => [
],
'pauseTimeoutMs' => 123
]),
CURLOPT_HTTPHEADER => [
"Content-Type: application/json"
],
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}package main
import (
"fmt"
"strings"
"net/http"
"io"
)
func main() {
url := "https://api.example.com/browser/sessions/{id}/tasks"
payload := strings.NewReader("{\n \"url\": \"<string>\",\n \"waitUntil\": \"<string>\",\n \"actions\": [\n {}\n ],\n \"screenshot\": {},\n \"pdf\": {},\n \"content\": true,\n \"filename\": \"<string>\",\n \"credentialId\": \"<string>\",\n \"mode\": \"<string>\",\n \"selectors\": {},\n \"success\": {},\n \"pauseTimeoutMs\": 123\n}")
req, _ := http.NewRequest("POST", url, payload)
req.Header.Add("Content-Type", "application/json")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}HttpResponse<String> response = Unirest.post("https://api.example.com/browser/sessions/{id}/tasks")
.header("Content-Type", "application/json")
.body("{\n \"url\": \"<string>\",\n \"waitUntil\": \"<string>\",\n \"actions\": [\n {}\n ],\n \"screenshot\": {},\n \"pdf\": {},\n \"content\": true,\n \"filename\": \"<string>\",\n \"credentialId\": \"<string>\",\n \"mode\": \"<string>\",\n \"selectors\": {},\n \"success\": {},\n \"pauseTimeoutMs\": 123\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.example.com/browser/sessions/{id}/tasks")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["Content-Type"] = 'application/json'
request.body = "{\n \"url\": \"<string>\",\n \"waitUntil\": \"<string>\",\n \"actions\": [\n {}\n ],\n \"screenshot\": {},\n \"pdf\": {},\n \"content\": true,\n \"filename\": \"<string>\",\n \"credentialId\": \"<string>\",\n \"mode\": \"<string>\",\n \"selectors\": {},\n \"success\": {},\n \"pauseTimeoutMs\": 123\n}"
response = http.request(request)
puts response.read_body{
"url": "<string>",
"screenshot": "<string>",
"pdf": "<string>",
"content": {},
"actionResults": [
{}
]
}Tasks
Run Task
Run a scripted sequence of browser actions (navigate, click, type, scroll, evaluate, upload, authenticate, etc.) and optionally return a screenshot, PDF, or page content in the same response.
POST
/
browser
/
sessions
/
{id}
/
tasks
Run Task
curl --request POST \
--url https://api.example.com/browser/sessions/{id}/tasks \
--header 'Content-Type: application/json' \
--data '
{
"url": "<string>",
"waitUntil": "<string>",
"actions": [
{}
],
"screenshot": {},
"pdf": {},
"content": true,
"filename": "<string>",
"credentialId": "<string>",
"mode": "<string>",
"selectors": {},
"success": {},
"pauseTimeoutMs": 123
}
'import requests
url = "https://api.example.com/browser/sessions/{id}/tasks"
payload = {
"url": "<string>",
"waitUntil": "<string>",
"actions": [{}],
"screenshot": {},
"pdf": {},
"content": True,
"filename": "<string>",
"credentialId": "<string>",
"mode": "<string>",
"selectors": {},
"success": {},
"pauseTimeoutMs": 123
}
headers = {"Content-Type": "application/json"}
response = requests.post(url, json=payload, headers=headers)
print(response.text)const options = {
method: 'POST',
headers: {'Content-Type': 'application/json'},
body: JSON.stringify({
url: '<string>',
waitUntil: '<string>',
actions: [{}],
screenshot: {},
pdf: {},
content: true,
filename: '<string>',
credentialId: '<string>',
mode: '<string>',
selectors: {},
success: {},
pauseTimeoutMs: 123
})
};
fetch('https://api.example.com/browser/sessions/{id}/tasks', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));<?php
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => "https://api.example.com/browser/sessions/{id}/tasks",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "POST",
CURLOPT_POSTFIELDS => json_encode([
'url' => '<string>',
'waitUntil' => '<string>',
'actions' => [
[
]
],
'screenshot' => [
],
'pdf' => [
],
'content' => true,
'filename' => '<string>',
'credentialId' => '<string>',
'mode' => '<string>',
'selectors' => [
],
'success' => [
],
'pauseTimeoutMs' => 123
]),
CURLOPT_HTTPHEADER => [
"Content-Type: application/json"
],
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}package main
import (
"fmt"
"strings"
"net/http"
"io"
)
func main() {
url := "https://api.example.com/browser/sessions/{id}/tasks"
payload := strings.NewReader("{\n \"url\": \"<string>\",\n \"waitUntil\": \"<string>\",\n \"actions\": [\n {}\n ],\n \"screenshot\": {},\n \"pdf\": {},\n \"content\": true,\n \"filename\": \"<string>\",\n \"credentialId\": \"<string>\",\n \"mode\": \"<string>\",\n \"selectors\": {},\n \"success\": {},\n \"pauseTimeoutMs\": 123\n}")
req, _ := http.NewRequest("POST", url, payload)
req.Header.Add("Content-Type", "application/json")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}HttpResponse<String> response = Unirest.post("https://api.example.com/browser/sessions/{id}/tasks")
.header("Content-Type", "application/json")
.body("{\n \"url\": \"<string>\",\n \"waitUntil\": \"<string>\",\n \"actions\": [\n {}\n ],\n \"screenshot\": {},\n \"pdf\": {},\n \"content\": true,\n \"filename\": \"<string>\",\n \"credentialId\": \"<string>\",\n \"mode\": \"<string>\",\n \"selectors\": {},\n \"success\": {},\n \"pauseTimeoutMs\": 123\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.example.com/browser/sessions/{id}/tasks")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["Content-Type"] = 'application/json'
request.body = "{\n \"url\": \"<string>\",\n \"waitUntil\": \"<string>\",\n \"actions\": [\n {}\n ],\n \"screenshot\": {},\n \"pdf\": {},\n \"content\": true,\n \"filename\": \"<string>\",\n \"credentialId\": \"<string>\",\n \"mode\": \"<string>\",\n \"selectors\": {},\n \"success\": {},\n \"pauseTimeoutMs\": 123\n}"
response = http.request(request)
puts response.read_body{
"url": "<string>",
"screenshot": "<string>",
"pdf": "<string>",
"content": {},
"actionResults": [
{}
]
}Overview
The task runner is the workhorse of the Browser Session API. A single request can:- Navigate to a
url(optional) - Execute a sequential list of
actionsagainst the active page - Capture output artifacts —
screenshot,pdf, and/orcontent— at the end
Path Parameters
string
required
Browser session ID (UUID).
Body
string
Optional URL to navigate to before running
actions.string
default:"load"
Wait condition for the initial navigation. One of
domcontentloaded, load, networkidle.object[]
Sequential list of actions to execute. See Action schema below.
object
When present, a screenshot is taken after all actions complete. Supports
{ fullPage?: boolean, selector?: string }.object
When present, renders a PDF after all actions complete. Accepts the same options as
POST /browser/sessions/{id}/pdf (format, landscape, margin, etc.). Returned base64-encoded.boolean
When true, returns
{ html, url } of the final page in the response.Action schema
Every action has atype field. The remaining fields depend on the type.
| Type | Required fields | Optional fields |
|---|---|---|
navigate | url | waitUntil |
click | selector or coordinates | — |
type | selector, text | — |
press | key | selector |
scroll | one of selector / coordinates / text | — |
wait | selector or text | — |
evaluate | script | — |
screenshot | — | selector |
uploadFile | selector, filename | — |
authenticate | mode + matching fields | credentialId, selectors, success, pauseTimeoutMs |
select | selector, text | — |
hover | selector | — |
string
For
uploadFile: must match a filename previously uploaded via POST /browser/sessions/{id}/files.string
For
authenticate when mode is vault or vault_then_prompt: UUID of a credential from POST /browser/credentials. Never pass raw username/password.string
For
authenticate: one of vault, prompt_user, vault_then_prompt.object
For
authenticate: { username, password, submit?, totp? } — CSS selectors pointing at each login form field.object
For
authenticate: how to detect login success. { condition: "url" | "selector" | "text" | "networkIdle", value: string, timeoutMs?: integer }.integer
default:"300000"
For
authenticate with mode: prompt_user: max time to wait for the end-user to complete login via the live view.Example Request
curl -X POST "https://api.scrapengine.io/api/v1/browser/sessions/baa3f390-fa6e-4a24-b84a-a575a5f3a9c7/tasks" \
-H "Authorization: Bearer $SCRAPENGINE_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"url": "https://example.com",
"waitUntil": "load",
"actions": [
{ "type": "click", "selector": "a[href=\"/login\"]" },
{ "type": "type", "selector": "#email", "text": "[email protected]" },
{ "type": "type", "selector": "#password", "text": "hunter2" },
{ "type": "click", "selector": "button[type=submit]" },
{ "type": "wait", "selector": "#dashboard" }
],
"screenshot": { "fullPage": true },
"content": true
}'
curl -X POST "https://api.scrapengine.io/api/v1/browser/sessions/baa3f390-fa6e-4a24-b84a-a575a5f3a9c7/tasks" \
-H "Authorization: Bearer $SCRAPENGINE_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"url": "https://app.example.com/login",
"actions": [
{
"type": "authenticate",
"mode": "vault",
"credentialId": "4a0d6b3a-1f10-4c6f-8a99-8e2b7f2c1234",
"selectors": {
"username": "#email",
"password": "#password",
"submit": "button[type=submit]"
},
"success": { "condition": "url", "value": "/dashboard", "timeoutMs": 30000 }
},
{ "type": "navigate", "url": "https://app.example.com/invoices/latest" }
],
"pdf": { "format": "A4", "printBackground": true }
}'
Response
Success Response (201)
string
Effective URL of the active tab after all actions.
string
Base64-encoded PNG, present when the request included
screenshot.string
Base64-encoded PDF bytes, present when the request included
pdf.object
{ html, url }, present when the request had content: true.object[]
One entry per action, in order. Shape depends on the action type (e.g.
evaluate returns { value }, authenticate returns { success, reason }).{
"url": "https://app.example.com/dashboard",
"screenshot": "iVBORw0KGgoAAAANSUhEUgAA...",
"content": {
"url": "https://app.example.com/dashboard",
"html": "<!doctype html>..."
},
"actionResults": [
{ "type": "click", "ok": true },
{ "type": "type", "ok": true, "charactersTyped": 18 },
{ "type": "authenticate", "ok": true, "reason": "success" }
]
}
Error Responses
| Status | Description |
|---|---|
400 | Invalid body — unknown action type, missing required fields for an action, or conflicting parameters. |
401 | Unauthorized — invalid or missing API key. |
404 | Session not found, or a selector inside an action matched nothing. |
408 | An action timed out (e.g. wait selector did not appear, authenticate success condition not met). |
422 | Action failed semantically (e.g. authenticate with mode: vault and domain_mismatch). |
503 | The browser session is temporarily unreachable. |
Notes
- Actions run sequentially. Order matters — put
waitbetween flaky interactions. screenshot,pdf, andcontentare all independent and can be combined in a single task.- For long-running login flows, prefer
authenticateover scriptedtype/clickpairs — it handles common anti-bot consent banners and supports vault-stored credentials. filenameinuploadFilemust be uploaded first viaPOST /browser/sessions/{id}/files.
Was this page helpful?