Skip to Content

Custom Scripts

Custom scripts use the script field instead of a natural-language task. They follow the standard browser-use  API — the browser and session objects exposed to your script are browser-use objects.

Getting access

Custom scripts are off by default and are not self-service. Access is granted per API key after a manager approves your request personally — ask in the dashboard  chat and someone will get back to you. The same approval covers uv_args.

Until it is granted, the API returns 403:

{ "error": "custom browsing scripts are not enabled for this API key" }

Quick start

Minimal script body (not a full Python file):

await browser.navigate_to("https://example.com") return { "ok": True, "url": "https://example.com", }

Run via async endpoint:

curl -sS -X POST "https://llm.dat.ai/api/v1/browsing/async" \ -H "Authorization: Bearer YOUR_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "script": "await browser.navigate_to(\"https://example.com\")\nreturn {\"ok\": true, \"url\": \"https://example.com\"}", "fanout": 1, "timeout_sec": 300 }'

Poll for the result:

curl -sS "https://llm.dat.ai/api/v1/browsing/status?task_id=web:YOUR_TASK_ID" \ -H "Authorization: Bearer YOUR_API_KEY"

What you send

The script field is the body of an async function — use await directly. Do not wrap it in async def main() or call asyncio.run(...).

Available variables

NameDescription
browserMain browser-use object for navigation and page actions
sessionLower-level browser-use session object
asyncioPython asyncio module
jsonPython json module
osPython os module
sysPython sys module
humanHelper for pointer paths and character-by-character typing

For navigation:

await browser.navigate_to("https://example.com")

Returning results

Return JSON-serializable data (dict, list, string, number, bool, or null). The value becomes the task payload when success is true.

Limits

LimitValue
Maximum task timeout10,800 seconds (3 hours)
fanout1 to 10
session_key length128 characters
uv_args length1024 characters

timeout_sec is in seconds (e.g. 5 minutes = 300).

Use uv_args to install extra Python packages on the node for your script.

Example: extract page title

await browser.navigate_to("https://example.com") title = await browser.get_current_page_title() url = await browser.get_current_page_url() return { "ok": True, "title": title, "url": url, }

Example: run JavaScript

await browser.navigate_to("https://example.com") page = await browser.get_current_page() if page is None: return { "ok": False, "error": "No active page after navigation", } data = await page.evaluate(""" () => ({ title: document.title, h1: document.querySelector("h1")?.innerText || null }) """) return { "ok": True, "data": data }