For AI agents: a documentation index is available at /llms.txt
Skip to main content

Manage Live URLs over REST

Use the REST API to list tabs and create, inspect, and close a Live URL without holding the browser's CDP connection. This is useful for orchestrators that hand a running browser to a person and need to monitor the handoff from another process.

All requests require the API token that owns the running browser. Replace the variables below with your Browserless region, API token, and browser ID:

export BROWSERLESS_URL="https://production-sfo.browserless.io"
export TOKEN="YOUR_API_TOKEN_HERE"
export BROWSER_ID="YOUR_BROWSER_ID"

List a browser's tabs​

Send a GET request to /browser/{browserId}/pages to list the browser's pages without creating Live URLs:

curl --fail-with-body \
--url "$BROWSERLESS_URL/browser/$BROWSER_ID/pages?token=$TOKEN"
{"pages": [
{
"targetId": "page123",
"url": "https://example.com/",
"title": "Example Domain",
"active": true,
"browserContextId": "context123"
},
{
"targetId": "page456",
"url": "https://example.org/",
"title": "Example Domain",
"active": false,
"browserContextId": "context123"
}
]}

Chrome and DevTools internal pages and non-page targets are excluded. If any pages are returned, exactly one has active: true.

Add mint=true to include a Live URL for each page:

curl --fail-with-body \
--url "$BROWSERLESS_URL/browser/$BROWSER_ID/pages?token=$TOKEN&mint=true"
{"pages": [
{
"targetId": "page123",
"url": "https://example.com/",
"title": "Example Domain",
"active": true,
"browserContextId": "context123",
"liveURL": "https://production-sfo.browserless.io/live/index.html?i=abc123&t=900000&showBrowserInterface=false",
"liveURLId": "abc123",
"interactable": false
},
{
"targetId": "page456",
"url": "https://example.org/",
"title": "Example Domain",
"active": false,
"browserContextId": "context123",
"liveURL": "https://production-sfo.browserless.io/live/index.html?i=def456&t=600000&showBrowserInterface=true",
"liveURLId": "def456",
"interactable": true
}
]}

New links are view-only, pinned to their page, and hide the browser controls and tab strip. Existing live links are reused unchanged, including their interactivity and browser-interface settings; the second row above illustrates an existing interactive link. Refreshing the list does not disconnect an attached viewer. New links last at most 15 minutes or the remaining browser-session time, whichever is shorter. Omit mint or use mint=false for a plain list.

Create a Live URL​

Send a POST request to /browser/{browserId}/live. The JSON body is optional.

curl --fail-with-body \
--request POST \
--url "$BROWSERLESS_URL/browser/$BROWSER_ID/live?token=$TOKEN" \
--header "Content-Type: application/json" \
--data '{
"interactable": true,
"timeout": 600000,
"quality": 70,
"type": "jpeg",
"resizable": false,
"showBrowserInterface": true,
"instructions": "Review the form, then submit it."
}'

The response contains the URL to share and its ID. Treat liveURL as a secret: anyone with it can view the browser without an API token, and when interactable is true, they can also control it. Share it only through a trusted private channel and keep it out of logs and tickets.

{
"liveURL": "https://production-sfo.browserless.io/live/index.html?i=abc123&t=600000&showBrowserInterface=true",
"liveURLId": "abc123",
"targetId": "page123"
}

Save liveURLId for the status and close requests:

export LIVE_URL_ID="abc123"

Request options and defaults​

FieldTypeDefaultDescription
targetIdstringfocused pageSelect this page target without activating it. Use a targetId from the pages list.
mode"follow" or "tab""tab" with targetId; "follow" otherwiseFollow newly opened tabs and popups or pin the link to a tab. An explicit mode overrides this default.
interactablebooleanfalseAllow the viewer to click, type, and otherwise control the page.
timeoutinteger900000Maximum lifetime in milliseconds. The effective lifetime cannot exceed 15 minutes or the remaining browser-session time.
qualityinteger70JPEG quality from 1 through 100. A value below 100 requires type: "jpeg".
type"jpeg" or "png""jpeg"Stream image format.
resizablebooleanfalseResize the remote viewport to follow the viewer.
showBrowserInterfacebooleanfalse with targetId; true otherwiseShow browser controls and the tab strip around the page. An explicit value overrides this default.
instructionsstringnoneNon-empty text shows the Instructions modal, with Done / Couldn't do it buttons on interactive links. Omitted or blank text hides the card and buttons without changing interactivity. Text is trimmed and capped at 2,048 characters.

