9Login API: profiles#
List, create, edit, copy and delete profiles, and manage their fingerprints, cookies and browser data. Most changes need the profile to be stopped. See Profiles for what each setting means.
GET /v1/profiles#
List profiles, filtered and paged.
MCP tool: list_profiles. Access: read only.
| Field | Type | Required | Description |
|---|---|---|---|
search |
string |
no | The same search as the box above the list: title, tags, proxy, fingerprint, sub-user, and the profile id once the search is 4 characters or longer. |
tags |
string[] |
no | Only profiles carrying all of these tags, case-insensitive. Comma separated. |
status |
string |
no | "running" = anything not fully stopped, "stopped" = fully stopped, or one exact phase. Values: running, stopped, idle, starting, live, stopping. |
cloud |
string |
no | Cloud mark of the browser data. "behind": the cloud has a copy this computer does not have yet. "ahead": the profile ran on this computer since its last upload or download, or ran here and was never uploaded. "synced": the cloud copy matches this computer as of the last upload or download. "none": no cloud copy and the profile never ran here; it can still hold cookies written on this computer (initial cookies when it was created, or a cookie import). Writing cookies does not change the mark. Values: none, ahead, behind, synced. |
sort |
string |
no | Sort by creation time, last start, or title. Values: created, lastUsed, title. Default "created". |
order |
string |
no | Sort direction. Values: asc, desc. Default "desc". |
page |
integer |
no | Page number, from 1. Min 1. Default 1. |
limit |
integer |
no | Profiles per page. Min 1, max 500. Default 50. |
Request
Response
{
"ok": true,
"data": {
"total": 17,
"page": 1,
"limit": 2,
"items": [
{
"id": "a1b2c3",
"title": "shop 1",
"tags": [
"shop"
],
"createdAt": 1760000000000,
"lastUsedAt": 0,
"status": {
"phase": "idle",
"running": false,
"state": "ready"
},
"proxy": {
"type": "http",
"server": "1.2.3.4:8080",
"user": "u",
"hasPassword": true
},
"os": "windows",
"browser": "chrome",
"cloud": "none",
"assignedTo": null
}
]
}
}
GET /v1/profiles/{id}#
One profile with every field, its status, and a summary of its fingerprint. Proxy passwords are never returned (hasPassword says whether one is set).
MCP tool: get_profile. Access: read only.
No parameters.
GET /v1/profiles/{id}/logs#
What the browser of a profile printed with Log(): its startup script, run_code calls and 9Login's own messages. The lines of the profile's latest run, oldest first: the run going on now, or the last one after its browser closed. They are kept until the profile starts again or 9Login restarts; a profile that has not run since then answers startedAt null and no lines. Without since you get the last lines; with since, the lines from that number on, which is how to follow a running profile: pass next from the previous answer, and call again while next is below total. Lines count from 0 at the start of the run; a run keeps its last 2000 lines, and dropped says how many earlier ones are gone. A line longer than 2000 characters is cut.
MCP tool: get_logs. Access: read only.
| Field | Type | Required | Description |
|---|---|---|---|
since |
integer |
no | Line number to continue from: next of the previous answer. Min 0. |
limit |
integer |
no | Most lines to return. Min 1, max 1000. Default 200. |
Request
Response
POST /v1/profiles/create#
Create one or more profiles, each with a new fingerprint. Each new profile uses one of the new fingerprints the plan allows per 30 days. Fields left out take the same defaults as the New profile form, so onStartup is "restore". When present, the warnings list in the result names settings that may not work as planned.
MCP tool: create_profiles. Access: needs "Allow changes", needs the sub-user permission "create".
| Field | Type | Required | Description |
|---|---|---|---|
title |
string |
yes | Name in the list. Title macros such as {DATE} work as in the form. |
tags |
string[] |
no | Replaces the tags. |
url |
string |
no | Start page, opened when onStartup is "custom". |
onStartup |
string |
no | "restore" reopens the last tabs, "custom" opens url. New profiles default to "restore". A profile whose script must run on a known page needs "custom". Values: restore, custom. |
proxy |
object |
no | Replaces the whole proxy of the profile. |
proxy.type |
string |
yes | "system" = direct connection, "mine" = an entry of the shared proxy list. A proxy script is an entry of the list too (POST /v1/proxies/add-script), used with "mine". Values: system, http, socks4, socks5, ssh, mine. |
proxy.server |
string |
no | host:port, for http, socks4, socks5 and ssh. Shorthands such as host:port:user:pass and user:pass@host:port are accepted. A missing port takes 22 for ssh, 80 otherwise. |
proxy.user |
string |
no | Overrides the user found in server. |
proxy.password |
string |
no | Overrides the password found in server. |
proxy.proxyId |
string |
no | Id of a proxy list entry, for type "mine". |
fpConfig |
object |
no | The device the fingerprint is rolled from. Fields left out keep their value. Changing osType clears osVersion, browserVersion and device, as in the form. |
fpConfig.osType |
string |
no | "android" and "ios" need a plan that includes mobile OS. Values: windows, mac, linux, android, ios. |
fpConfig.osVersion |
string |
no | "" = random, else one of GET /v1/options platforms.<os>.versions. |
fpConfig.browserType |
string |
no | Must be one the OS supports (GET /v1/options). Values: chrome, edge, opera, firefox, safari. |
fpConfig.browserVersion |
string |
no | "" = random, else one of GET /v1/options browsers.<type>. |
fpConfig.device |
string |
no | Android or iOS device name, "" = random. |
fpConfig.screenWidth |
integer |
no | 0 with screenHeight 0 keeps the rolled screen; otherwise both at least 100. Min 0, max 10000. |
fpConfig.screenHeight |
integer |
no | Min 0, max 10000. |
fpConfig.cpusMode |
string |
no | "default" = the real machine, "random", or "fixed" to cpus. Values: default, random, fixed. |
fpConfig.cpus |
integer |
no | Min 0, max 256. |
fpConfig.ramMode |
string |
no | "default" = the real machine, "random", or "fixed" to ram (GB). Values: default, random, fixed. |
fpConfig.ram |
number |
no | GB, as navigator.deviceMemory reports it: 2, 4, 8, 16 or 32 on desktop, 1, 2, 4 or 8 on Android (GET /v1/options platforms.<os>.deviceMemory). iOS does not report it. Values: 1, 2, 4, 8, 16, 32. |
fpConfig.canvas |
string |
no | Values: default, noise. |
fpConfig.audio |
string |
no | Values: default, noise. |
fpConfig.rect |
string |
no | Values: default, noise. |
fpConfig.font |
string |
no | Values: default, noise. |
fpConfig.webgl |
string |
no | Values: default, auto, disabled. |
timezone |
string |
no | "auto" = this computer's zone, else an IANA id from GET /v1/options. |
language |
string |
no | "auto" = this computer's languages, else an Accept-Language list such as "en-US,en;q=0.9". |
geo |
object |
no | Geolocation. Fields left out keep their value. |
geo.mode |
string |
no | Values: disabled, prompt, allow. |
geo.latitude |
number |
no | Min -90, max 90. |
geo.longitude |
number |
no | Min -180, max 180. |
geo.accuracy |
integer |
no | Meters. Min 0, max 100000. |
webrtc |
object |
no | WebRTC. Fields left out keep their value. |
webrtc.mode |
string |
no | Values: default, hide, spoof. |
webrtc.publicIpV4 |
string |
no | |
webrtc.publicIpV6 |
string |
no | |
ipAuto |
object |
no | Take these from the proxy exit IP at every start instead of from the fields. For rotating proxies. |
ipAuto.timezone |
boolean |
no | |
ipAuto.language |
boolean |
no | |
ipAuto.geo |
boolean |
no | |
ipAuto.webrtc |
boolean |
no | |
flags |
object |
no | Browser switches. Fields left out keep their value. |
flags.jsEnabled |
boolean |
no | |
flags.imageEnabled |
boolean |
no | |
flags.cssEnabled |
boolean |
no | |
flags.soundEnabled |
boolean |
no | |
flags.jsDialogsEnabled |
boolean |
no | |
flags.webSecurityEnabled |
boolean |
no | |
flags.blockPortScan |
boolean |
no | Stops pages from calling localhost and the LAN. |
flags.incognito |
boolean |
no | |
flags.hideBrowser |
boolean |
no | |
flags.colorScheme |
string |
no | Values: system, light, dark. |
flags.downloadMode |
string |
no | Values: enabled, enabled-del, disabled. |
flags.notificationPermission |
string |
no | Values: prompt, allow, deny. |
extensionIds |
string[] |
no | Replaces the extensions, as ids from the extension list. Adding any needs a plan with extensions. |
scriptId |
string |
no | Id from the script library, "" for none; the script runs each time the profile starts. Setting one needs a plan with scripts. With onStartup "restore" it starts on a tab restored from the last session and may not run as planned. |
injectJs |
string |
no | JavaScript injected into every page. |
requestBlock |
object |
no | Requests to block. Fields left out keep their value. |
requestBlock.mode |
string |
no | Values: none, patterns, regex. |
requestBlock.value |
string |
no | Patterns, one per line, or one regular expression. |
headersRemove |
string[] |
no | Request headers to strip. |
headersOverride |
map of string |
no | Request headers to set, name to value. |
afterExit |
string |
no | What happens when the browser closes: "" nothing, "re-open", "clear-data", "clear-data-open". Values: `,re-open,clear-data,clear-data-open`. |
duration |
integer |
no | Seconds before the browser is closed again, 0 = until stopped. At most about 24 days. Min 0, max 2147478. |
count |
integer |
no | How many profiles to make from these fields. Each gets its own fingerprint; titles are numbered as in the form. Min 1, max 100. Default 1. |
cookies |
string |
no | Initial cookies, JSON, Netscape or Cookie header text (base64 accepted), written into every new profile once the server has accepted it, as POST /v1/profiles/import-cookies writes them. A Cookie header needs cookieDomain. They stay on this computer until the browser data of the profile is uploaded to the cloud. |
cookieDomain |
string |
no | The domain of cookies when they are a Cookie header (name=value; name2=value2), such as facebook.com. Ignored for JSON and Netscape text. |
Request
curl -X POST "http://127.0.0.1:37286/v1/profiles/create" \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"title": "shop {N}",
"count": 2,
"tags": [
"shop"
],
"proxy": {
"type": "http",
"server": "1.2.3.4:8080:user:pass"
},
"fpConfig": {
"osType": "windows",
"browserType": "chrome"
},
"timezone": "Europe/Berlin"
}'
Response
POST /v1/profiles/update#
Change fields on one or more stopped profiles. Profiles that are not fully stopped are skipped and reported. A change to the device fields of fpConfig rolls a new fingerprint, which counts against the plan's new fingerprints. When present, the warnings list in the result names settings that may not work as planned.
MCP tool: update_profiles. Access: needs "Allow changes", needs the sub-user permission "edit".
| Field | Type | Required | Description |
|---|---|---|---|
ids |
string[] |
yes | Profile ids. |
set |
object |
no | Fields to change on every listed profile. Fields left out keep their value. A title with macros is numbered across the list, as in Bulk edit. |
set.title |
string |
no | Name in the list. Title macros such as {DATE} work as in the form. |
set.tags |
string[] |
no | Replaces the tags. |
set.url |
string |
no | Start page, opened when onStartup is "custom". |
set.onStartup |
string |
no | "restore" reopens the last tabs, "custom" opens url. New profiles default to "restore". A profile whose script must run on a known page needs "custom". Values: restore, custom. |
set.proxy |
object |
no | Replaces the whole proxy of the profile. |
set.proxy.type |
string |
yes | "system" = direct connection, "mine" = an entry of the shared proxy list. A proxy script is an entry of the list too (POST /v1/proxies/add-script), used with "mine". Values: system, http, socks4, socks5, ssh, mine. |
set.proxy.server |
string |
no | host:port, for http, socks4, socks5 and ssh. Shorthands such as host:port:user:pass and user:pass@host:port are accepted. A missing port takes 22 for ssh, 80 otherwise. |
set.proxy.user |
string |
no | Overrides the user found in server. |
set.proxy.password |
string |
no | Overrides the password found in server. |
set.proxy.proxyId |
string |
no | Id of a proxy list entry, for type "mine". |
set.fpConfig |
object |
no | The device the fingerprint is rolled from. Fields left out keep their value. Changing osType clears osVersion, browserVersion and device, as in the form. |
set.fpConfig.osType |
string |
no | "android" and "ios" need a plan that includes mobile OS. Values: windows, mac, linux, android, ios. |
set.fpConfig.osVersion |
string |
no | "" = random, else one of GET /v1/options platforms.<os>.versions. |
set.fpConfig.browserType |
string |
no | Must be one the OS supports (GET /v1/options). Values: chrome, edge, opera, firefox, safari. |
set.fpConfig.browserVersion |
string |
no | "" = random, else one of GET /v1/options browsers.<type>. |
set.fpConfig.device |
string |
no | Android or iOS device name, "" = random. |
set.fpConfig.screenWidth |
integer |
no | 0 with screenHeight 0 keeps the rolled screen; otherwise both at least 100. Min 0, max 10000. |
set.fpConfig.screenHeight |
integer |
no | Min 0, max 10000. |
set.fpConfig.cpusMode |
string |
no | "default" = the real machine, "random", or "fixed" to cpus. Values: default, random, fixed. |
set.fpConfig.cpus |
integer |
no | Min 0, max 256. |
set.fpConfig.ramMode |
string |
no | "default" = the real machine, "random", or "fixed" to ram (GB). Values: default, random, fixed. |
set.fpConfig.ram |
number |
no | GB, as navigator.deviceMemory reports it: 2, 4, 8, 16 or 32 on desktop, 1, 2, 4 or 8 on Android (GET /v1/options platforms.<os>.deviceMemory). iOS does not report it. Values: 1, 2, 4, 8, 16, 32. |
set.fpConfig.canvas |
string |
no | Values: default, noise. |
set.fpConfig.audio |
string |
no | Values: default, noise. |
set.fpConfig.rect |
string |
no | Values: default, noise. |
set.fpConfig.font |
string |
no | Values: default, noise. |
set.fpConfig.webgl |
string |
no | Values: default, auto, disabled. |
set.timezone |
string |
no | "auto" = this computer's zone, else an IANA id from GET /v1/options. |
set.language |
string |
no | "auto" = this computer's languages, else an Accept-Language list such as "en-US,en;q=0.9". |
set.geo |
object |
no | Geolocation. Fields left out keep their value. |
set.geo.mode |
string |
no | Values: disabled, prompt, allow. |
set.geo.latitude |
number |
no | Min -90, max 90. |
set.geo.longitude |
number |
no | Min -180, max 180. |
set.geo.accuracy |
integer |
no | Meters. Min 0, max 100000. |
set.webrtc |
object |
no | WebRTC. Fields left out keep their value. |
set.webrtc.mode |
string |
no | Values: default, hide, spoof. |
set.webrtc.publicIpV4 |
string |
no | |
set.webrtc.publicIpV6 |
string |
no | |
set.ipAuto |
object |
no | Take these from the proxy exit IP at every start instead of from the fields. For rotating proxies. |
set.ipAuto.timezone |
boolean |
no | |
set.ipAuto.language |
boolean |
no | |
set.ipAuto.geo |
boolean |
no | |
set.ipAuto.webrtc |
boolean |
no | |
set.flags |
object |
no | Browser switches. Fields left out keep their value. |
set.flags.jsEnabled |
boolean |
no | |
set.flags.imageEnabled |
boolean |
no | |
set.flags.cssEnabled |
boolean |
no | |
set.flags.soundEnabled |
boolean |
no | |
set.flags.jsDialogsEnabled |
boolean |
no | |
set.flags.webSecurityEnabled |
boolean |
no | |
set.flags.blockPortScan |
boolean |
no | Stops pages from calling localhost and the LAN. |
set.flags.incognito |
boolean |
no | |
set.flags.hideBrowser |
boolean |
no | |
set.flags.colorScheme |
string |
no | Values: system, light, dark. |
set.flags.downloadMode |
string |
no | Values: enabled, enabled-del, disabled. |
set.flags.notificationPermission |
string |
no | Values: prompt, allow, deny. |
set.extensionIds |
string[] |
no | Replaces the extensions, as ids from the extension list. Adding any needs a plan with extensions. |
set.scriptId |
string |
no | Id from the script library, "" for none; the script runs each time the profile starts. Setting one needs a plan with scripts. With onStartup "restore" it starts on a tab restored from the last session and may not run as planned. |
set.injectJs |
string |
no | JavaScript injected into every page. |
set.requestBlock |
object |
no | Requests to block. Fields left out keep their value. |
set.requestBlock.mode |
string |
no | Values: none, patterns, regex. |
set.requestBlock.value |
string |
no | Patterns, one per line, or one regular expression. |
set.headersRemove |
string[] |
no | Request headers to strip. |
set.headersOverride |
map of string |
no | Request headers to set, name to value. |
set.afterExit |
string |
no | What happens when the browser closes: "" nothing, "re-open", "clear-data", "clear-data-open". Values: `,re-open,clear-data,clear-data-open`. |
set.duration |
integer |
no | Seconds before the browser is closed again, 0 = until stopped. At most about 24 days. Min 0, max 2147478. |
addTags |
string[] |
no | Tags to add, keeping the others. |
removeTags |
string[] |
no | Tags to remove, case-insensitive. |
confirmNewIdentity |
boolean |
no | Changing the device fields of fpConfig rolls a new fingerprint. On a profile that already has browsing data this is refused unless true. Default false. |
Request
POST /v1/profiles/tags#
Add, remove or replace tags on stopped profiles. Only the tags change. replace applies first, then add, then remove. A profile keeps at most 20 tags; extra ones are dropped. Profiles whose tags would stay the same are listed in unchanged and not written. Profiles that are not fully stopped are skipped and reported.
MCP tool: tag_profiles. Access: needs "Allow changes", needs the sub-user permission "edit".
| Field | Type | Required | Description |
|---|---|---|---|
ids |
string[] |
yes | Profile ids. |
add |
string[] |
no | Tags to add, keeping the others. |
remove |
string[] |
no | Tags to remove, case-insensitive. |
replace |
string[] |
no | Replaces all the tags. [] removes them all. |
Request
Response
POST /v1/profiles/duplicate#
Copy profiles, as Duplicate in the row menu does. Each copy keeps every setting of its source and gets a new id, a numbered title such as "shop 1 (2)" and a new fingerprint rolled from the same fpConfig. Browser data, cookies and cloud data are not copied. Each copy takes one profile of the plan and one of the new fingerprints the plan allows per 30 days. The source may be running.
MCP tool: duplicate_profiles. Access: needs "Allow changes", needs the sub-user permission "create".
| Field | Type | Required | Description |
|---|---|---|---|
ids |
string[] |
yes | Profiles to copy, at most 100. A profile may be running. |
count |
integer |
no | Copies of each profile. ids times count must be at most 100. Min 1, max 100. Default 1. |
Request
Response
POST /v1/profiles/regenerate-fp#
Give stopped profiles a new fingerprint, rolled from their own fpConfig. As "New fingerprint" in Bulk edit: fpConfig stays as it is, and what it leaves random is rolled again. Each profile uses one of the new fingerprints the plan allows per 30 days. Profiles that are not fully stopped are skipped and reported.
MCP tool: regenerate_fingerprints. Access: needs "Allow changes", needs the sub-user permission "edit".
| Field | Type | Required | Description |
|---|---|---|---|
ids |
string[] |
yes | Profile ids. |
confirmNewIdentity |
boolean |
no | On a profile that already has browsing data, a new fingerprint is refused unless true. Default false. |
Request
Response
POST /v1/profiles/ua-upgrade#
Move stopped profiles to the newest browser version this app supports, keeping the device. Moves each stopped profile to the newest version of its browser that this app supports, keeping the device: only the version numbers change, and no new fingerprint is used. It only ever moves a profile up, never to an older version. A browserVersion pinned in fpConfig follows the new version. Profiles it cannot move, such as Firefox, Safari or iOS, are listed in unchanged with reason "notSupported"; profiles already on that version or a newer one with reason "current". Profiles that are not fully stopped are skipped and reported.
MCP tool: upgrade_user_agent. Access: needs "Allow changes", needs the sub-user permission "edit".
| Field | Type | Required | Description |
|---|---|---|---|
ids |
string[] |
yes | Profile ids. |
Request
Response
POST /v1/profiles/export-cookies#
Read the cookies of one stopped profile as JSON, a Netscape cookies.txt or a Cookie header. Reads the cookies kept for the profile on this computer. text is what the Export panel of the Cookies dialog copies: format "json" is a pretty-printed array of cookies, "netscape" a cookies.txt with its header, "header" one line of name=value pairs as a Cookie request header carries them, and base64 encodes any of them (compact JSON inside). Every cookie is exported unless search narrows it. A header holds the cookies of one domain, given in domain (import it again with that domain); when the cookies span more than one, the call answers invalidParams on search, naming them. Cookies that cannot be decrypted on this computer are left out and counted in skipped. The profile must be fully stopped.
MCP tool: export_cookies. Access: needs "Allow changes", needs the sub-user permission "export".
| Field | Type | Required | Description |
|---|---|---|---|
id |
string |
yes | Profile id. |
format |
string |
no | "json": an array of cookies as Cookie-Editor and EditThisCookie read them. "netscape": a cookies.txt as curl and wget read it. "header": name=value; name2=value2 for one domain, without domain, path, expiry or flags. Values: json, netscape, header. Default "json". |
base64 |
boolean |
no | Return the text base64-encoded, as the Base64 tick of the dialog. The Import box reads it back. Default false. |
search |
string |
no | Only cookies whose domain, name, value or path contains this text, ignoring case, as in the search box of the Cookies dialog. Leave out for every cookie. |
Request
Response
POST /v1/profiles/import-cookies#
Write cookies from JSON, Netscape or Cookie header text into stopped profiles. Takes the same text as the Import box of the Cookies dialog: a JSON array of cookies (Cookie-Editor, EditThisCookie, Puppeteer, a 9Login export, or { "cookies": [...] }), a Netscape cookies.txt, or a Cookie header (name=value; name2=value2), any of them plain or base64. A Cookie header names no domain, so it needs domain, which is never guessed here; its cookies are stored for that domain and its subdomains, secure, on path /, and on facebook.com, instagram.com and x.com with the httpOnly and SameSite flags 9Login knows those sites set. The text is checked once for the whole list: corrected cookies are counted in adjusted, refused ones in rejected by reason (domain, name, value, path, hiddenPrefix, nameAndValue, and duplicate for a name a header repeats, of which the first is kept), and text with no usable cookie answers invalidParams. A cookie without an expiry (a session cookie, and every cookie of a header) is stored with one a year away, so the profile still has it when it starts. mode "merge" keeps the other cookies of the profile and overwrites those with the same domain, name and path; "replace" deletes every cookie first and needs "Allow deleting". Profiles that are not fully stopped, or whose browser data is being uploaded or downloaded, are skipped and reported. The cookies stay on this computer and do not change the profile's cloud mark: a start that pulls newer browser data from the cloud, or POST /v1/profiles/download, replaces them. Upload the profile with POST /v1/profiles/upload to keep them in the cloud and share them with other computers. A profile that never ran gets browser data here, so a later device change needs confirmNewIdentity. Keep the whole JSON body under 4 MB.
MCP tool: import_cookies. Access: needs "Allow changes".
| Field | Type | Required | Description |
|---|---|---|---|
ids |
string[] |
yes | Profile ids. |
cookies |
string |
yes | JSON, Netscape or Cookie header text, plain or base64. |
domain |
string |
no | The domain the cookies belong to, such as facebook.com, or a URL of the site. Needed when cookies is a Cookie header; ignored for JSON and Netscape text, whose cookies carry their own. |
mode |
string |
no | "merge" keeps the other cookies; "replace" deletes every cookie of the profile first and needs "Allow deleting". Values: merge, replace. Default "merge". |
Request
curl -X POST "http://127.0.0.1:37286/v1/profiles/import-cookies" \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"ids": [
"a1b2c3",
"d4e5f6"
],
"cookies": "[{\"domain\":\".example.com\",\"name\":\"sid\",\"value\":\"abc123\",\"path\":\"/\",\"secure\":true,\"httpOnly\":true,\"hostOnly\":false,\"session\":false,\"sameSite\":\"lax\",\"expirationDate\":1767225600},{\"domain\":\"Example.com\",\"name\":\"lang\",\"value\":\"en\",\"path\":\"/\",\"secure\":false,\"httpOnly\":false,\"hostOnly\":true,\"session\":true,\"sameSite\":\"unspecified\"}]",
"mode": "merge"
}'
Response
{
"ok": true,
"data": {
"format": "json",
"base64": false,
"total": 2,
"accepted": 2,
"adjusted": 1,
"rejected": {},
"imported": [
{
"id": "a1b2c3",
"written": 2,
"replaced": 1,
"cleared": 0
}
],
"failed": [
{
"id": "d4e5f6",
"code": "profileRunning",
"message": "The profile is not fully stopped. Stop it first."
}
]
}
}
POST /v1/profiles/clear-cookies#
Delete the cookies of stopped profiles, all of them or those matching a search. Needs "Allow deleting". There is no undo: sites signed in with these cookies are signed out. With search, only the cookies whose domain, name, value or path contains it are deleted; leave search out to delete every cookie. Profiles that are not fully stopped, or whose browser data is being uploaded or downloaded, are skipped and reported.
MCP tool: clear_cookies. Access: needs "Allow deleting".
| Field | Type | Required | Description |
|---|---|---|---|
ids |
string[] |
yes | Profile ids. |
search |
string |
no | Only cookies whose domain, name, value or path contains this text, ignoring case, as in the search box of the Cookies dialog. Leave out to delete every cookie; a blank search is refused. |
Request
POST /v1/profiles/clear-data#
Delete browser data of stopped profiles on this computer, the cache only or everything. Returns a job. mode "cache" deletes cached files only and keeps cookies, logins and site data. mode "all" deletes every piece of browser data of the profile on this computer (cookies, logins, site data; extensions show their first-run pages again) and needs "Allow deleting". There is no undo. The cloud copy is never touched: after "all", a profile with cloud data reads cloud "behind", and its next start pulls that data back (cloudNewer "pull"), fails ("fail") or opens with the empty data ("open"). afterExit "clear-data" never runs after a stop; call this after stopping instead. Profiles that are not fully stopped, or whose browser data is being uploaded or downloaded, are skipped and reported. The job result lists cleared and failed profiles, and cloud: the cloud mark of each profile after the clear.
MCP tool: clear_browser_data. Access: needs "Allow changes".
| Field | Type | Required | Description |
|---|---|---|---|
ids |
string[] |
yes | Profile ids. |
mode |
string |
yes | "cache": cached files only. "all": every piece of browser data on this computer, needs "Allow deleting". Values: cache, all. |
wait |
boolean |
no | Wait for the job to finish, at most waitSec, before answering. false answers at once with the job, to follow with GET /v1/jobs/{id}. Default true. |
waitSec |
integer |
no | How long wait may hold the request. Min 1, max 100. Default 60. |
Request
Response
{
"ok": true,
"data": {
"id": "j0123456789abcdef",
"kind": "clearData",
"state": "done",
"createdAt": 1760000000000,
"finishedAt": 1760000000800,
"progress": {
"done": 2,
"total": 2
},
"error": null,
"result": {
"cleared": [
"a1b2c3"
],
"failed": [
{
"id": "d4e5f6",
"code": "profileRunning",
"message": "The profile is not fully stopped. Stop it first."
}
],
"cloud": {
"a1b2c3": "behind",
"d4e5f6": "synced"
}
}
}
}
POST /v1/profiles/upload#
Upload the browser data of stopped profiles to the cloud, as the Upload data button does. Returns a job. Each profile keeps one cloud copy, and an upload replaces it: there is no history to go back to. Profiles whose cloud copy is newer than this computer's data fail with cloudNewer unless overwriteNewer is true. The job result lists the uploaded profiles with the size of their cloud copy in bytes, the ones already up to date, and why the rest failed. Send many profiles per call rather than one call per profile: the server limits uploads per minute for each account, and at most 2 cloud data jobs run at once.
MCP tool: upload_browser_data. Access: needs "Allow changes", needs a plan with cloud data.
| Field | Type | Required | Description |
|---|---|---|---|
ids |
string[] |
yes | Profile ids, at most 500 per call. |
overwriteNewer |
boolean |
no | Also upload profiles whose cloud copy is newer than the data on this computer (cloud "behind" in the profile list), replacing that copy. Without it they fail with cloudNewer. Default false. |
skipUnchanged |
boolean |
no | Skip profiles whose data has not changed since their last upload or download on this computer and list them in unchanged. Off, every profile is sent, as the Upload data button does. Default false. |
wait |
boolean |
no | Wait for the job to finish, at most waitSec, before answering. false answers at once with the job, to follow with GET /v1/jobs/{id}. Default true. |
waitSec |
integer |
no | How long wait may hold the request. Min 1, max 100. Default 60. |
Request
Response
{
"ok": true,
"data": {
"id": "j0123456789abcdef",
"kind": "upload",
"state": "done",
"createdAt": 1760000000000,
"finishedAt": 1760000003000,
"progress": {
"done": 1,
"total": 1
},
"error": null,
"result": {
"uploaded": [
{
"id": "a1b2c3",
"bytes": 184320
}
],
"unchanged": [],
"failed": [
{
"id": "d4e5f6",
"code": "cloudNewer",
"message": "The cloud copy is newer than this computer's data. Pass overwriteNewer true to replace it."
}
]
}
}
}
POST /v1/profiles/download#
Download the cloud copy of the browser data of stopped profiles, as the Download data button does. Returns a job. Replaces this computer's copy of the synced browser data (cookies and sessions, site storage and the like) with the cloud copy. This cannot be undone. Profiles whose data on this computer is newer than the cloud copy (they ran here since the last upload or download, cloud "ahead") fail with localNewer unless overwriteLocalNewer is true. Cookies written by POST /v1/profiles/import-cookies do not make a profile newer, so a download replaces them: upload the profile first to keep them, or pass skipUnchanged to leave alone the profiles whose cloud copy this computer already has. The job result lists the downloaded profiles with the size of their cloud copy in bytes, the ones already up to date, and why the rest failed. At most 250 profiles per call, because the server allows about 300 profile downloads a minute for each account, including those made before a Start; at most 2 cloud data jobs run at once.
MCP tool: download_browser_data. Access: needs "Allow changes", needs a plan with cloud data.
| Field | Type | Required | Description |
|---|---|---|---|
ids |
string[] |
yes | Profile ids, at most 250 per call. |
overwriteLocalNewer |
boolean |
no | Also download profiles whose data on this computer is newer than the cloud copy (cloud "ahead" in the profile list), replacing it. Without it they fail with localNewer. Default false. |
skipUnchanged |
boolean |
no | Skip profiles whose cloud copy is the one this computer last downloaded or uploaded, and list them in unchanged. Off, every profile is downloaded again, as the Download data button does. Default false. |
wait |
boolean |
no | Wait for the job to finish, at most waitSec, before answering. false answers at once with the job, to follow with GET /v1/jobs/{id}. Default true. |
waitSec |
integer |
no | How long wait may hold the request. Min 1, max 100. Default 60. |
Request
Response
{
"ok": true,
"data": {
"id": "j0123456789abcdef",
"kind": "download",
"state": "done",
"createdAt": 1760000000000,
"finishedAt": 1760000002000,
"progress": {
"done": 2,
"total": 2
},
"error": null,
"result": {
"downloaded": [
{
"id": "a1b2c3",
"bytes": 184320
}
],
"unchanged": [],
"failed": [
{
"id": "d4e5f6",
"code": "noCloudData",
"message": "The cloud has no browser data for this profile."
}
]
}
}
}
POST /v1/profiles/delete#
Delete stopped profiles, on the server and their browser data on this machine. Needs "Allow deleting" on the API & MCP screen. There is no undo. Profiles that are not fully stopped are skipped and reported.
MCP tool: delete_profiles. Access: needs "Allow deleting", needs the sub-user permission "delete".
| Field | Type | Required | Description |
|---|---|---|---|
ids |
string[] |
yes | Profile ids. |