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
| Field | Type | What it is |
|---|---|---|
idrequired | string | The 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
| Field | Type | What it is |
|---|---|---|
idrequired | string | The record’s id. |
Body
| Field | Type | What it is |
|---|---|---|
urlrequired | string | Absolute 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
| Field | Type | What it is |
|---|---|---|
idrequired | string | The record’s id. |
tabIdrequired | string | The 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
| Field | Type | What it is |
|---|---|---|
idrequired | string | The record’s id. |
Query parameters
| Field | Type | What it is |
|---|---|---|
tabId | string | Tab id from GET /profiles/:id/tabs. Omit for the tab with content on it. |
html | boolean | Also return document.documentElement.outerHTML. |
maxChars | number | Cap 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
| Field | Type | What it is |
|---|---|---|
idrequired | string | The record’s id. |
Query parameters
| Field | Type | What it is |
|---|---|---|
tabId | string | Tab id from GET /profiles/:id/tabs. Omit for the tab with content on it. |
fullPage | boolean | Capture 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
| Field | Type | What it is |
|---|---|---|
idrequired | string | The record’s id. |
Body
| Field | Type | What it is |
|---|---|---|
expressionrequired | string | A JavaScript expression. |
tabId | string | Tab 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
| Field | Type | What it is |
|---|---|---|
idrequired | string | The record’s id. |
Body
| Field | Type | What it is |
|---|---|---|
selectorrequired | string | CSS selector. |
tabId | string | Tab 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
| Field | Type | What it is |
|---|---|---|
idrequired | string | The record’s id. |
Body
| Field | Type | What it is |
|---|---|---|
seconds | number | How long to record, 1–60 (default 8). |
tabId | string | Tab 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
| Field | Type | What it is |
|---|---|---|
idrequired | string | The record’s id. |
Query parameters
| Field | Type | What it is |
|---|---|---|
tabId | string | Tab 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
| Field | Type | What it is |
|---|---|---|
idrequired | string | The record’s id. |
Body
| Field | Type | What it is |
|---|---|---|
whichrequired | "local" | "session" | Which store to write. |
entriesrequired | Record<string, string | null> | Keys to set; null removes. |
tabId | string | Tab id from GET /profiles/:id/tabs. Omit for the tab with content on it. |
Returns
{ written }
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.
Mosaic is a desktop app
Email yourself the link and open it on your computer.