Automation REST API

Tabs

Read and drive the tabs a running profile already has open. These attach to an existing tab rather than a scratch one, because the point is to see what the person sees. They existed only as MCP tools until 2026-09-15; the routes here are the same capability on the REST surface, where the project’s own rule always required them.

List open tabs

GET/api/v1/profiles/:id/tabs

Every page target the profile has open, newest last, chrome:// pages included. The ids are what every other tab and page route takes as tabId.

Path parameters

FieldTypeWhat it is
idrequiredstringThe record’s id.

Returns

{ total, tabs: [{ id, title, url, type, attached }] }

Errors

  • 400 — the profile is not running.

Open a tab

POST/api/v1/profiles/:id/tabs

Opens a URL in a new tab. The browser navigates it itself, so this returns as soon as the tab exists rather than when the page has loaded — wait for it with POST /profiles/:id/page/wait or read it with a page route, which do wait.

Path parameters

FieldTypeWhat it is
idrequiredstringThe record’s id.

Body

FieldTypeWhat it is
urlrequiredstringAbsolute URL to open.

Returns

The new tab.

Close a tab

DELETE/api/v1/profiles/:id/tabs/:tabId

Closes one tab. Closing the last one stops the profile, a couple of seconds later, through the same clean shutdown POST /profiles/:id/stop runs — cookies flushed, session written, exit marked clean. It used to leave the browser running: macOS keeps an application alive with no windows, so what was left was four processes, a Dock tile with nothing under it, and GET /running still reporting the profile. Opening another tab inside that couple of seconds cancels it, so close-then-open is not a race. A one-time profile retires to the trash, exactly as it would have on stop.

Path parameters

FieldTypeWhat it is
idrequiredstringThe record’s id.
tabIdrequiredstringThe tab to close.

Returns

{ closed: true, tabId }

Errors

  • 404 — no profile with that id, or it is not running.

Read a page

GET/api/v1/profiles/:id/tabs/read

The visible text of the page, its title, its URL and its links. Uses innerText rather than textContent, so it is what a person sees rather than the contents of every <script> and <style> — which on a detection site is the collector’s own source.

Path parameters

FieldTypeWhat it is
idrequiredstringThe record’s id.

Query parameters

FieldTypeWhat it is
tabIdstringTab id from GET /profiles/:id/tabs. Omit for the tab with content on it.
htmlbooleanAlso return document.documentElement.outerHTML.
maxCharsnumberCap on characters, 200–200000 (default 20000).

Returns

{ url, title, text, links, html? }

Screenshot a tab

GET/api/v1/profiles/:id/tabs/screenshot

A PNG of the tab, base64, for when the text is not the answer.

Path parameters

FieldTypeWhat it is
idrequiredstringThe record’s id.

Query parameters

FieldTypeWhat it is
tabIdstringTab id from GET /profiles/:id/tabs. Omit for the tab with content on it.
fullPagebooleanCapture beyond the viewport.

Returns

{ format: "png", base64 }

Run script in a tab

POST/api/v1/profiles/:id/tabs/evaluate

Evaluates a JavaScript expression in the page’s own world and returns its value, so it sees the page’s variables and the fingerprint exactly as the page does. An await is fine; the result is awaited. Return something JSON can carry. For the invisible world, and for refs, use POST /profiles/:id/page/evaluate.

Path parameters

FieldTypeWhat it is
idrequiredstringThe record’s id.

Body

FieldTypeWhat it is
expressionrequiredstringA JavaScript expression.
tabIdstringTab id from GET /profiles/:id/tabs. Omit for the tab with content on it.

Returns

{ value }

Click a selector

POST/api/v1/profiles/:id/tabs/click

Clicks the element a CSS selector names, as a real mouse event at its centre. Deliberately not element.click(), which dispatches an untrusted event with no preceding move. POST /profiles/:id/page/click is the fuller version: it scrolls with a real wheel first and moves along a human trajectory.

Path parameters

FieldTypeWhat it is
idrequiredstringThe record’s id.

Body

FieldTypeWhat it is
selectorrequiredstringCSS selector.
tabIdstringTab id from GET /profiles/:id/tabs. Omit for the tab with content on it.

Returns

{ x, y } — where it clicked.

Record requests for a window

POST/api/v1/profiles/:id/tabs/watch-network

Records every request the tab makes for a number of seconds and returns them. Answers what a screenshot cannot: which third party a page really calls, whether a request went out at all, where a detector posted its verdict. The recording domain is enabled only for the window you ask for and turned off again. For recording that spans several actions, use POST /profiles/:id/page/network/start.

Path parameters

FieldTypeWhat it is
idrequiredstringThe record’s id.

Body

FieldTypeWhat it is
secondsnumberHow long to record, 1–60 (default 8).
tabIdstringTab id from GET /profiles/:id/tabs. Omit for the tab with content on it.

Returns

{ total, requests: [{ method, url, resourceType, status, mimeType, fromCache, failed }] }

Read site storage

GET/api/v1/profiles/:id/tabs/storage

What the site has stored in this profile: cookies, localStorage and sessionStorage. The cookie jar is the profile’s real identity — more of what re-identifies a returning visitor lives here than in any fingerprint field.

Path parameters

FieldTypeWhat it is
idrequiredstringThe record’s id.

Query parameters

FieldTypeWhat it is
tabIdstringTab id from GET /profiles/:id/tabs. Omit for the tab with content on it.

Returns

{ local, session, cookies }

Write site storage

POST/api/v1/profiles/:id/tabs/storage

Sets or removes localStorage or sessionStorage keys for the tab’s origin. A null value removes the key.

Path parameters

FieldTypeWhat it is
idrequiredstringThe record’s id.

Body

FieldTypeWhat it is
whichrequired"local" | "session"Which store to write.
entriesrequiredRecord<string, string | null>Keys to set; null removes.
tabIdstringTab id from GET /profiles/:id/tabs. Omit for the tab with content on it.

Returns

{ written }

Next Try it on your own accounts

Run the API on your own profiles

The REST API and the MCP server are part of Pro: $49 a month, with the first 14 days free. Free has every browser feature and no API key.