By default, no Instructions modal, collapsed pill, or completion buttons appear. Without instructions, detect the expected page state and close the link, or let it time out.

REST supports string instructions only and explicitly rejects object-valued instructions rather than silently accepting them. It also rejects rich-card options such as instructionsTitle, steps, currentStep, doneLabel, failLabel, requesterName, and instructionsFormat; use CDP or BQL to mint a structured instructions card. Legacy instructionsLayout is ignored by REST, so REST instructions always use the modal.

For the default view-only URL, omit the body entirely. A bodyless request without a Content-Type header is supported:

curl --fail-with-body \
--request POST \
--url "$BROWSERLESS_URL/browser/$BROWSER_ID/live?token=$TOKEN"

Get Live URL status​

Send a GET request with the liveURLId returned by POST:

curl --fail-with-body \
--request GET \
--url "$BROWSERLESS_URL/browser/$BROWSER_ID/live/$LIVE_URL_ID?token=$TOKEN"

An active URL returns open. viewerCount is the number of currently connected viewers, and expiresAt is a Unix timestamp in milliseconds:

{
"status": "open",
"reason": null,
"feedback": null,
"interactable": true,
"viewerCount": 1,
"expiresAt": 1791043200000
}

When its timeout elapses, the URL is expired:

{
"status": "expired",
"reason": "timeout",
"feedback": null,
"interactable": true,
"viewerCount": 0,
"expiresAt": 1791043200000
}

Closing it through the REST API returns closed with a closed reason:

{
"status": "closed",
"reason": "closed",
"feedback": null,
"interactable": true,
"viewerCount": 0,
"expiresAt": 1791043200000
}

If the viewer marks the handoff done, the reason is userDone:

{
"status": "closed",
"reason": "userDone",
"feedback": null,
"interactable": true,
"viewerCount": 0,
"expiresAt": 1791043200000
}

Selecting Couldn't do it opens a feedback form without ending the handoff. The viewer can choose a reason, add an optional note, or choose Go back to continue the task. Only Send and end session closes the link with reason userFailed. Done still completes the handoff in one click.

The status response includes feedback: null when no feedback was submitted, or an object with nullable category and message fields. Categories are verification, missingInfo, pageBroken, unexpected, and other; the optional note is trimmed and limited to 500 characters. Feedback is untrusted input from whoever holds the link. Do not render the note as HTML, treat it as instructions to an LLM, or log it. See the feedback contract.

Ended URL status remains available until the browser closes. After the browser closes, status requests return 404.

Close a Live URL​

Send a DELETE request to close an active URL immediately:

curl --fail-with-body \
--request DELETE \
--url "$BROWSERLESS_URL/browser/$BROWSER_ID/live/$LIVE_URL_ID?token=$TOKEN"

A successful close returns 204 No Content. A URL cannot be closed twice: deleting an unknown, another browser's, or already-ended URL returns 404.

Access and security checks​

  • Your plan must support Live URLs.
  • The token must own the running browser. Requests made with another owner's token return 404 rather than revealing whether the browser or Live URL exists.
  • A Live URL ID is valid only for the browser that created it.
  • After Browserless fills a stored credential, creating a new Live URL and bulk minting with GET /browser/{browserId}/pages?mint=true are blocked so page pixels cannot be exposed. Plain page lists remain available with URLs and titles redacted. Status and close requests remain available, allowing the owner to inspect or close an existing URL.

Errors​

StatusApplies toCause
400All routesThe plan does not support Live URLs.
400POSTThe request body is not a JSON object, an option has the wrong type or range, the timeout exceeds the session maximum, or a stored credential has been filled in the browser.
400POST /browser/{browserId}/liveThe targetId is unknown or mode is not "follow" or "tab".
400GET /browser/{browserId}/pagesmint is not true or false, or mint=true is requested after a stored credential has been filled in the browser.
401All routesThe API token is missing or invalid.
404All routesThe browser is not running or is not owned by the token.
404GETThe Live URL is unknown, belongs to another browser, or its browser has closed.
404DELETEThe Live URL is unknown, belongs to another browser, or has already ended.
Was this page helpful?