APIAPIs and integrationsShardX Launcher APIProfiles

Profiles

List profiles

GEThttp://127.0.0.1:40325/profiles

Lists persistent profiles (temporary profiles are hidden), newest first, pinned on top. Each entry is enriched with live run state.

Authorizations
bearerAuth
Authorizationstringrequired

Permanent JWT from Settings → Automation API.

Responses
200Profile list.application/json

Launcher-facing profile metadata (returned by create).

idstring · uuidoptional
namestringoptional
notesstringoptional
proxy_idstring· nullableoptional
last_launched_atstring· nullableoptional

ISO-8601 or null.

created_atstring· nullableoptional
pinnedbooleanoptional
folderstringoptional
colorstring· nullableoptional

Icon accent as #rrggbb; null means it is derived from the name, which is what the browser does when nothing is chosen.

extensionsstring[]optional

Extension-library ids loaded at launch.

runningbooleanoptional
pidinteger · int64· nullableoptional
cdpobject · CdpInfo· nullableoptional

Chrome DevTools Protocol endpoint of a running profile.

Show propertiesHide properties
portintegeroptional

Chrome-chosen remote-debugging port.

http_urlstringoptional

REST base (/json, /json/version).

web_socket_debugger_urlstringoptional

Browser-level WS endpoint for Puppeteer/Playwright connect.

401Missing or invalid Bearer token.
GET/profiles
GET /profiles HTTP/1.1
Host: 127.0.0.1:40325
Authorization: Bearer YOUR_SECRET_TOKEN
Accept: */*
curl -X GET 'http://127.0.0.1:40325/profiles' \
  -H 'Authorization: Bearer YOUR_SECRET_TOKEN'
import requests

# Permanent JWT from Settings → Automation API.
token = "YOUR_SECRET_TOKEN"

url = "http://127.0.0.1:40325/profiles"
headers = {
    "Authorization": f"Bearer {token}",
}

response = requests.get(url, headers=headers, timeout=30)
response.raise_for_status()
print(response.status_code)
print(response.text)
// Permanent JWT from Settings → Automation API.
const token = "YOUR_SECRET_TOKEN";

const url = "http://127.0.0.1:40325/profiles";

const response = await fetch(url, {
  method: "GET",
  headers: {
    "Authorization": `Bearer ${token}`,
  },
});

console.log(response.status);
console.log(await response.text());
package main

import (
	"fmt"
	"io"
	"log"
	"net/http"
)

func main() {
	// Permanent JWT from Settings → Automation API.
	token := "YOUR_SECRET_TOKEN"

	url := "http://127.0.0.1:40325/profiles"

	req, err := http.NewRequest("GET", url, nil)
	if err != nil {
		log.Fatal(err)
	}
	req.Header.Set("Authorization", "Bearer "+token)

	resp, err := http.DefaultClient.Do(req)
	if err != nil {
		log.Fatal(err)
	}
	defer resp.Body.Close()

	out, err := io.ReadAll(resp.Body)
	if err != nil {
		log.Fatal(err)
	}
	fmt.Println(resp.Status)
	fmt.Println(string(out))
}
// Cargo.toml: reqwest = { version = "0.12", features = ["json"] }, tokio = { version = "1", features = ["full"] }

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
    // Permanent JWT from Settings → Automation API.
    let token = "YOUR_SECRET_TOKEN";

    let client = reqwest::Client::new();
    let response = client
        .get("http://127.0.0.1:40325/profiles")
        .header("Authorization", format!("Bearer {token}"))
        .send()
        .await?;

    println!("{}", response.status());
    println!("{}", response.text().await?);
    Ok(())
}
using System;
using System.Net.Http;
using System.Net.Http.Headers;
using System.Threading.Tasks;

class Program
{
    static async Task Main()
    {
        // Permanent JWT from Settings → Automation API.
        var token = "YOUR_SECRET_TOKEN";

        using var client = new HttpClient();
        client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", token);

        var request = new HttpRequestMessage(HttpMethod.Get, "http://127.0.0.1:40325/profiles");

        var response = await client.SendAsync(request);
        Console.WriteLine((int)response.StatusCode);
        Console.WriteLine(await response.Content.ReadAsStringAsync());
    }
}
// build: c++ -std=c++17 main.cpp -lcurl
#include <curl/curl.h>

#include <iostream>
#include <string>

static size_t write_cb(char *ptr, size_t size, size_t nmemb, void *userdata) {
    static_cast<std::string *>(userdata)->append(ptr, size * nmemb);
    return size * nmemb;
}

int main() {
    // Permanent JWT from Settings → Automation API.
    const std::string token = "YOUR_SECRET_TOKEN";

    curl_global_init(CURL_GLOBAL_DEFAULT);
    CURL *curl = curl_easy_init();
    if (!curl) {
        std::cerr << "curl_easy_init failed\n";
        curl_global_cleanup();
        return 1;
    }

    struct curl_slist *headers = nullptr;
    headers = curl_slist_append(headers, ("Authorization: Bearer " + token).c_str());

    std::string response;
    curl_easy_setopt(curl, CURLOPT_URL, "http://127.0.0.1:40325/profiles");
    curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headers);
    curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, write_cb);
    curl_easy_setopt(curl, CURLOPT_WRITEDATA, &response);

    const CURLcode rc = curl_easy_perform(curl);
    if (rc != CURLE_OK) {
        std::cerr << curl_easy_strerror(rc) << "\n";
    } else {
        long status = 0;
        curl_easy_getinfo(curl, CURLINFO_RESPONSE_CODE, &status);
        std::cout << status << "\n" << response << "\n";
    }

    curl_slist_free_all(headers);
    curl_easy_cleanup(curl);
    curl_global_cleanup();
    return rc == CURLE_OK ? 0 : 1;
}
200Profile list.
[
  {
    "id": "123e4567-e89b-12d3-a456-426614174000",
    "name": "text",
    "notes": "text",
    "proxy_id": "text",
    "last_launched_at": "text",
    "created_at": "text",
    "pinned": true,
    "folder": "text",
    "color": "text",
    "extensions": [
      "text"
    ],
    "running": true,
    "pid": 1,
    "cdp": {
      "port": 1,
      "http_url": "http://127.0.0.1:53217",
      "web_socket_debugger_url": "ws://127.0.0.1:53217/devtools/browser/ab12-..."
    }
  }
]

Create a profile

POSThttp://127.0.0.1:40325/profiles

Persists a profile from a client-supplied fingerprint exactly as given (no re-randomization; uniquification already happened in /fingerprint/new). Use folder to file it; bind a proxy by stored proxy_id or attach one inline via proxy (a string that is NOT saved to the proxy store).

Authorizations
bearerAuth
Authorizationstringrequired

Permanent JWT from Settings → Automation API.

Body
application/json
namestringoptional
notesstringoptional
proxy_idstringoptional

Bind a proxy already in the store (by id).

proxystringoptional

Attach a proxy by string (host:port:user:pass or scheme://user:pass@host:port). On a persistent profile it is added to the proxy store (deduped by endpoint) and full-tested (UDP + geo), then bound by id; so it appears in the proxy list and QUIC/WebRTC gating has a cached result. On a temporary profile it is attached inline (not stored). Ignored if proxy_id is set.

folderstringoptional

Folder tag (ignored on /folders/{folder}/profiles, which wins).

colorstringoptional

Accent for the profile's window icon and for the pill carrying its name in the omnibox. Omit it and the icon derives a colour from the name while the pill keeps the browser's own toolbar colour.

extensionsstring[]optional

Extension-library ids (GET /extensions), loaded at launch. An id the library does not hold is a 400 rather than a profile that silently starts without it.

refresh_rateinteger· min: 24· max: 480optional

Claimed display refresh rate, written into screen.refresh_rate. No web API reports it; a page measures it by timing requestAnimationFrame, which is why leaving it out is not neutral; absent means 60, what most machines report, rather than whatever the host's own screen does. Frames can only be slowed, so the effective rate is the closest whole division of the host's panel at or under this.

fingerprintobject · Fingerprintrequired

Stored verbatim. Get one from /fingerprint/new and edit as needed.

Show propertiesHide properties
namestringoptional
notesstringoptional
seedintegeroptional

0 = overrides-only mode (the common case).

navigatorobjectoptional
Show propertiesHide properties
user_agentstringoptional
platformstringoptional
hardware_concurrencyintegeroptional
device_memoryinteger · enumoptional
Possible values:81632
languagestringoptional
do_not_trackbooleanoptional
screenobjectoptional
Show propertiesHide properties
widthintegeroptional
heightintegeroptional
avail_widthintegeroptional
avail_heightintegeroptional
color_depthintegeroptional
device_pixel_rationumberoptional
color_gamutstring · enumoptional
Possible values:srgbp3rec2020
refresh_rateinteger· min: 24· max: 480optional

How often the claimed display refreshes. Absent means 60. See the refresh_rate field on the create/edit requests.

client_hintsobjectoptional

Sec-CH-UA family (browser.vision calls this hints).

Show propertiesHide properties
platformstringoptional
platform_versionstringoptional
architecturestringoptional
bitnessstringoptional
mobilebooleanoptional
webglobjectoptional
Show propertiesHide properties
unmasked_vendorstringoptional
unmasked_rendererstringoptional
webgpuobjectoptional
webrtcstring · enumoptional

WebRTC handling mode.

Possible values:autotcp_onlyblock
noiseobject · NoisePrefsoptional

Per-vector anti-fingerprint noise. Each block is {enabled, seed} (+ feature-specific knobs). enabled:false = pass-through.

Show propertiesHide properties
canvasobject · NoiseBlockoptional
Show propertiesHide properties
enabledbooleanoptional
seedintegeroptional

Per-profile entropy; 0 = derive automatically.

webglobject · NoiseBlockoptional
Show propertiesHide properties
enabledbooleanoptional
seedintegeroptional

Per-profile entropy; 0 = derive automatically.

intensitynumberoptional
audioobject · NoiseBlockoptional
Show propertiesHide properties
enabledbooleanoptional
seedintegeroptional

Per-profile entropy; 0 = derive automatically.

intensitynumberoptional
client_rectsobject · NoiseBlockoptional
Show propertiesHide properties
enabledbooleanoptional
seedintegeroptional

Per-profile entropy; 0 = derive automatically.

max_offsetnumberoptional
sensorsobject · NoiseBlockoptional
Show propertiesHide properties
enabledbooleanoptional
seedintegeroptional

Per-profile entropy; 0 = derive automatically.

fontsobject · NoiseBlockoptional

enabled:true hides a small deterministic per-profile subset of non-essential fonts (real host fonts otherwise pass through).

Show propertiesHide properties
enabledbooleanoptional
seedintegeroptional

Per-profile entropy; 0 = derive automatically.

networkobjectoptional
Show propertiesHide properties
blocked_portsinteger[]optional

Local-network port-scan defense (ports_protection).

timezonestringoptional

IANA name, or "auto" to resolve from the bound proxy at launch.

Responses
200Created profile metadata.application/json

Launcher-facing profile metadata (returned by create).

idstring · uuidoptional
namestringoptional
notesstringoptional
proxy_idstring· nullableoptional
last_launched_atstring· nullableoptional

ISO-8601 or null.

created_atstring· nullableoptional
pinnedbooleanoptional
folderstringoptional
colorstring· nullableoptional

Icon accent as #rrggbb; null means it is derived from the name, which is what the browser does when nothing is chosen.

extensionsstring[]optional

Extension-library ids loaded at launch.

400Missing/!object `fingerprint`, or an unparseable proxy string.application/json
errorstringrequired
401Missing or invalid Bearer token.
POST/profiles
POST /profiles HTTP/1.1
Host: 127.0.0.1:40325
Authorization: Bearer YOUR_SECRET_TOKEN
Content-Type: application/json
Accept: */*

{
  "name": "text",
  "notes": "text",
  "proxy_id": "text",
  "proxy": "socks5://user:[email protected]:1080",
  "folder": "text",
  "color": "#2FCB80",
  "extensions": [
    "text"
  ],
  "refresh_rate": 60,
  "fingerprint": {
    "name": "text",
    "notes": "text",
    "seed": 1,
    "navigator": {
      "user_agent": "text",
      "platform": "Win32",
      "hardware_concurrency": 12,
      "device_memory": 16,
      "language": "text",
      "do_not_track": true
    },
    "screen": {
      "width": 1,
      "height": 1,
      "avail_width": 1,
      "avail_height": 1,
      "color_depth": 24,
      "device_pixel_ratio": 2,
      "color_gamut": "",
      "refresh_rate": 60
    },
    "client_hints": {
      "platform": "text",
      "platform_version": "text",
      "architecture": "x86",
      "bitness": "64",
      "mobile": true
    },
    "webgl": {
      "unmasked_vendor": "text",
      "unmasked_renderer": "text"
    },
    "webgpu": {},
    "webrtc": "auto",
    "noise": {
      "canvas": {
        "enabled": true,
        "seed": 1
      },
      "webgl": {
        "enabled": true,
        "seed": 1,
        "intensity": 1
      },
      "audio": {
        "enabled": true,
        "seed": 1,
        "intensity": 1
      },
      "client_rects": {
        "enabled": true,
        "seed": 1,
        "max_offset": 1
      },
      "sensors": {
        "enabled": true,
        "seed": 1
      },
      "fonts": {
        "enabled": true,
        "seed": 1
      }
    },
    "network": {
      "blocked_ports": [
        1
      ]
    },
    "timezone": "text"
  }
}
curl -X POST 'http://127.0.0.1:40325/profiles' \
  -H 'Authorization: Bearer YOUR_SECRET_TOKEN' \
  -H 'Content-Type: application/json' \
  -d '{"name":"text","notes":"text","proxy_id":"text","proxy":"socks5://user:[email protected]:1080","folder":"text","color":"#2FCB80","extensions":["text"],"refresh_rate":60,"fingerprint":{"name":"text","notes":"text","seed":1,"navigator":{"user_agent":"text","platform":"Win32","hardware_concurrency":12,"device_memory":16,"language":"text","do_not_track":true},"screen":{"width":1,"height":1,"avail_width":1,"avail_height":1,"color_depth":24,"device_pixel_ratio":2,"color_gamut":"","refresh_rate":60},"client_hints":{"platform":"text","platform_version":"text","architecture":"x86","bitness":"64","mobile":true},"webgl":{"unmasked_vendor":"text","unmasked_renderer":"text"},"webgpu":{},"webrtc":"auto","noise":{"canvas":{"enabled":true,"seed":1},"webgl":{"enabled":true,"seed":1,"intensity":1},"audio":{"enabled":true,"seed":1,"intensity":1},"client_rects":{"enabled":true,"seed":1,"max_offset":1},"sensors":{"enabled":true,"seed":1},"fonts":{"enabled":true,"seed":1}},"network":{"blocked_ports":[1]},"timezone":"text"}}'
import requests

# Permanent JWT from Settings → Automation API.
token = "YOUR_SECRET_TOKEN"

url = "http://127.0.0.1:40325/profiles"
headers = {
    "Authorization": f"Bearer {token}",
}
payload = {
    "name": "text",
    "notes": "text",
    "proxy_id": "text",
    "proxy": "socks5://user:[email protected]:1080",
    "folder": "text",
    "color": "#2FCB80",
    "extensions": [
        "text",
    ],
    "refresh_rate": 60,
    "fingerprint": {
        "name": "text",
        "notes": "text",
        "seed": 1,
        "navigator": {
            "user_agent": "text",
            "platform": "Win32",
            "hardware_concurrency": 12,
            "device_memory": 16,
            "language": "text",
            "do_not_track": True,
        },
        "screen": {
            "width": 1,
            "height": 1,
            "avail_width": 1,
            "avail_height": 1,
            "color_depth": 24,
            "device_pixel_ratio": 2,
            "color_gamut": "",
            "refresh_rate": 60,
        },
        "client_hints": {
            "platform": "text",
            "platform_version": "text",
            "architecture": "x86",
            "bitness": "64",
            "mobile": True,
        },
        "webgl": {
            "unmasked_vendor": "text",
            "unmasked_renderer": "text",
        },
        "webgpu": {},
        "webrtc": "auto",
        "noise": {
            "canvas": {
                "enabled": True,
                "seed": 1,
            },
            "webgl": {
                "enabled": True,
                "seed": 1,
                "intensity": 1,
            },
            "audio": {
                "enabled": True,
                "seed": 1,
                "intensity": 1,
            },
            "client_rects": {
                "enabled": True,
                "seed": 1,
                "max_offset": 1,
            },
            "sensors": {
                "enabled": True,
                "seed": 1,
            },
            "fonts": {
                "enabled": True,
                "seed": 1,
            },
        },
        "network": {
            "blocked_ports": [
                1,
            ],
        },
        "timezone": "text",
    },
}

response = requests.post(url, headers=headers, json=payload, timeout=30)
response.raise_for_status()
print(response.status_code)
print(response.text)
// Permanent JWT from Settings → Automation API.
const token = "YOUR_SECRET_TOKEN";

const url = "http://127.0.0.1:40325/profiles";
const payload = {
  "name": "text",
  "notes": "text",
  "proxy_id": "text",
  "proxy": "socks5://user:[email protected]:1080",
  "folder": "text",
  "color": "#2FCB80",
  "extensions": [
    "text"
  ],
  "refresh_rate": 60,
  "fingerprint": {
    "name": "text",
    "notes": "text",
    "seed": 1,
    "navigator": {
      "user_agent": "text",
      "platform": "Win32",
      "hardware_concurrency": 12,
      "device_memory": 16,
      "language": "text",
      "do_not_track": true
    },
    "screen": {
      "width": 1,
      "height": 1,
      "avail_width": 1,
      "avail_height": 1,
      "color_depth": 24,
      "device_pixel_ratio": 2,
      "color_gamut": "",
      "refresh_rate": 60
    },
    "client_hints": {
      "platform": "text",
      "platform_version": "text",
      "architecture": "x86",
      "bitness": "64",
      "mobile": true
    },
    "webgl": {
      "unmasked_vendor": "text",
      "unmasked_renderer": "text"
    },
    "webgpu": {},
    "webrtc": "auto",
    "noise": {
      "canvas": {
        "enabled": true,
        "seed": 1
      },
      "webgl": {
        "enabled": true,
        "seed": 1,
        "intensity": 1
      },
      "audio": {
        "enabled": true,
        "seed": 1,
        "intensity": 1
      },
      "client_rects": {
        "enabled": true,
        "seed": 1,
        "max_offset": 1
      },
      "sensors": {
        "enabled": true,
        "seed": 1
      },
      "fonts": {
        "enabled": true,
        "seed": 1
      }
    },
    "network": {
      "blocked_ports": [
        1
      ]
    },
    "timezone": "text"
  }
};

const response = await fetch(url, {
  method: "POST",
  headers: {
    "Authorization": `Bearer ${token}`,
    "Content-Type": "application/json",
  },
  body: JSON.stringify(payload),
});

console.log(response.status);
console.log(await response.text());
package main

import (
	"bytes"
	"fmt"
	"io"
	"log"
	"net/http"
)

func main() {
	// Permanent JWT from Settings → Automation API.
	token := "YOUR_SECRET_TOKEN"

	url := "http://127.0.0.1:40325/profiles"
	body := bytes.NewBufferString(`{
  "name": "text",
  "notes": "text",
  "proxy_id": "text",
  "proxy": "socks5://user:[email protected]:1080",
  "folder": "text",
  "color": "#2FCB80",
  "extensions": [
    "text"
  ],
  "refresh_rate": 60,
  "fingerprint": {
    "name": "text",
    "notes": "text",
    "seed": 1,
    "navigator": {
      "user_agent": "text",
      "platform": "Win32",
      "hardware_concurrency": 12,
      "device_memory": 16,
      "language": "text",
      "do_not_track": true
    },
    "screen": {
      "width": 1,
      "height": 1,
      "avail_width": 1,
      "avail_height": 1,
      "color_depth": 24,
      "device_pixel_ratio": 2,
      "color_gamut": "",
      "refresh_rate": 60
    },
    "client_hints": {
      "platform": "text",
      "platform_version": "text",
      "architecture": "x86",
      "bitness": "64",
      "mobile": true
    },
    "webgl": {
      "unmasked_vendor": "text",
      "unmasked_renderer": "text"
    },
    "webgpu": {},
    "webrtc": "auto",
    "noise": {
      "canvas": {
        "enabled": true,
        "seed": 1
      },
      "webgl": {
        "enabled": true,
        "seed": 1,
        "intensity": 1
      },
      "audio": {
        "enabled": true,
        "seed": 1,
        "intensity": 1
      },
      "client_rects": {
        "enabled": true,
        "seed": 1,
        "max_offset": 1
      },
      "sensors": {
        "enabled": true,
        "seed": 1
      },
      "fonts": {
        "enabled": true,
        "seed": 1
      }
    },
    "network": {
      "blocked_ports": [
        1
      ]
    },
    "timezone": "text"
  }
}`)

	req, err := http.NewRequest("POST", url, body)
	if err != nil {
		log.Fatal(err)
	}
	req.Header.Set("Authorization", "Bearer "+token)
	req.Header.Set("Content-Type", "application/json")

	resp, err := http.DefaultClient.Do(req)
	if err != nil {
		log.Fatal(err)
	}
	defer resp.Body.Close()

	out, err := io.ReadAll(resp.Body)
	if err != nil {
		log.Fatal(err)
	}
	fmt.Println(resp.Status)
	fmt.Println(string(out))
}
// Cargo.toml: reqwest = { version = "0.12", features = ["json"] }, tokio = { version = "1", features = ["full"] }, serde_json = "1"

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
    // Permanent JWT from Settings → Automation API.
    let token = "YOUR_SECRET_TOKEN";

    let client = reqwest::Client::new();
    let response = client
        .post("http://127.0.0.1:40325/profiles")
        .header("Authorization", format!("Bearer {token}"))
        .json(&serde_json::json!({
          "name": "text",
          "notes": "text",
          "proxy_id": "text",
          "proxy": "socks5://user:[email protected]:1080",
          "folder": "text",
          "color": "#2FCB80",
          "extensions": [
            "text"
          ],
          "refresh_rate": 60,
          "fingerprint": {
            "name": "text",
            "notes": "text",
            "seed": 1,
            "navigator": {
              "user_agent": "text",
              "platform": "Win32",
              "hardware_concurrency": 12,
              "device_memory": 16,
              "language": "text",
              "do_not_track": true
            },
            "screen": {
              "width": 1,
              "height": 1,
              "avail_width": 1,
              "avail_height": 1,
              "color_depth": 24,
              "device_pixel_ratio": 2,
              "color_gamut": "",
              "refresh_rate": 60
            },
            "client_hints": {
              "platform": "text",
              "platform_version": "text",
              "architecture": "x86",
              "bitness": "64",
              "mobile": true
            },
            "webgl": {
              "unmasked_vendor": "text",
              "unmasked_renderer": "text"
            },
            "webgpu": {},
            "webrtc": "auto",
            "noise": {
              "canvas": {
                "enabled": true,
                "seed": 1
              },
              "webgl": {
                "enabled": true,
                "seed": 1,
                "intensity": 1
              },
              "audio": {
                "enabled": true,
                "seed": 1,
                "intensity": 1
              },
              "client_rects": {
                "enabled": true,
                "seed": 1,
                "max_offset": 1
              },
              "sensors": {
                "enabled": true,
                "seed": 1
              },
              "fonts": {
                "enabled": true,
                "seed": 1
              }
            },
            "network": {
              "blocked_ports": [
                1
              ]
            },
            "timezone": "text"
          }
        }))
        .send()
        .await?;

    println!("{}", response.status());
    println!("{}", response.text().await?);
    Ok(())
}
using System;
using System.Net.Http;
using System.Net.Http.Headers;
using System.Text;
using System.Threading.Tasks;

class Program
{
    static async Task Main()
    {
        // Permanent JWT from Settings → Automation API.
        var token = "YOUR_SECRET_TOKEN";

        using var client = new HttpClient();
        client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", token);

        var request = new HttpRequestMessage(HttpMethod.Post, "http://127.0.0.1:40325/profiles");
        request.Content = new StringContent("""
            {
              "name": "text",
              "notes": "text",
              "proxy_id": "text",
              "proxy": "socks5://user:[email protected]:1080",
              "folder": "text",
              "color": "#2FCB80",
              "extensions": [
                "text"
              ],
              "refresh_rate": 60,
              "fingerprint": {
                "name": "text",
                "notes": "text",
                "seed": 1,
                "navigator": {
                  "user_agent": "text",
                  "platform": "Win32",
                  "hardware_concurrency": 12,
                  "device_memory": 16,
                  "language": "text",
                  "do_not_track": true
                },
                "screen": {
                  "width": 1,
                  "height": 1,
                  "avail_width": 1,
                  "avail_height": 1,
                  "color_depth": 24,
                  "device_pixel_ratio": 2,
                  "color_gamut": "",
                  "refresh_rate": 60
                },
                "client_hints": {
                  "platform": "text",
                  "platform_version": "text",
                  "architecture": "x86",
                  "bitness": "64",
                  "mobile": true
                },
                "webgl": {
                  "unmasked_vendor": "text",
                  "unmasked_renderer": "text"
                },
                "webgpu": {},
                "webrtc": "auto",
                "noise": {
                  "canvas": {
                    "enabled": true,
                    "seed": 1
                  },
                  "webgl": {
                    "enabled": true,
                    "seed": 1,
                    "intensity": 1
                  },
                  "audio": {
                    "enabled": true,
                    "seed": 1,
                    "intensity": 1
                  },
                  "client_rects": {
                    "enabled": true,
                    "seed": 1,
                    "max_offset": 1
                  },
                  "sensors": {
                    "enabled": true,
                    "seed": 1
                  },
                  "fonts": {
                    "enabled": true,
                    "seed": 1
                  }
                },
                "network": {
                  "blocked_ports": [
                    1
                  ]
                },
                "timezone": "text"
              }
            }
            """, Encoding.UTF8, "application/json");

        var response = await client.SendAsync(request);
        Console.WriteLine((int)response.StatusCode);
        Console.WriteLine(await response.Content.ReadAsStringAsync());
    }
}
// build: c++ -std=c++17 main.cpp -lcurl
#include <curl/curl.h>

#include <iostream>
#include <string>

static size_t write_cb(char *ptr, size_t size, size_t nmemb, void *userdata) {
    static_cast<std::string *>(userdata)->append(ptr, size * nmemb);
    return size * nmemb;
}

int main() {
    // Permanent JWT from Settings → Automation API.
    const std::string token = "YOUR_SECRET_TOKEN";

    curl_global_init(CURL_GLOBAL_DEFAULT);
    CURL *curl = curl_easy_init();
    if (!curl) {
        std::cerr << "curl_easy_init failed\n";
        curl_global_cleanup();
        return 1;
    }

    struct curl_slist *headers = nullptr;
    headers = curl_slist_append(headers, ("Authorization: Bearer " + token).c_str());
    headers = curl_slist_append(headers, "Content-Type: application/json");

    const std::string body = R"json({
  "name": "text",
  "notes": "text",
  "proxy_id": "text",
  "proxy": "socks5://user:[email protected]:1080",
  "folder": "text",
  "color": "#2FCB80",
  "extensions": [
    "text"
  ],
  "refresh_rate": 60,
  "fingerprint": {
    "name": "text",
    "notes": "text",
    "seed": 1,
    "navigator": {
      "user_agent": "text",
      "platform": "Win32",
      "hardware_concurrency": 12,
      "device_memory": 16,
      "language": "text",
      "do_not_track": true
    },
    "screen": {
      "width": 1,
      "height": 1,
      "avail_width": 1,
      "avail_height": 1,
      "color_depth": 24,
      "device_pixel_ratio": 2,
      "color_gamut": "",
      "refresh_rate": 60
    },
    "client_hints": {
      "platform": "text",
      "platform_version": "text",
      "architecture": "x86",
      "bitness": "64",
      "mobile": true
    },
    "webgl": {
      "unmasked_vendor": "text",
      "unmasked_renderer": "text"
    },
    "webgpu": {},
    "webrtc": "auto",
    "noise": {
      "canvas": {
        "enabled": true,
        "seed": 1
      },
      "webgl": {
        "enabled": true,
        "seed": 1,
        "intensity": 1
      },
      "audio": {
        "enabled": true,
        "seed": 1,
        "intensity": 1
      },
      "client_rects": {
        "enabled": true,
        "seed": 1,
        "max_offset": 1
      },
      "sensors": {
        "enabled": true,
        "seed": 1
      },
      "fonts": {
        "enabled": true,
        "seed": 1
      }
    },
    "network": {
      "blocked_ports": [
        1
      ]
    },
    "timezone": "text"
  }
})json";

    std::string response;
    curl_easy_setopt(curl, CURLOPT_URL, "http://127.0.0.1:40325/profiles");
    curl_easy_setopt(curl, CURLOPT_CUSTOMREQUEST, "POST");
    curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headers);
    curl_easy_setopt(curl, CURLOPT_POSTFIELDS, body.c_str());
    curl_easy_setopt(curl, CURLOPT_POSTFIELDSIZE, static_cast<long>(body.size()));
    curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, write_cb);
    curl_easy_setopt(curl, CURLOPT_WRITEDATA, &response);

    const CURLcode rc = curl_easy_perform(curl);
    if (rc != CURLE_OK) {
        std::cerr << curl_easy_strerror(rc) << "\n";
    } else {
        long status = 0;
        curl_easy_getinfo(curl, CURLINFO_RESPONSE_CODE, &status);
        std::cout << status << "\n" << response << "\n";
    }

    curl_slist_free_all(headers);
    curl_easy_cleanup(curl);
    curl_global_cleanup();
    return rc == CURLE_OK ? 0 : 1;
}
{
  "id": "123e4567-e89b-12d3-a456-426614174000",
  "name": "text",
  "notes": "text",
  "proxy_id": "text",
  "last_launched_at": "text",
  "created_at": "text",
  "pinned": true,
  "folder": "text",
  "color": "text",
  "extensions": [
    "text"
  ]
}
{
  "error": "text"
}

Create a temporary profile

POSThttp://127.0.0.1:40325/profiles/temporary

Creates a profile from a random (or specified) library fingerprint, uniquified like /fingerprint/new and stored verbatim, flagged temporary: hidden from listings and auto-deleted when its browser closes (or purged on next app start after a crash). Pair with POST /profiles/{id}/start.

Authorizations
bearerAuth
Authorizationstringrequired

Permanent JWT from Settings → Automation API.

Body
application/json
fingerprint_idstringoptional

Library entry to base off; random match for platform when omitted.

platformstring · enumoptional

Used to pick a random fingerprint when fingerprint_id is omitted; host OS when both omitted.

Possible values:WindowsmacOSLinux
proxystringoptional

Inline proxy string (not saved to the store).

namestringoptional
folderstringoptional
refresh_rateinteger· min: 24· max: 480optional

Claimed display refresh rate, written into screen.refresh_rate. No web API reports it; a page measures it by timing requestAnimationFrame, which is why leaving it out is not neutral; absent means 60, what most machines report, rather than whatever the host's own screen does. Frames can only be slowed, so the effective rate is the closest whole division of the host's panel at or under this.

noiseobjectoptional

Per-vector fingerprint noise. Omitted vectors keep their defaults (disabled). Two formats can be combined: shorthand {"canvas": true, "webgl": true}, which also applies the UI default intensity to webgl and client_rects, and a full object such as {"canvas": {"enabled": true, "seed": 42}}, matching the format returned by GET /profiles/{id}.

Fields are merged with the existing vector settings. A missing or zero seed generates a stable value from the profile ID.

Show propertiesHide properties
canvasanyoptional
webglanyoptional
audioanyoptional
client_rectsanyoptional
sensorsanyoptional
fontsanyoptional
Responses
200Created temporary profile.application/json
idstring · uuidoptional
namestringoptional
fingerprint_idstringoptional

The library entry the profile was generated from.

temporarybooleanoptional
proxy_inlinebooleanoptional

Whether an inline proxy string was attached.

400Unparseable proxy string, or an unknown noise vector.application/json
errorstringrequired
401Missing or invalid Bearer token.
404No matching fingerprint / empty library.application/json
errorstringrequired
POST/profiles/temporary
POST /profiles/temporary HTTP/1.1
Host: 127.0.0.1:40325
Authorization: Bearer YOUR_SECRET_TOKEN
Content-Type: application/json
Accept: */*

{
  "fingerprint_id": "text",
  "platform": "Windows",
  "proxy": "text",
  "name": "text",
  "folder": "text",
  "refresh_rate": 60,
  "noise": {
    "canvas": true,
    "webgl": {
      "enabled": true,
      "intensity": 0.0005
    },
    "fonts": true
  }
}
curl -X POST 'http://127.0.0.1:40325/profiles/temporary' \
  -H 'Authorization: Bearer YOUR_SECRET_TOKEN' \
  -H 'Content-Type: application/json' \
  -d '{"fingerprint_id":"text","platform":"Windows","proxy":"text","name":"text","folder":"text","refresh_rate":60,"noise":{"canvas":true,"webgl":{"enabled":true,"intensity":0.0005},"fonts":true}}'
import requests

# Permanent JWT from Settings → Automation API.
token = "YOUR_SECRET_TOKEN"

url = "http://127.0.0.1:40325/profiles/temporary"
headers = {
    "Authorization": f"Bearer {token}",
}
payload = {
    "fingerprint_id": "text",
    "platform": "Windows",
    "proxy": "text",
    "name": "text",
    "folder": "text",
    "refresh_rate": 60,
    "noise": {
        "canvas": True,
        "webgl": {
            "enabled": True,
            "intensity": 0.0005,
        },
        "fonts": True,
    },
}

response = requests.post(url, headers=headers, json=payload, timeout=30)
response.raise_for_status()
print(response.status_code)
print(response.text)
// Permanent JWT from Settings → Automation API.
const token = "YOUR_SECRET_TOKEN";

const url = "http://127.0.0.1:40325/profiles/temporary";
const payload = {
  "fingerprint_id": "text",
  "platform": "Windows",
  "proxy": "text",
  "name": "text",
  "folder": "text",
  "refresh_rate": 60,
  "noise": {
    "canvas": true,
    "webgl": {
      "enabled": true,
      "intensity": 0.0005
    },
    "fonts": true
  }
};

const response = await fetch(url, {
  method: "POST",
  headers: {
    "Authorization": `Bearer ${token}`,
    "Content-Type": "application/json",
  },
  body: JSON.stringify(payload),
});

console.log(response.status);
console.log(await response.text());
package main

import (
	"bytes"
	"fmt"
	"io"
	"log"
	"net/http"
)

func main() {
	// Permanent JWT from Settings → Automation API.
	token := "YOUR_SECRET_TOKEN"

	url := "http://127.0.0.1:40325/profiles/temporary"
	body := bytes.NewBufferString(`{
  "fingerprint_id": "text",
  "platform": "Windows",
  "proxy": "text",
  "name": "text",
  "folder": "text",
  "refresh_rate": 60,
  "noise": {
    "canvas": true,
    "webgl": {
      "enabled": true,
      "intensity": 0.0005
    },
    "fonts": true
  }
}`)

	req, err := http.NewRequest("POST", url, body)
	if err != nil {
		log.Fatal(err)
	}
	req.Header.Set("Authorization", "Bearer "+token)
	req.Header.Set("Content-Type", "application/json")

	resp, err := http.DefaultClient.Do(req)
	if err != nil {
		log.Fatal(err)
	}
	defer resp.Body.Close()

	out, err := io.ReadAll(resp.Body)
	if err != nil {
		log.Fatal(err)
	}
	fmt.Println(resp.Status)
	fmt.Println(string(out))
}
// Cargo.toml: reqwest = { version = "0.12", features = ["json"] }, tokio = { version = "1", features = ["full"] }, serde_json = "1"

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
    // Permanent JWT from Settings → Automation API.
    let token = "YOUR_SECRET_TOKEN";

    let client = reqwest::Client::new();
    let response = client
        .post("http://127.0.0.1:40325/profiles/temporary")
        .header("Authorization", format!("Bearer {token}"))
        .json(&serde_json::json!({
          "fingerprint_id": "text",
          "platform": "Windows",
          "proxy": "text",
          "name": "text",
          "folder": "text",
          "refresh_rate": 60,
          "noise": {
            "canvas": true,
            "webgl": {
              "enabled": true,
              "intensity": 0.0005
            },
            "fonts": true
          }
        }))
        .send()
        .await?;

    println!("{}", response.status());
    println!("{}", response.text().await?);
    Ok(())
}
using System;
using System.Net.Http;
using System.Net.Http.Headers;
using System.Text;
using System.Threading.Tasks;

class Program
{
    static async Task Main()
    {
        // Permanent JWT from Settings → Automation API.
        var token = "YOUR_SECRET_TOKEN";

        using var client = new HttpClient();
        client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", token);

        var request = new HttpRequestMessage(HttpMethod.Post, "http://127.0.0.1:40325/profiles/temporary");
        request.Content = new StringContent("""
            {
              "fingerprint_id": "text",
              "platform": "Windows",
              "proxy": "text",
              "name": "text",
              "folder": "text",
              "refresh_rate": 60,
              "noise": {
                "canvas": true,
                "webgl": {
                  "enabled": true,
                  "intensity": 0.0005
                },
                "fonts": true
              }
            }
            """, Encoding.UTF8, "application/json");

        var response = await client.SendAsync(request);
        Console.WriteLine((int)response.StatusCode);
        Console.WriteLine(await response.Content.ReadAsStringAsync());
    }
}
// build: c++ -std=c++17 main.cpp -lcurl
#include <curl/curl.h>

#include <iostream>
#include <string>

static size_t write_cb(char *ptr, size_t size, size_t nmemb, void *userdata) {
    static_cast<std::string *>(userdata)->append(ptr, size * nmemb);
    return size * nmemb;
}

int main() {
    // Permanent JWT from Settings → Automation API.
    const std::string token = "YOUR_SECRET_TOKEN";

    curl_global_init(CURL_GLOBAL_DEFAULT);
    CURL *curl = curl_easy_init();
    if (!curl) {
        std::cerr << "curl_easy_init failed\n";
        curl_global_cleanup();
        return 1;
    }

    struct curl_slist *headers = nullptr;
    headers = curl_slist_append(headers, ("Authorization: Bearer " + token).c_str());
    headers = curl_slist_append(headers, "Content-Type: application/json");

    const std::string body = R"json({
  "fingerprint_id": "text",
  "platform": "Windows",
  "proxy": "text",
  "name": "text",
  "folder": "text",
  "refresh_rate": 60,
  "noise": {
    "canvas": true,
    "webgl": {
      "enabled": true,
      "intensity": 0.0005
    },
    "fonts": true
  }
})json";

    std::string response;
    curl_easy_setopt(curl, CURLOPT_URL, "http://127.0.0.1:40325/profiles/temporary");
    curl_easy_setopt(curl, CURLOPT_CUSTOMREQUEST, "POST");
    curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headers);
    curl_easy_setopt(curl, CURLOPT_POSTFIELDS, body.c_str());
    curl_easy_setopt(curl, CURLOPT_POSTFIELDSIZE, static_cast<long>(body.size()));
    curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, write_cb);
    curl_easy_setopt(curl, CURLOPT_WRITEDATA, &response);

    const CURLcode rc = curl_easy_perform(curl);
    if (rc != CURLE_OK) {
        std::cerr << curl_easy_strerror(rc) << "\n";
    } else {
        long status = 0;
        curl_easy_getinfo(curl, CURLINFO_RESPONSE_CODE, &status);
        std::cout << status << "\n" << response << "\n";
    }

    curl_slist_free_all(headers);
    curl_easy_cleanup(curl);
    curl_global_cleanup();
    return rc == CURLE_OK ? 0 : 1;
}
{
  "id": "123e4567-e89b-12d3-a456-426614174000",
  "name": "text",
  "fingerprint_id": "text",
  "temporary": true,
  "proxy_inline": true
}
{
  "error": "text"
}
{
  "error": "text"
}

Get a profile

GEThttp://127.0.0.1:40325/profiles/{id}

Returns the full stored profile: the _meta envelope plus the flattened FingerprintConfig. If the profile is running, running and cdp are added.

Authorizations
bearerAuth
Authorizationstringrequired

Permanent JWT from Settings → Automation API.

Path parameters
idstring · uuidrequired

Profile UUID.

Responses
200The stored profile.application/json

Full on-disk profile: the _meta envelope plus the flattened FingerprintConfig (all Fingerprint fields appear at the top level). running/cdp are present only while the profile runs.

_metaobjectoptional
Show propertiesHide properties
idstring · uuidoptional
proxy_idstring· nullableoptional
inline_proxyobject · ProxyEntry· nullableoptional

Full proxy (as embedded in _meta.inline_proxy).

Show propertiesHide properties
idstringoptional
namestringoptional
kindstring · enumoptional
Possible values:socks5httphttps
hoststringoptional
portintegeroptional
usernamestringoptional
passwordstringoptional
countrystringoptional
notesstringoptional
last_launched_atstring· nullableoptional
created_atstring· nullableoptional
pinnedbooleanoptional
folderstringoptional
temporarybooleanoptional
revintegeroptional

Bumped by every write. The desktop editor sends back the number it opened the profile at, so a save that would land on top of a change made through this API is refused rather than silently reverting it. API edits are never refused; they read the profile and write it back in one step.

runningbooleanoptional
cdpobject · CdpInfo· nullableoptional

Chrome DevTools Protocol endpoint of a running profile.

Show propertiesHide properties
portintegeroptional

Chrome-chosen remote-debugging port.

http_urlstringoptional

REST base (/json, /json/version).

web_socket_debugger_urlstringoptional

Browser-level WS endpoint for Puppeteer/Playwright connect.

401Missing or invalid Bearer token.
404No such profile.application/json
errorstringrequired
GET/profiles/123e4567-e89b-12d3-a456-426614174000
GET /profiles/123e4567-e89b-12d3-a456-426614174000 HTTP/1.1
Host: 127.0.0.1:40325
Authorization: Bearer YOUR_SECRET_TOKEN
Accept: */*
curl -X GET 'http://127.0.0.1:40325/profiles/123e4567-e89b-12d3-a456-426614174000' \
  -H 'Authorization: Bearer YOUR_SECRET_TOKEN'
import requests

# Permanent JWT from Settings → Automation API.
token = "YOUR_SECRET_TOKEN"

url = "http://127.0.0.1:40325/profiles/123e4567-e89b-12d3-a456-426614174000"
headers = {
    "Authorization": f"Bearer {token}",
}

response = requests.get(url, headers=headers, timeout=30)
response.raise_for_status()
print(response.status_code)
print(response.text)
// Permanent JWT from Settings → Automation API.
const token = "YOUR_SECRET_TOKEN";

const url = "http://127.0.0.1:40325/profiles/123e4567-e89b-12d3-a456-426614174000";

const response = await fetch(url, {
  method: "GET",
  headers: {
    "Authorization": `Bearer ${token}`,
  },
});

console.log(response.status);
console.log(await response.text());
package main

import (
	"fmt"
	"io"
	"log"
	"net/http"
)

func main() {
	// Permanent JWT from Settings → Automation API.
	token := "YOUR_SECRET_TOKEN"

	url := "http://127.0.0.1:40325/profiles/123e4567-e89b-12d3-a456-426614174000"

	req, err := http.NewRequest("GET", url, nil)
	if err != nil {
		log.Fatal(err)
	}
	req.Header.Set("Authorization", "Bearer "+token)

	resp, err := http.DefaultClient.Do(req)
	if err != nil {
		log.Fatal(err)
	}
	defer resp.Body.Close()

	out, err := io.ReadAll(resp.Body)
	if err != nil {
		log.Fatal(err)
	}
	fmt.Println(resp.Status)
	fmt.Println(string(out))
}
// Cargo.toml: reqwest = { version = "0.12", features = ["json"] }, tokio = { version = "1", features = ["full"] }

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
    // Permanent JWT from Settings → Automation API.
    let token = "YOUR_SECRET_TOKEN";

    let client = reqwest::Client::new();
    let response = client
        .get("http://127.0.0.1:40325/profiles/123e4567-e89b-12d3-a456-426614174000")
        .header("Authorization", format!("Bearer {token}"))
        .send()
        .await?;

    println!("{}", response.status());
    println!("{}", response.text().await?);
    Ok(())
}
using System;
using System.Net.Http;
using System.Net.Http.Headers;
using System.Threading.Tasks;

class Program
{
    static async Task Main()
    {
        // Permanent JWT from Settings → Automation API.
        var token = "YOUR_SECRET_TOKEN";

        using var client = new HttpClient();
        client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", token);

        var request = new HttpRequestMessage(HttpMethod.Get, "http://127.0.0.1:40325/profiles/123e4567-e89b-12d3-a456-426614174000");

        var response = await client.SendAsync(request);
        Console.WriteLine((int)response.StatusCode);
        Console.WriteLine(await response.Content.ReadAsStringAsync());
    }
}
// build: c++ -std=c++17 main.cpp -lcurl
#include <curl/curl.h>

#include <iostream>
#include <string>

static size_t write_cb(char *ptr, size_t size, size_t nmemb, void *userdata) {
    static_cast<std::string *>(userdata)->append(ptr, size * nmemb);
    return size * nmemb;
}

int main() {
    // Permanent JWT from Settings → Automation API.
    const std::string token = "YOUR_SECRET_TOKEN";

    curl_global_init(CURL_GLOBAL_DEFAULT);
    CURL *curl = curl_easy_init();
    if (!curl) {
        std::cerr << "curl_easy_init failed\n";
        curl_global_cleanup();
        return 1;
    }

    struct curl_slist *headers = nullptr;
    headers = curl_slist_append(headers, ("Authorization: Bearer " + token).c_str());

    std::string response;
    curl_easy_setopt(curl, CURLOPT_URL, "http://127.0.0.1:40325/profiles/123e4567-e89b-12d3-a456-426614174000");
    curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headers);
    curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, write_cb);
    curl_easy_setopt(curl, CURLOPT_WRITEDATA, &response);

    const CURLcode rc = curl_easy_perform(curl);
    if (rc != CURLE_OK) {
        std::cerr << curl_easy_strerror(rc) << "\n";
    } else {
        long status = 0;
        curl_easy_getinfo(curl, CURLINFO_RESPONSE_CODE, &status);
        std::cout << status << "\n" << response << "\n";
    }

    curl_slist_free_all(headers);
    curl_easy_cleanup(curl);
    curl_global_cleanup();
    return rc == CURLE_OK ? 0 : 1;
}
{
  "_meta": {
    "id": "123e4567-e89b-12d3-a456-426614174000",
    "proxy_id": "text",
    "inline_proxy": {
      "id": "text",
      "name": "text",
      "kind": "socks5",
      "host": "text",
      "port": 1,
      "username": "text",
      "password": "text",
      "country": "text",
      "notes": "text"
    },
    "last_launched_at": "text",
    "created_at": "text",
    "pinned": true,
    "folder": "text",
    "temporary": true,
    "rev": 1
  },
  "running": true,
  "cdp": {
    "port": 1,
    "http_url": "http://127.0.0.1:53217",
    "web_socket_debugger_url": "ws://127.0.0.1:53217/devtools/browser/ab12-..."
  }
}
{
  "error": "text"
}

Delete a profile

DELhttp://127.0.0.1:40325/profiles/{id}

Moves the profile to Trash. It can be restored for 7 days. The archive includes cookies, logins, web data, preferences, Local Storage, and IndexedDB. Cache data is excluded. The original configuration and user data directory are deleted after the archive is created.

Temporary profiles are deleted automatically when their browser closes and are not moved to Trash.

Authorizations
bearerAuth
Authorizationstringrequired

Permanent JWT from Settings → Automation API.

Path parameters
idstring · uuidrequired

Profile UUID.

Responses
200Profile moved to Trash.application/json
deletedbooleanoptional
idstring · uuidoptional
trashedbooleanoptional

Can be restored from Trash for 7 days.

401Missing or invalid Bearer token.
500Deletion failed.application/json
errorstringrequired
DEL/profiles/123e4567-e89b-12d3-a456-426614174000
DELETE /profiles/123e4567-e89b-12d3-a456-426614174000 HTTP/1.1
Host: 127.0.0.1:40325
Authorization: Bearer YOUR_SECRET_TOKEN
Accept: */*
curl -X DELETE 'http://127.0.0.1:40325/profiles/123e4567-e89b-12d3-a456-426614174000' \
  -H 'Authorization: Bearer YOUR_SECRET_TOKEN'
import requests

# Permanent JWT from Settings → Automation API.
token = "YOUR_SECRET_TOKEN"

url = "http://127.0.0.1:40325/profiles/123e4567-e89b-12d3-a456-426614174000"
headers = {
    "Authorization": f"Bearer {token}",
}

response = requests.delete(url, headers=headers, timeout=30)
response.raise_for_status()
print(response.status_code)
print(response.text)
// Permanent JWT from Settings → Automation API.
const token = "YOUR_SECRET_TOKEN";

const url = "http://127.0.0.1:40325/profiles/123e4567-e89b-12d3-a456-426614174000";

const response = await fetch(url, {
  method: "DELETE",
  headers: {
    "Authorization": `Bearer ${token}`,
  },
});

console.log(response.status);
console.log(await response.text());
package main

import (
	"fmt"
	"io"
	"log"
	"net/http"
)

func main() {
	// Permanent JWT from Settings → Automation API.
	token := "YOUR_SECRET_TOKEN"

	url := "http://127.0.0.1:40325/profiles/123e4567-e89b-12d3-a456-426614174000"

	req, err := http.NewRequest("DELETE", url, nil)
	if err != nil {
		log.Fatal(err)
	}
	req.Header.Set("Authorization", "Bearer "+token)

	resp, err := http.DefaultClient.Do(req)
	if err != nil {
		log.Fatal(err)
	}
	defer resp.Body.Close()

	out, err := io.ReadAll(resp.Body)
	if err != nil {
		log.Fatal(err)
	}
	fmt.Println(resp.Status)
	fmt.Println(string(out))
}
// Cargo.toml: reqwest = { version = "0.12", features = ["json"] }, tokio = { version = "1", features = ["full"] }

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
    // Permanent JWT from Settings → Automation API.
    let token = "YOUR_SECRET_TOKEN";

    let client = reqwest::Client::new();
    let response = client
        .delete("http://127.0.0.1:40325/profiles/123e4567-e89b-12d3-a456-426614174000")
        .header("Authorization", format!("Bearer {token}"))
        .send()
        .await?;

    println!("{}", response.status());
    println!("{}", response.text().await?);
    Ok(())
}
using System;
using System.Net.Http;
using System.Net.Http.Headers;
using System.Threading.Tasks;

class Program
{
    static async Task Main()
    {
        // Permanent JWT from Settings → Automation API.
        var token = "YOUR_SECRET_TOKEN";

        using var client = new HttpClient();
        client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", token);

        var request = new HttpRequestMessage(HttpMethod.Delete, "http://127.0.0.1:40325/profiles/123e4567-e89b-12d3-a456-426614174000");

        var response = await client.SendAsync(request);
        Console.WriteLine((int)response.StatusCode);
        Console.WriteLine(await response.Content.ReadAsStringAsync());
    }
}
// build: c++ -std=c++17 main.cpp -lcurl
#include <curl/curl.h>

#include <iostream>
#include <string>

static size_t write_cb(char *ptr, size_t size, size_t nmemb, void *userdata) {
    static_cast<std::string *>(userdata)->append(ptr, size * nmemb);
    return size * nmemb;
}

int main() {
    // Permanent JWT from Settings → Automation API.
    const std::string token = "YOUR_SECRET_TOKEN";

    curl_global_init(CURL_GLOBAL_DEFAULT);
    CURL *curl = curl_easy_init();
    if (!curl) {
        std::cerr << "curl_easy_init failed\n";
        curl_global_cleanup();
        return 1;
    }

    struct curl_slist *headers = nullptr;
    headers = curl_slist_append(headers, ("Authorization: Bearer " + token).c_str());

    std::string response;
    curl_easy_setopt(curl, CURLOPT_URL, "http://127.0.0.1:40325/profiles/123e4567-e89b-12d3-a456-426614174000");
    curl_easy_setopt(curl, CURLOPT_CUSTOMREQUEST, "DELETE");
    curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headers);
    curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, write_cb);
    curl_easy_setopt(curl, CURLOPT_WRITEDATA, &response);

    const CURLcode rc = curl_easy_perform(curl);
    if (rc != CURLE_OK) {
        std::cerr << curl_easy_strerror(rc) << "\n";
    } else {
        long status = 0;
        curl_easy_getinfo(curl, CURLINFO_RESPONSE_CODE, &status);
        std::cout << status << "\n" << response << "\n";
    }

    curl_slist_free_all(headers);
    curl_easy_cleanup(curl);
    curl_global_cleanup();
    return rc == CURLE_OK ? 0 : 1;
}
{
  "deleted": true,
  "id": "123e4567-e89b-12d3-a456-426614174000",
  "trashed": true
}
{
  "error": "text"
}

Edit a profile

PATCHhttp://127.0.0.1:40325/profiles/{id}

Updates only the provided fields. When fingerprint is given it REPLACES the stored fingerprint verbatim (no re-randomization). folder: "" unfiles the profile; proxy_id: "" unbinds the proxy; a proxy string is stored (deduped) + full-tested, then bound. Returns the updated stored profile.

Authorizations
bearerAuth
Authorizationstringrequired

Permanent JWT from Settings → Automation API.

Path parameters
idstring · uuidrequired

Profile UUID.

Body
application/json
namestringoptional
notesstringoptional
folderstringoptional

"" unfiles (moves to All).

proxy_idstringoptional

"" unbinds the proxy.

proxystringoptional

Proxy string; stored (deduped) + full-tested, then bound.

colorstringoptional

#rrggbb; "" goes back to the name-derived colour.

extensionsstring[]optional

Replaces the whole list; [] loads none.

refresh_rateinteger· min: 24· max: 480optional

Claimed display refresh rate, applied AFTER fingerprint and written into screen.refresh_rate. No web API reports it; a page measures it by timing requestAnimationFrame, which is why leaving it out is not neutral; absent means 60, what most machines report, rather than whatever the host's own screen does. Frames can only be slowed, so the effective rate is the closest whole division of the host's panel at or under this.

fingerprintobject · Fingerprintoptional

When present, REPLACES the stored fingerprint verbatim.

Show propertiesHide properties
namestringoptional
notesstringoptional
seedintegeroptional

0 = overrides-only mode (the common case).

navigatorobjectoptional
Show propertiesHide properties
user_agentstringoptional
platformstringoptional
hardware_concurrencyintegeroptional
device_memoryinteger · enumoptional
Possible values:81632
languagestringoptional
do_not_trackbooleanoptional
screenobjectoptional
Show propertiesHide properties
widthintegeroptional
heightintegeroptional
avail_widthintegeroptional
avail_heightintegeroptional
color_depthintegeroptional
device_pixel_rationumberoptional
color_gamutstring · enumoptional
Possible values:srgbp3rec2020
refresh_rateinteger· min: 24· max: 480optional

How often the claimed display refreshes. Absent means 60. See the refresh_rate field on the create/edit requests.

client_hintsobjectoptional

Sec-CH-UA family (browser.vision calls this hints).

Show propertiesHide properties
platformstringoptional
platform_versionstringoptional
architecturestringoptional
bitnessstringoptional
mobilebooleanoptional
webglobjectoptional
Show propertiesHide properties
unmasked_vendorstringoptional
unmasked_rendererstringoptional
webgpuobjectoptional
webrtcstring · enumoptional

WebRTC handling mode.

Possible values:autotcp_onlyblock
noiseobject · NoisePrefsoptional

Per-vector anti-fingerprint noise. Each block is {enabled, seed} (+ feature-specific knobs). enabled:false = pass-through.

Show propertiesHide properties
canvasobject · NoiseBlockoptional
Show propertiesHide properties
enabledbooleanoptional
seedintegeroptional

Per-profile entropy; 0 = derive automatically.

webglobject · NoiseBlockoptional
Show propertiesHide properties
enabledbooleanoptional
seedintegeroptional

Per-profile entropy; 0 = derive automatically.

intensitynumberoptional
audioobject · NoiseBlockoptional
Show propertiesHide properties
enabledbooleanoptional
seedintegeroptional

Per-profile entropy; 0 = derive automatically.

intensitynumberoptional
client_rectsobject · NoiseBlockoptional
Show propertiesHide properties
enabledbooleanoptional
seedintegeroptional

Per-profile entropy; 0 = derive automatically.

max_offsetnumberoptional
sensorsobject · NoiseBlockoptional
Show propertiesHide properties
enabledbooleanoptional
seedintegeroptional

Per-profile entropy; 0 = derive automatically.

fontsobject · NoiseBlockoptional

enabled:true hides a small deterministic per-profile subset of non-essential fonts (real host fonts otherwise pass through).

Show propertiesHide properties
enabledbooleanoptional
seedintegeroptional

Per-profile entropy; 0 = derive automatically.

networkobjectoptional
Show propertiesHide properties
blocked_portsinteger[]optional

Local-network port-scan defense (ports_protection).

timezonestringoptional

IANA name, or "auto" to resolve from the bound proxy at launch.

Responses
200Updated stored profile.application/json

Full on-disk profile: the _meta envelope plus the flattened FingerprintConfig (all Fingerprint fields appear at the top level). running/cdp are present only while the profile runs.

_metaobjectoptional
Show propertiesHide properties
idstring · uuidoptional
proxy_idstring· nullableoptional
inline_proxyobject · ProxyEntry· nullableoptional

Full proxy (as embedded in _meta.inline_proxy).

Show propertiesHide properties
idstringoptional
namestringoptional
kindstring · enumoptional
Possible values:socks5httphttps
hoststringoptional
portintegeroptional
usernamestringoptional
passwordstringoptional
countrystringoptional
notesstringoptional
last_launched_atstring· nullableoptional
created_atstring· nullableoptional
pinnedbooleanoptional
folderstringoptional
temporarybooleanoptional
revintegeroptional

Bumped by every write. The desktop editor sends back the number it opened the profile at, so a save that would land on top of a change made through this API is refused rather than silently reverting it. API edits are never refused; they read the profile and write it back in one step.

runningbooleanoptional
cdpobject · CdpInfo· nullableoptional

Chrome DevTools Protocol endpoint of a running profile.

Show propertiesHide properties
portintegeroptional

Chrome-chosen remote-debugging port.

http_urlstringoptional

REST base (/json, /json/version).

web_socket_debugger_urlstringoptional

Browser-level WS endpoint for Puppeteer/Playwright connect.

400Bad fingerprint (not an object) or unparseable proxy.application/json
errorstringrequired
401Missing or invalid Bearer token.
404No such profile.application/json
errorstringrequired
PATCH/profiles/123e4567-e89b-12d3-a456-426614174000
PATCH /profiles/123e4567-e89b-12d3-a456-426614174000 HTTP/1.1
Host: 127.0.0.1:40325
Authorization: Bearer YOUR_SECRET_TOKEN
Content-Type: application/json
Accept: */*

{
  "name": "text",
  "notes": "text",
  "folder": "text",
  "proxy_id": "text",
  "proxy": "text",
  "color": "text",
  "extensions": [
    "text"
  ],
  "refresh_rate": 60,
  "fingerprint": {
    "name": "text",
    "notes": "text",
    "seed": 1,
    "navigator": {
      "user_agent": "text",
      "platform": "Win32",
      "hardware_concurrency": 12,
      "device_memory": 16,
      "language": "text",
      "do_not_track": true
    },
    "screen": {
      "width": 1,
      "height": 1,
      "avail_width": 1,
      "avail_height": 1,
      "color_depth": 24,
      "device_pixel_ratio": 2,
      "color_gamut": "",
      "refresh_rate": 60
    },
    "client_hints": {
      "platform": "text",
      "platform_version": "text",
      "architecture": "x86",
      "bitness": "64",
      "mobile": true
    },
    "webgl": {
      "unmasked_vendor": "text",
      "unmasked_renderer": "text"
    },
    "webgpu": {},
    "webrtc": "auto",
    "noise": {
      "canvas": {
        "enabled": true,
        "seed": 1
      },
      "webgl": {
        "enabled": true,
        "seed": 1,
        "intensity": 1
      },
      "audio": {
        "enabled": true,
        "seed": 1,
        "intensity": 1
      },
      "client_rects": {
        "enabled": true,
        "seed": 1,
        "max_offset": 1
      },
      "sensors": {
        "enabled": true,
        "seed": 1
      },
      "fonts": {
        "enabled": true,
        "seed": 1
      }
    },
    "network": {
      "blocked_ports": [
        1
      ]
    },
    "timezone": "text"
  }
}
curl -X PATCH 'http://127.0.0.1:40325/profiles/123e4567-e89b-12d3-a456-426614174000' \
  -H 'Authorization: Bearer YOUR_SECRET_TOKEN' \
  -H 'Content-Type: application/json' \
  -d '{"name":"text","notes":"text","folder":"text","proxy_id":"text","proxy":"text","color":"text","extensions":["text"],"refresh_rate":60,"fingerprint":{"name":"text","notes":"text","seed":1,"navigator":{"user_agent":"text","platform":"Win32","hardware_concurrency":12,"device_memory":16,"language":"text","do_not_track":true},"screen":{"width":1,"height":1,"avail_width":1,"avail_height":1,"color_depth":24,"device_pixel_ratio":2,"color_gamut":"","refresh_rate":60},"client_hints":{"platform":"text","platform_version":"text","architecture":"x86","bitness":"64","mobile":true},"webgl":{"unmasked_vendor":"text","unmasked_renderer":"text"},"webgpu":{},"webrtc":"auto","noise":{"canvas":{"enabled":true,"seed":1},"webgl":{"enabled":true,"seed":1,"intensity":1},"audio":{"enabled":true,"seed":1,"intensity":1},"client_rects":{"enabled":true,"seed":1,"max_offset":1},"sensors":{"enabled":true,"seed":1},"fonts":{"enabled":true,"seed":1}},"network":{"blocked_ports":[1]},"timezone":"text"}}'
import requests

# Permanent JWT from Settings → Automation API.
token = "YOUR_SECRET_TOKEN"

url = "http://127.0.0.1:40325/profiles/123e4567-e89b-12d3-a456-426614174000"
headers = {
    "Authorization": f"Bearer {token}",
}
payload = {
    "name": "text",
    "notes": "text",
    "folder": "text",
    "proxy_id": "text",
    "proxy": "text",
    "color": "text",
    "extensions": [
        "text",
    ],
    "refresh_rate": 60,
    "fingerprint": {
        "name": "text",
        "notes": "text",
        "seed": 1,
        "navigator": {
            "user_agent": "text",
            "platform": "Win32",
            "hardware_concurrency": 12,
            "device_memory": 16,
            "language": "text",
            "do_not_track": True,
        },
        "screen": {
            "width": 1,
            "height": 1,
            "avail_width": 1,
            "avail_height": 1,
            "color_depth": 24,
            "device_pixel_ratio": 2,
            "color_gamut": "",
            "refresh_rate": 60,
        },
        "client_hints": {
            "platform": "text",
            "platform_version": "text",
            "architecture": "x86",
            "bitness": "64",
            "mobile": True,
        },
        "webgl": {
            "unmasked_vendor": "text",
            "unmasked_renderer": "text",
        },
        "webgpu": {},
        "webrtc": "auto",
        "noise": {
            "canvas": {
                "enabled": True,
                "seed": 1,
            },
            "webgl": {
                "enabled": True,
                "seed": 1,
                "intensity": 1,
            },
            "audio": {
                "enabled": True,
                "seed": 1,
                "intensity": 1,
            },
            "client_rects": {
                "enabled": True,
                "seed": 1,
                "max_offset": 1,
            },
            "sensors": {
                "enabled": True,
                "seed": 1,
            },
            "fonts": {
                "enabled": True,
                "seed": 1,
            },
        },
        "network": {
            "blocked_ports": [
                1,
            ],
        },
        "timezone": "text",
    },
}

response = requests.patch(url, headers=headers, json=payload, timeout=30)
response.raise_for_status()
print(response.status_code)
print(response.text)
// Permanent JWT from Settings → Automation API.
const token = "YOUR_SECRET_TOKEN";

const url = "http://127.0.0.1:40325/profiles/123e4567-e89b-12d3-a456-426614174000";
const payload = {
  "name": "text",
  "notes": "text",
  "folder": "text",
  "proxy_id": "text",
  "proxy": "text",
  "color": "text",
  "extensions": [
    "text"
  ],
  "refresh_rate": 60,
  "fingerprint": {
    "name": "text",
    "notes": "text",
    "seed": 1,
    "navigator": {
      "user_agent": "text",
      "platform": "Win32",
      "hardware_concurrency": 12,
      "device_memory": 16,
      "language": "text",
      "do_not_track": true
    },
    "screen": {
      "width": 1,
      "height": 1,
      "avail_width": 1,
      "avail_height": 1,
      "color_depth": 24,
      "device_pixel_ratio": 2,
      "color_gamut": "",
      "refresh_rate": 60
    },
    "client_hints": {
      "platform": "text",
      "platform_version": "text",
      "architecture": "x86",
      "bitness": "64",
      "mobile": true
    },
    "webgl": {
      "unmasked_vendor": "text",
      "unmasked_renderer": "text"
    },
    "webgpu": {},
    "webrtc": "auto",
    "noise": {
      "canvas": {
        "enabled": true,
        "seed": 1
      },
      "webgl": {
        "enabled": true,
        "seed": 1,
        "intensity": 1
      },
      "audio": {
        "enabled": true,
        "seed": 1,
        "intensity": 1
      },
      "client_rects": {
        "enabled": true,
        "seed": 1,
        "max_offset": 1
      },
      "sensors": {
        "enabled": true,
        "seed": 1
      },
      "fonts": {
        "enabled": true,
        "seed": 1
      }
    },
    "network": {
      "blocked_ports": [
        1
      ]
    },
    "timezone": "text"
  }
};

const response = await fetch(url, {
  method: "PATCH",
  headers: {
    "Authorization": `Bearer ${token}`,
    "Content-Type": "application/json",
  },
  body: JSON.stringify(payload),
});

console.log(response.status);
console.log(await response.text());
package main

import (
	"bytes"
	"fmt"
	"io"
	"log"
	"net/http"
)

func main() {
	// Permanent JWT from Settings → Automation API.
	token := "YOUR_SECRET_TOKEN"

	url := "http://127.0.0.1:40325/profiles/123e4567-e89b-12d3-a456-426614174000"
	body := bytes.NewBufferString(`{
  "name": "text",
  "notes": "text",
  "folder": "text",
  "proxy_id": "text",
  "proxy": "text",
  "color": "text",
  "extensions": [
    "text"
  ],
  "refresh_rate": 60,
  "fingerprint": {
    "name": "text",
    "notes": "text",
    "seed": 1,
    "navigator": {
      "user_agent": "text",
      "platform": "Win32",
      "hardware_concurrency": 12,
      "device_memory": 16,
      "language": "text",
      "do_not_track": true
    },
    "screen": {
      "width": 1,
      "height": 1,
      "avail_width": 1,
      "avail_height": 1,
      "color_depth": 24,
      "device_pixel_ratio": 2,
      "color_gamut": "",
      "refresh_rate": 60
    },
    "client_hints": {
      "platform": "text",
      "platform_version": "text",
      "architecture": "x86",
      "bitness": "64",
      "mobile": true
    },
    "webgl": {
      "unmasked_vendor": "text",
      "unmasked_renderer": "text"
    },
    "webgpu": {},
    "webrtc": "auto",
    "noise": {
      "canvas": {
        "enabled": true,
        "seed": 1
      },
      "webgl": {
        "enabled": true,
        "seed": 1,
        "intensity": 1
      },
      "audio": {
        "enabled": true,
        "seed": 1,
        "intensity": 1
      },
      "client_rects": {
        "enabled": true,
        "seed": 1,
        "max_offset": 1
      },
      "sensors": {
        "enabled": true,
        "seed": 1
      },
      "fonts": {
        "enabled": true,
        "seed": 1
      }
    },
    "network": {
      "blocked_ports": [
        1
      ]
    },
    "timezone": "text"
  }
}`)

	req, err := http.NewRequest("PATCH", url, body)
	if err != nil {
		log.Fatal(err)
	}
	req.Header.Set("Authorization", "Bearer "+token)
	req.Header.Set("Content-Type", "application/json")

	resp, err := http.DefaultClient.Do(req)
	if err != nil {
		log.Fatal(err)
	}
	defer resp.Body.Close()

	out, err := io.ReadAll(resp.Body)
	if err != nil {
		log.Fatal(err)
	}
	fmt.Println(resp.Status)
	fmt.Println(string(out))
}
// Cargo.toml: reqwest = { version = "0.12", features = ["json"] }, tokio = { version = "1", features = ["full"] }, serde_json = "1"

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
    // Permanent JWT from Settings → Automation API.
    let token = "YOUR_SECRET_TOKEN";

    let client = reqwest::Client::new();
    let response = client
        .patch("http://127.0.0.1:40325/profiles/123e4567-e89b-12d3-a456-426614174000")
        .header("Authorization", format!("Bearer {token}"))
        .json(&serde_json::json!({
          "name": "text",
          "notes": "text",
          "folder": "text",
          "proxy_id": "text",
          "proxy": "text",
          "color": "text",
          "extensions": [
            "text"
          ],
          "refresh_rate": 60,
          "fingerprint": {
            "name": "text",
            "notes": "text",
            "seed": 1,
            "navigator": {
              "user_agent": "text",
              "platform": "Win32",
              "hardware_concurrency": 12,
              "device_memory": 16,
              "language": "text",
              "do_not_track": true
            },
            "screen": {
              "width": 1,
              "height": 1,
              "avail_width": 1,
              "avail_height": 1,
              "color_depth": 24,
              "device_pixel_ratio": 2,
              "color_gamut": "",
              "refresh_rate": 60
            },
            "client_hints": {
              "platform": "text",
              "platform_version": "text",
              "architecture": "x86",
              "bitness": "64",
              "mobile": true
            },
            "webgl": {
              "unmasked_vendor": "text",
              "unmasked_renderer": "text"
            },
            "webgpu": {},
            "webrtc": "auto",
            "noise": {
              "canvas": {
                "enabled": true,
                "seed": 1
              },
              "webgl": {
                "enabled": true,
                "seed": 1,
                "intensity": 1
              },
              "audio": {
                "enabled": true,
                "seed": 1,
                "intensity": 1
              },
              "client_rects": {
                "enabled": true,
                "seed": 1,
                "max_offset": 1
              },
              "sensors": {
                "enabled": true,
                "seed": 1
              },
              "fonts": {
                "enabled": true,
                "seed": 1
              }
            },
            "network": {
              "blocked_ports": [
                1
              ]
            },
            "timezone": "text"
          }
        }))
        .send()
        .await?;

    println!("{}", response.status());
    println!("{}", response.text().await?);
    Ok(())
}
using System;
using System.Net.Http;
using System.Net.Http.Headers;
using System.Text;
using System.Threading.Tasks;

class Program
{
    static async Task Main()
    {
        // Permanent JWT from Settings → Automation API.
        var token = "YOUR_SECRET_TOKEN";

        using var client = new HttpClient();
        client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", token);

        var request = new HttpRequestMessage(HttpMethod.Patch, "http://127.0.0.1:40325/profiles/123e4567-e89b-12d3-a456-426614174000");
        request.Content = new StringContent("""
            {
              "name": "text",
              "notes": "text",
              "folder": "text",
              "proxy_id": "text",
              "proxy": "text",
              "color": "text",
              "extensions": [
                "text"
              ],
              "refresh_rate": 60,
              "fingerprint": {
                "name": "text",
                "notes": "text",
                "seed": 1,
                "navigator": {
                  "user_agent": "text",
                  "platform": "Win32",
                  "hardware_concurrency": 12,
                  "device_memory": 16,
                  "language": "text",
                  "do_not_track": true
                },
                "screen": {
                  "width": 1,
                  "height": 1,
                  "avail_width": 1,
                  "avail_height": 1,
                  "color_depth": 24,
                  "device_pixel_ratio": 2,
                  "color_gamut": "",
                  "refresh_rate": 60
                },
                "client_hints": {
                  "platform": "text",
                  "platform_version": "text",
                  "architecture": "x86",
                  "bitness": "64",
                  "mobile": true
                },
                "webgl": {
                  "unmasked_vendor": "text",
                  "unmasked_renderer": "text"
                },
                "webgpu": {},
                "webrtc": "auto",
                "noise": {
                  "canvas": {
                    "enabled": true,
                    "seed": 1
                  },
                  "webgl": {
                    "enabled": true,
                    "seed": 1,
                    "intensity": 1
                  },
                  "audio": {
                    "enabled": true,
                    "seed": 1,
                    "intensity": 1
                  },
                  "client_rects": {
                    "enabled": true,
                    "seed": 1,
                    "max_offset": 1
                  },
                  "sensors": {
                    "enabled": true,
                    "seed": 1
                  },
                  "fonts": {
                    "enabled": true,
                    "seed": 1
                  }
                },
                "network": {
                  "blocked_ports": [
                    1
                  ]
                },
                "timezone": "text"
              }
            }
            """, Encoding.UTF8, "application/json");

        var response = await client.SendAsync(request);
        Console.WriteLine((int)response.StatusCode);
        Console.WriteLine(await response.Content.ReadAsStringAsync());
    }
}
// build: c++ -std=c++17 main.cpp -lcurl
#include <curl/curl.h>

#include <iostream>
#include <string>

static size_t write_cb(char *ptr, size_t size, size_t nmemb, void *userdata) {
    static_cast<std::string *>(userdata)->append(ptr, size * nmemb);
    return size * nmemb;
}

int main() {
    // Permanent JWT from Settings → Automation API.
    const std::string token = "YOUR_SECRET_TOKEN";

    curl_global_init(CURL_GLOBAL_DEFAULT);
    CURL *curl = curl_easy_init();
    if (!curl) {
        std::cerr << "curl_easy_init failed\n";
        curl_global_cleanup();
        return 1;
    }

    struct curl_slist *headers = nullptr;
    headers = curl_slist_append(headers, ("Authorization: Bearer " + token).c_str());
    headers = curl_slist_append(headers, "Content-Type: application/json");

    const std::string body = R"json({
  "name": "text",
  "notes": "text",
  "folder": "text",
  "proxy_id": "text",
  "proxy": "text",
  "color": "text",
  "extensions": [
    "text"
  ],
  "refresh_rate": 60,
  "fingerprint": {
    "name": "text",
    "notes": "text",
    "seed": 1,
    "navigator": {
      "user_agent": "text",
      "platform": "Win32",
      "hardware_concurrency": 12,
      "device_memory": 16,
      "language": "text",
      "do_not_track": true
    },
    "screen": {
      "width": 1,
      "height": 1,
      "avail_width": 1,
      "avail_height": 1,
      "color_depth": 24,
      "device_pixel_ratio": 2,
      "color_gamut": "",
      "refresh_rate": 60
    },
    "client_hints": {
      "platform": "text",
      "platform_version": "text",
      "architecture": "x86",
      "bitness": "64",
      "mobile": true
    },
    "webgl": {
      "unmasked_vendor": "text",
      "unmasked_renderer": "text"
    },
    "webgpu": {},
    "webrtc": "auto",
    "noise": {
      "canvas": {
        "enabled": true,
        "seed": 1
      },
      "webgl": {
        "enabled": true,
        "seed": 1,
        "intensity": 1
      },
      "audio": {
        "enabled": true,
        "seed": 1,
        "intensity": 1
      },
      "client_rects": {
        "enabled": true,
        "seed": 1,
        "max_offset": 1
      },
      "sensors": {
        "enabled": true,
        "seed": 1
      },
      "fonts": {
        "enabled": true,
        "seed": 1
      }
    },
    "network": {
      "blocked_ports": [
        1
      ]
    },
    "timezone": "text"
  }
})json";

    std::string response;
    curl_easy_setopt(curl, CURLOPT_URL, "http://127.0.0.1:40325/profiles/123e4567-e89b-12d3-a456-426614174000");
    curl_easy_setopt(curl, CURLOPT_CUSTOMREQUEST, "PATCH");
    curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headers);
    curl_easy_setopt(curl, CURLOPT_POSTFIELDS, body.c_str());
    curl_easy_setopt(curl, CURLOPT_POSTFIELDSIZE, static_cast<long>(body.size()));
    curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, write_cb);
    curl_easy_setopt(curl, CURLOPT_WRITEDATA, &response);

    const CURLcode rc = curl_easy_perform(curl);
    if (rc != CURLE_OK) {
        std::cerr << curl_easy_strerror(rc) << "\n";
    } else {
        long status = 0;
        curl_easy_getinfo(curl, CURLINFO_RESPONSE_CODE, &status);
        std::cout << status << "\n" << response << "\n";
    }

    curl_slist_free_all(headers);
    curl_easy_cleanup(curl);
    curl_global_cleanup();
    return rc == CURLE_OK ? 0 : 1;
}
{
  "_meta": {
    "id": "123e4567-e89b-12d3-a456-426614174000",
    "proxy_id": "text",
    "inline_proxy": {
      "id": "text",
      "name": "text",
      "kind": "socks5",
      "host": "text",
      "port": 1,
      "username": "text",
      "password": "text",
      "country": "text",
      "notes": "text"
    },
    "last_launched_at": "text",
    "created_at": "text",
    "pinned": true,
    "folder": "text",
    "temporary": true,
    "rev": 1
  },
  "running": true,
  "cdp": {
    "port": 1,
    "http_url": "http://127.0.0.1:53217",
    "web_socket_debugger_url": "ws://127.0.0.1:53217/devtools/browser/ab12-..."
  }
}
{
  "error": "text"
}
{
  "error": "text"
}

Launch a profile (with CDP)

POSThttp://127.0.0.1:40325/profiles/{id}/start

Spawns the ShardX browser for the profile with remote-debugging enabled, resolves any auto timezone/locale/geo from the bound proxy, and returns the CDP endpoint once Chrome has written its DevToolsActivePort. CDP is enabled only on API launches (UI launches stay debugging-free for anti-detect). The call waits up to 30 seconds for the endpoint; if it still has none, cdp is null and cdp_error says what happened and where to read the port yourself. Works for both regular and temporary profiles.

Authorizations
bearerAuth
Authorizationstringrequired

Permanent JWT from Settings → Automation API.

Path parameters
idstring · uuidrequired

Profile UUID.

Body
application/json

Optional. Empty body launches headed.

headlessboolean· default: falseoptional

Launch headless (--headless=new).

Responses
200Launched.application/json
profile_idstringoptional
pidinteger · int64optional

OS process id.

headlessbooleanoptional
cdpobject · CdpInfo· nullableoptional

Chrome DevTools Protocol endpoint of a running profile.

Show propertiesHide properties
portintegeroptional

Chrome-chosen remote-debugging port.

http_urlstringoptional

REST base (/json, /json/version).

web_socket_debugger_urlstringoptional

Browser-level WS endpoint for Puppeteer/Playwright connect.

cdp_errorstring· nullableoptional

Why cdp is null, when it is. Absent otherwise.

401Missing or invalid Bearer token.
500Binary not configured / spawn failed.application/json
errorstringrequired
POST/profiles/123e4567-e89b-12d3-a456-426614174000/start
POST /profiles/123e4567-e89b-12d3-a456-426614174000/start HTTP/1.1
Host: 127.0.0.1:40325
Authorization: Bearer YOUR_SECRET_TOKEN
Content-Type: application/json
Accept: */*

{
  "headless": false
}
curl -X POST 'http://127.0.0.1:40325/profiles/123e4567-e89b-12d3-a456-426614174000/start' \
  -H 'Authorization: Bearer YOUR_SECRET_TOKEN' \
  -H 'Content-Type: application/json' \
  -d '{"headless":false}'
import requests

# Permanent JWT from Settings → Automation API.
token = "YOUR_SECRET_TOKEN"

url = "http://127.0.0.1:40325/profiles/123e4567-e89b-12d3-a456-426614174000/start"
headers = {
    "Authorization": f"Bearer {token}",
}
payload = {
    "headless": False,
}

response = requests.post(url, headers=headers, json=payload, timeout=30)
response.raise_for_status()
print(response.status_code)
print(response.text)
// Permanent JWT from Settings → Automation API.
const token = "YOUR_SECRET_TOKEN";

const url = "http://127.0.0.1:40325/profiles/123e4567-e89b-12d3-a456-426614174000/start";
const payload = {
  "headless": false
};

const response = await fetch(url, {
  method: "POST",
  headers: {
    "Authorization": `Bearer ${token}`,
    "Content-Type": "application/json",
  },
  body: JSON.stringify(payload),
});

console.log(response.status);
console.log(await response.text());
package main

import (
	"bytes"
	"fmt"
	"io"
	"log"
	"net/http"
)

func main() {
	// Permanent JWT from Settings → Automation API.
	token := "YOUR_SECRET_TOKEN"

	url := "http://127.0.0.1:40325/profiles/123e4567-e89b-12d3-a456-426614174000/start"
	body := bytes.NewBufferString(`{
  "headless": false
}`)

	req, err := http.NewRequest("POST", url, body)
	if err != nil {
		log.Fatal(err)
	}
	req.Header.Set("Authorization", "Bearer "+token)
	req.Header.Set("Content-Type", "application/json")

	resp, err := http.DefaultClient.Do(req)
	if err != nil {
		log.Fatal(err)
	}
	defer resp.Body.Close()

	out, err := io.ReadAll(resp.Body)
	if err != nil {
		log.Fatal(err)
	}
	fmt.Println(resp.Status)
	fmt.Println(string(out))
}
// Cargo.toml: reqwest = { version = "0.12", features = ["json"] }, tokio = { version = "1", features = ["full"] }, serde_json = "1"

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
    // Permanent JWT from Settings → Automation API.
    let token = "YOUR_SECRET_TOKEN";

    let client = reqwest::Client::new();
    let response = client
        .post("http://127.0.0.1:40325/profiles/123e4567-e89b-12d3-a456-426614174000/start")
        .header("Authorization", format!("Bearer {token}"))
        .json(&serde_json::json!({
          "headless": false
        }))
        .send()
        .await?;

    println!("{}", response.status());
    println!("{}", response.text().await?);
    Ok(())
}
using System;
using System.Net.Http;
using System.Net.Http.Headers;
using System.Text;
using System.Threading.Tasks;

class Program
{
    static async Task Main()
    {
        // Permanent JWT from Settings → Automation API.
        var token = "YOUR_SECRET_TOKEN";

        using var client = new HttpClient();
        client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", token);

        var request = new HttpRequestMessage(HttpMethod.Post, "http://127.0.0.1:40325/profiles/123e4567-e89b-12d3-a456-426614174000/start");
        request.Content = new StringContent("""
            {
              "headless": false
            }
            """, Encoding.UTF8, "application/json");

        var response = await client.SendAsync(request);
        Console.WriteLine((int)response.StatusCode);
        Console.WriteLine(await response.Content.ReadAsStringAsync());
    }
}
// build: c++ -std=c++17 main.cpp -lcurl
#include <curl/curl.h>

#include <iostream>
#include <string>

static size_t write_cb(char *ptr, size_t size, size_t nmemb, void *userdata) {
    static_cast<std::string *>(userdata)->append(ptr, size * nmemb);
    return size * nmemb;
}

int main() {
    // Permanent JWT from Settings → Automation API.
    const std::string token = "YOUR_SECRET_TOKEN";

    curl_global_init(CURL_GLOBAL_DEFAULT);
    CURL *curl = curl_easy_init();
    if (!curl) {
        std::cerr << "curl_easy_init failed\n";
        curl_global_cleanup();
        return 1;
    }

    struct curl_slist *headers = nullptr;
    headers = curl_slist_append(headers, ("Authorization: Bearer " + token).c_str());
    headers = curl_slist_append(headers, "Content-Type: application/json");

    const std::string body = R"json({
  "headless": false
})json";

    std::string response;
    curl_easy_setopt(curl, CURLOPT_URL, "http://127.0.0.1:40325/profiles/123e4567-e89b-12d3-a456-426614174000/start");
    curl_easy_setopt(curl, CURLOPT_CUSTOMREQUEST, "POST");
    curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headers);
    curl_easy_setopt(curl, CURLOPT_POSTFIELDS, body.c_str());
    curl_easy_setopt(curl, CURLOPT_POSTFIELDSIZE, static_cast<long>(body.size()));
    curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, write_cb);
    curl_easy_setopt(curl, CURLOPT_WRITEDATA, &response);

    const CURLcode rc = curl_easy_perform(curl);
    if (rc != CURLE_OK) {
        std::cerr << curl_easy_strerror(rc) << "\n";
    } else {
        long status = 0;
        curl_easy_getinfo(curl, CURLINFO_RESPONSE_CODE, &status);
        std::cout << status << "\n" << response << "\n";
    }

    curl_slist_free_all(headers);
    curl_easy_cleanup(curl);
    curl_global_cleanup();
    return rc == CURLE_OK ? 0 : 1;
}
{
  "profile_id": "text",
  "pid": 1,
  "headless": true,
  "cdp": {
    "port": 1,
    "http_url": "http://127.0.0.1:53217",
    "web_socket_debugger_url": "ws://127.0.0.1:53217/devtools/browser/ab12-..."
  },
  "cdp_error": "text"
}
{
  "error": "text"
}

Stop a profile

POSThttp://127.0.0.1:40325/profiles/{id}/stop

Sends the browser a graceful shutdown (SIGTERM on Unix; 5s grace then SIGKILL). Temporary profiles are deleted as part of close. stopped is false if the profile wasn't running.

Authorizations
bearerAuth
Authorizationstringrequired

Permanent JWT from Settings → Automation API.

Path parameters
idstring · uuidrequired

Profile UUID.

Responses
200Stop requested.application/json
profile_idstringoptional
stoppedbooleanoptional
401Missing or invalid Bearer token.
POST/profiles/123e4567-e89b-12d3-a456-426614174000/stop
POST /profiles/123e4567-e89b-12d3-a456-426614174000/stop HTTP/1.1
Host: 127.0.0.1:40325
Authorization: Bearer YOUR_SECRET_TOKEN
Accept: */*
curl -X POST 'http://127.0.0.1:40325/profiles/123e4567-e89b-12d3-a456-426614174000/stop' \
  -H 'Authorization: Bearer YOUR_SECRET_TOKEN'
import requests

# Permanent JWT from Settings → Automation API.
token = "YOUR_SECRET_TOKEN"

url = "http://127.0.0.1:40325/profiles/123e4567-e89b-12d3-a456-426614174000/stop"
headers = {
    "Authorization": f"Bearer {token}",
}

response = requests.post(url, headers=headers, timeout=30)
response.raise_for_status()
print(response.status_code)
print(response.text)
// Permanent JWT from Settings → Automation API.
const token = "YOUR_SECRET_TOKEN";

const url = "http://127.0.0.1:40325/profiles/123e4567-e89b-12d3-a456-426614174000/stop";

const response = await fetch(url, {
  method: "POST",
  headers: {
    "Authorization": `Bearer ${token}`,
  },
});

console.log(response.status);
console.log(await response.text());
package main

import (
	"fmt"
	"io"
	"log"
	"net/http"
)

func main() {
	// Permanent JWT from Settings → Automation API.
	token := "YOUR_SECRET_TOKEN"

	url := "http://127.0.0.1:40325/profiles/123e4567-e89b-12d3-a456-426614174000/stop"

	req, err := http.NewRequest("POST", url, nil)
	if err != nil {
		log.Fatal(err)
	}
	req.Header.Set("Authorization", "Bearer "+token)

	resp, err := http.DefaultClient.Do(req)
	if err != nil {
		log.Fatal(err)
	}
	defer resp.Body.Close()

	out, err := io.ReadAll(resp.Body)
	if err != nil {
		log.Fatal(err)
	}
	fmt.Println(resp.Status)
	fmt.Println(string(out))
}
// Cargo.toml: reqwest = { version = "0.12", features = ["json"] }, tokio = { version = "1", features = ["full"] }

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
    // Permanent JWT from Settings → Automation API.
    let token = "YOUR_SECRET_TOKEN";

    let client = reqwest::Client::new();
    let response = client
        .post("http://127.0.0.1:40325/profiles/123e4567-e89b-12d3-a456-426614174000/stop")
        .header("Authorization", format!("Bearer {token}"))
        .send()
        .await?;

    println!("{}", response.status());
    println!("{}", response.text().await?);
    Ok(())
}
using System;
using System.Net.Http;
using System.Net.Http.Headers;
using System.Threading.Tasks;

class Program
{
    static async Task Main()
    {
        // Permanent JWT from Settings → Automation API.
        var token = "YOUR_SECRET_TOKEN";

        using var client = new HttpClient();
        client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", token);

        var request = new HttpRequestMessage(HttpMethod.Post, "http://127.0.0.1:40325/profiles/123e4567-e89b-12d3-a456-426614174000/stop");

        var response = await client.SendAsync(request);
        Console.WriteLine((int)response.StatusCode);
        Console.WriteLine(await response.Content.ReadAsStringAsync());
    }
}
// build: c++ -std=c++17 main.cpp -lcurl
#include <curl/curl.h>

#include <iostream>
#include <string>

static size_t write_cb(char *ptr, size_t size, size_t nmemb, void *userdata) {
    static_cast<std::string *>(userdata)->append(ptr, size * nmemb);
    return size * nmemb;
}

int main() {
    // Permanent JWT from Settings → Automation API.
    const std::string token = "YOUR_SECRET_TOKEN";

    curl_global_init(CURL_GLOBAL_DEFAULT);
    CURL *curl = curl_easy_init();
    if (!curl) {
        std::cerr << "curl_easy_init failed\n";
        curl_global_cleanup();
        return 1;
    }

    struct curl_slist *headers = nullptr;
    headers = curl_slist_append(headers, ("Authorization: Bearer " + token).c_str());

    std::string response;
    curl_easy_setopt(curl, CURLOPT_URL, "http://127.0.0.1:40325/profiles/123e4567-e89b-12d3-a456-426614174000/stop");
    curl_easy_setopt(curl, CURLOPT_CUSTOMREQUEST, "POST");
    curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headers);
    curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, write_cb);
    curl_easy_setopt(curl, CURLOPT_WRITEDATA, &response);

    const CURLcode rc = curl_easy_perform(curl);
    if (rc != CURLE_OK) {
        std::cerr << curl_easy_strerror(rc) << "\n";
    } else {
        long status = 0;
        curl_easy_getinfo(curl, CURLINFO_RESPONSE_CODE, &status);
        std::cout << status << "\n" << response << "\n";
    }

    curl_slist_free_all(headers);
    curl_easy_cleanup(curl);
    curl_global_cleanup();
    return rc == CURLE_OK ? 0 : 1;
}
200Stop requested.
{
  "profile_id": "text",
  "stopped": true
}

Export cookies

GEThttp://127.0.0.1:40325/profiles/{id}/cookies

Reads the profile's Chromium cookie store and returns all cookies decrypted. Works whether the profile is running or stopped. Empty array if the profile has never launched.

Authorizations
bearerAuth
Authorizationstringrequired

Permanent JWT from Settings → Automation API.

Path parameters
idstring · uuidrequired

Profile UUID.

Responses
200Cookies.application/json
cookiesobject · Cookie[]optional
Show propertiesHide properties
domainstringrequired

Cookie host (Chromium host_key), e.g. ".example.com".

namestringrequired
valuestringrequired
pathstring· default: "/"optional
expiresnumber· nullableoptional

Unix seconds; null/absent = session cookie.

secureboolean· default: falseoptional
http_onlyboolean· default: falseoptional
same_sitestring · enumoptional

Case-insensitive on import.

Possible values:StrictLaxNoneunspecified
401Missing or invalid Bearer token.
500Cookie DB read/decrypt failed.application/json
errorstringrequired
GET/profiles/123e4567-e89b-12d3-a456-426614174000/cookies
GET /profiles/123e4567-e89b-12d3-a456-426614174000/cookies HTTP/1.1
Host: 127.0.0.1:40325
Authorization: Bearer YOUR_SECRET_TOKEN
Accept: */*
curl -X GET 'http://127.0.0.1:40325/profiles/123e4567-e89b-12d3-a456-426614174000/cookies' \
  -H 'Authorization: Bearer YOUR_SECRET_TOKEN'
import requests

# Permanent JWT from Settings → Automation API.
token = "YOUR_SECRET_TOKEN"

url = "http://127.0.0.1:40325/profiles/123e4567-e89b-12d3-a456-426614174000/cookies"
headers = {
    "Authorization": f"Bearer {token}",
}

response = requests.get(url, headers=headers, timeout=30)
response.raise_for_status()
print(response.status_code)
print(response.text)
// Permanent JWT from Settings → Automation API.
const token = "YOUR_SECRET_TOKEN";

const url = "http://127.0.0.1:40325/profiles/123e4567-e89b-12d3-a456-426614174000/cookies";

const response = await fetch(url, {
  method: "GET",
  headers: {
    "Authorization": `Bearer ${token}`,
  },
});

console.log(response.status);
console.log(await response.text());
package main

import (
	"fmt"
	"io"
	"log"
	"net/http"
)

func main() {
	// Permanent JWT from Settings → Automation API.
	token := "YOUR_SECRET_TOKEN"

	url := "http://127.0.0.1:40325/profiles/123e4567-e89b-12d3-a456-426614174000/cookies"

	req, err := http.NewRequest("GET", url, nil)
	if err != nil {
		log.Fatal(err)
	}
	req.Header.Set("Authorization", "Bearer "+token)

	resp, err := http.DefaultClient.Do(req)
	if err != nil {
		log.Fatal(err)
	}
	defer resp.Body.Close()

	out, err := io.ReadAll(resp.Body)
	if err != nil {
		log.Fatal(err)
	}
	fmt.Println(resp.Status)
	fmt.Println(string(out))
}
// Cargo.toml: reqwest = { version = "0.12", features = ["json"] }, tokio = { version = "1", features = ["full"] }

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
    // Permanent JWT from Settings → Automation API.
    let token = "YOUR_SECRET_TOKEN";

    let client = reqwest::Client::new();
    let response = client
        .get("http://127.0.0.1:40325/profiles/123e4567-e89b-12d3-a456-426614174000/cookies")
        .header("Authorization", format!("Bearer {token}"))
        .send()
        .await?;

    println!("{}", response.status());
    println!("{}", response.text().await?);
    Ok(())
}
using System;
using System.Net.Http;
using System.Net.Http.Headers;
using System.Threading.Tasks;

class Program
{
    static async Task Main()
    {
        // Permanent JWT from Settings → Automation API.
        var token = "YOUR_SECRET_TOKEN";

        using var client = new HttpClient();
        client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", token);

        var request = new HttpRequestMessage(HttpMethod.Get, "http://127.0.0.1:40325/profiles/123e4567-e89b-12d3-a456-426614174000/cookies");

        var response = await client.SendAsync(request);
        Console.WriteLine((int)response.StatusCode);
        Console.WriteLine(await response.Content.ReadAsStringAsync());
    }
}
// build: c++ -std=c++17 main.cpp -lcurl
#include <curl/curl.h>

#include <iostream>
#include <string>

static size_t write_cb(char *ptr, size_t size, size_t nmemb, void *userdata) {
    static_cast<std::string *>(userdata)->append(ptr, size * nmemb);
    return size * nmemb;
}

int main() {
    // Permanent JWT from Settings → Automation API.
    const std::string token = "YOUR_SECRET_TOKEN";

    curl_global_init(CURL_GLOBAL_DEFAULT);
    CURL *curl = curl_easy_init();
    if (!curl) {
        std::cerr << "curl_easy_init failed\n";
        curl_global_cleanup();
        return 1;
    }

    struct curl_slist *headers = nullptr;
    headers = curl_slist_append(headers, ("Authorization: Bearer " + token).c_str());

    std::string response;
    curl_easy_setopt(curl, CURLOPT_URL, "http://127.0.0.1:40325/profiles/123e4567-e89b-12d3-a456-426614174000/cookies");
    curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headers);
    curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, write_cb);
    curl_easy_setopt(curl, CURLOPT_WRITEDATA, &response);

    const CURLcode rc = curl_easy_perform(curl);
    if (rc != CURLE_OK) {
        std::cerr << curl_easy_strerror(rc) << "\n";
    } else {
        long status = 0;
        curl_easy_getinfo(curl, CURLINFO_RESPONSE_CODE, &status);
        std::cout << status << "\n" << response << "\n";
    }

    curl_slist_free_all(headers);
    curl_easy_cleanup(curl);
    curl_global_cleanup();
    return rc == CURLE_OK ? 0 : 1;
}
{
  "cookies": [
    {
      "domain": "text",
      "name": "text",
      "value": "text",
      "path": "/",
      "expires": 1,
      "secure": false,
      "http_only": false,
      "same_site": "Strict"
    }
  ]
}
{
  "error": "text"
}

Import cookies

POSThttp://127.0.0.1:40325/profiles/{id}/cookies

Writes cookies into the profile's cookie store (re-encrypting to Chromium's v10 scheme). The profile must be stopped; a running browser rewrites the store on exit and would clobber the import.

Authorizations
bearerAuth
Authorizationstringrequired

Permanent JWT from Settings → Automation API.

Path parameters
idstring · uuidrequired

Profile UUID.

Body
application/json
cookiesobject · Cookie[]required
Show propertiesHide properties
domainstringrequired

Cookie host (Chromium host_key), e.g. ".example.com".

namestringrequired
valuestringrequired
pathstring· default: "/"optional
expiresnumber· nullableoptional

Unix seconds; null/absent = session cookie.

secureboolean· default: falseoptional
http_onlyboolean· default: falseoptional
same_sitestring · enumoptional

Case-insensitive on import.

Possible values:StrictLaxNoneunspecified
Responses
200Imported.application/json
importedintegeroptional

Number of cookies written.

401Missing or invalid Bearer token.
409Profile is running; stop it first.application/json
errorstringrequired
500Cookie DB write failed.application/json
errorstringrequired
POST/profiles/123e4567-e89b-12d3-a456-426614174000/cookies
POST /profiles/123e4567-e89b-12d3-a456-426614174000/cookies HTTP/1.1
Host: 127.0.0.1:40325
Authorization: Bearer YOUR_SECRET_TOKEN
Content-Type: application/json
Accept: */*

{
  "cookies": [
    {
      "domain": "text",
      "name": "text",
      "value": "text",
      "path": "/",
      "expires": 1,
      "secure": false,
      "http_only": false,
      "same_site": "Strict"
    }
  ]
}
curl -X POST 'http://127.0.0.1:40325/profiles/123e4567-e89b-12d3-a456-426614174000/cookies' \
  -H 'Authorization: Bearer YOUR_SECRET_TOKEN' \
  -H 'Content-Type: application/json' \
  -d '{"cookies":[{"domain":"text","name":"text","value":"text","path":"/","expires":1,"secure":false,"http_only":false,"same_site":"Strict"}]}'
import requests

# Permanent JWT from Settings → Automation API.
token = "YOUR_SECRET_TOKEN"

url = "http://127.0.0.1:40325/profiles/123e4567-e89b-12d3-a456-426614174000/cookies"
headers = {
    "Authorization": f"Bearer {token}",
}
payload = {
    "cookies": [
        {
            "domain": "text",
            "name": "text",
            "value": "text",
            "path": "/",
            "expires": 1,
            "secure": False,
            "http_only": False,
            "same_site": "Strict",
        },
    ],
}

response = requests.post(url, headers=headers, json=payload, timeout=30)
response.raise_for_status()
print(response.status_code)
print(response.text)
// Permanent JWT from Settings → Automation API.
const token = "YOUR_SECRET_TOKEN";

const url = "http://127.0.0.1:40325/profiles/123e4567-e89b-12d3-a456-426614174000/cookies";
const payload = {
  "cookies": [
    {
      "domain": "text",
      "name": "text",
      "value": "text",
      "path": "/",
      "expires": 1,
      "secure": false,
      "http_only": false,
      "same_site": "Strict"
    }
  ]
};

const response = await fetch(url, {
  method: "POST",
  headers: {
    "Authorization": `Bearer ${token}`,
    "Content-Type": "application/json",
  },
  body: JSON.stringify(payload),
});

console.log(response.status);
console.log(await response.text());
package main

import (
	"bytes"
	"fmt"
	"io"
	"log"
	"net/http"
)

func main() {
	// Permanent JWT from Settings → Automation API.
	token := "YOUR_SECRET_TOKEN"

	url := "http://127.0.0.1:40325/profiles/123e4567-e89b-12d3-a456-426614174000/cookies"
	body := bytes.NewBufferString(`{
  "cookies": [
    {
      "domain": "text",
      "name": "text",
      "value": "text",
      "path": "/",
      "expires": 1,
      "secure": false,
      "http_only": false,
      "same_site": "Strict"
    }
  ]
}`)

	req, err := http.NewRequest("POST", url, body)
	if err != nil {
		log.Fatal(err)
	}
	req.Header.Set("Authorization", "Bearer "+token)
	req.Header.Set("Content-Type", "application/json")

	resp, err := http.DefaultClient.Do(req)
	if err != nil {
		log.Fatal(err)
	}
	defer resp.Body.Close()

	out, err := io.ReadAll(resp.Body)
	if err != nil {
		log.Fatal(err)
	}
	fmt.Println(resp.Status)
	fmt.Println(string(out))
}
// Cargo.toml: reqwest = { version = "0.12", features = ["json"] }, tokio = { version = "1", features = ["full"] }, serde_json = "1"

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
    // Permanent JWT from Settings → Automation API.
    let token = "YOUR_SECRET_TOKEN";

    let client = reqwest::Client::new();
    let response = client
        .post("http://127.0.0.1:40325/profiles/123e4567-e89b-12d3-a456-426614174000/cookies")
        .header("Authorization", format!("Bearer {token}"))
        .json(&serde_json::json!({
          "cookies": [
            {
              "domain": "text",
              "name": "text",
              "value": "text",
              "path": "/",
              "expires": 1,
              "secure": false,
              "http_only": false,
              "same_site": "Strict"
            }
          ]
        }))
        .send()
        .await?;

    println!("{}", response.status());
    println!("{}", response.text().await?);
    Ok(())
}
using System;
using System.Net.Http;
using System.Net.Http.Headers;
using System.Text;
using System.Threading.Tasks;

class Program
{
    static async Task Main()
    {
        // Permanent JWT from Settings → Automation API.
        var token = "YOUR_SECRET_TOKEN";

        using var client = new HttpClient();
        client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", token);

        var request = new HttpRequestMessage(HttpMethod.Post, "http://127.0.0.1:40325/profiles/123e4567-e89b-12d3-a456-426614174000/cookies");
        request.Content = new StringContent("""
            {
              "cookies": [
                {
                  "domain": "text",
                  "name": "text",
                  "value": "text",
                  "path": "/",
                  "expires": 1,
                  "secure": false,
                  "http_only": false,
                  "same_site": "Strict"
                }
              ]
            }
            """, Encoding.UTF8, "application/json");

        var response = await client.SendAsync(request);
        Console.WriteLine((int)response.StatusCode);
        Console.WriteLine(await response.Content.ReadAsStringAsync());
    }
}
// build: c++ -std=c++17 main.cpp -lcurl
#include <curl/curl.h>

#include <iostream>
#include <string>

static size_t write_cb(char *ptr, size_t size, size_t nmemb, void *userdata) {
    static_cast<std::string *>(userdata)->append(ptr, size * nmemb);
    return size * nmemb;
}

int main() {
    // Permanent JWT from Settings → Automation API.
    const std::string token = "YOUR_SECRET_TOKEN";

    curl_global_init(CURL_GLOBAL_DEFAULT);
    CURL *curl = curl_easy_init();
    if (!curl) {
        std::cerr << "curl_easy_init failed\n";
        curl_global_cleanup();
        return 1;
    }

    struct curl_slist *headers = nullptr;
    headers = curl_slist_append(headers, ("Authorization: Bearer " + token).c_str());
    headers = curl_slist_append(headers, "Content-Type: application/json");

    const std::string body = R"json({
  "cookies": [
    {
      "domain": "text",
      "name": "text",
      "value": "text",
      "path": "/",
      "expires": 1,
      "secure": false,
      "http_only": false,
      "same_site": "Strict"
    }
  ]
})json";

    std::string response;
    curl_easy_setopt(curl, CURLOPT_URL, "http://127.0.0.1:40325/profiles/123e4567-e89b-12d3-a456-426614174000/cookies");
    curl_easy_setopt(curl, CURLOPT_CUSTOMREQUEST, "POST");
    curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headers);
    curl_easy_setopt(curl, CURLOPT_POSTFIELDS, body.c_str());
    curl_easy_setopt(curl, CURLOPT_POSTFIELDSIZE, static_cast<long>(body.size()));
    curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, write_cb);
    curl_easy_setopt(curl, CURLOPT_WRITEDATA, &response);

    const CURLcode rc = curl_easy_perform(curl);
    if (rc != CURLE_OK) {
        std::cerr << curl_easy_strerror(rc) << "\n";
    } else {
        long status = 0;
        curl_easy_getinfo(curl, CURLINFO_RESPONSE_CODE, &status);
        std::cout << status << "\n" << response << "\n";
    }

    curl_slist_free_all(headers);
    curl_easy_cleanup(curl);
    curl_global_cleanup();
    return rc == CURLE_OK ? 0 : 1;
}
{
  "imported": 1
}
{
  "error": "text"
}
{
  "error": "text"
}

List running profiles

GEThttp://127.0.0.1:40325/running

Profiles with a live browser process, including the CDP endpoint when launched via the API.

Authorizations
bearerAuth
Authorizationstringrequired

Permanent JWT from Settings → Automation API.

Responses
200Running profiles.application/json
profile_idstringoptional
pidinteger · int64optional
cdpobject · CdpInfo· nullableoptional

Chrome DevTools Protocol endpoint of a running profile.

Show propertiesHide properties
portintegeroptional

Chrome-chosen remote-debugging port.

http_urlstringoptional

REST base (/json, /json/version).

web_socket_debugger_urlstringoptional

Browser-level WS endpoint for Puppeteer/Playwright connect.

401Missing or invalid Bearer token.
GET/running
GET /running HTTP/1.1
Host: 127.0.0.1:40325
Authorization: Bearer YOUR_SECRET_TOKEN
Accept: */*
curl -X GET 'http://127.0.0.1:40325/running' \
  -H 'Authorization: Bearer YOUR_SECRET_TOKEN'
import requests

# Permanent JWT from Settings → Automation API.
token = "YOUR_SECRET_TOKEN"

url = "http://127.0.0.1:40325/running"
headers = {
    "Authorization": f"Bearer {token}",
}

response = requests.get(url, headers=headers, timeout=30)
response.raise_for_status()
print(response.status_code)
print(response.text)
// Permanent JWT from Settings → Automation API.
const token = "YOUR_SECRET_TOKEN";

const url = "http://127.0.0.1:40325/running";

const response = await fetch(url, {
  method: "GET",
  headers: {
    "Authorization": `Bearer ${token}`,
  },
});

console.log(response.status);
console.log(await response.text());
package main

import (
	"fmt"
	"io"
	"log"
	"net/http"
)

func main() {
	// Permanent JWT from Settings → Automation API.
	token := "YOUR_SECRET_TOKEN"

	url := "http://127.0.0.1:40325/running"

	req, err := http.NewRequest("GET", url, nil)
	if err != nil {
		log.Fatal(err)
	}
	req.Header.Set("Authorization", "Bearer "+token)

	resp, err := http.DefaultClient.Do(req)
	if err != nil {
		log.Fatal(err)
	}
	defer resp.Body.Close()

	out, err := io.ReadAll(resp.Body)
	if err != nil {
		log.Fatal(err)
	}
	fmt.Println(resp.Status)
	fmt.Println(string(out))
}
// Cargo.toml: reqwest = { version = "0.12", features = ["json"] }, tokio = { version = "1", features = ["full"] }

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
    // Permanent JWT from Settings → Automation API.
    let token = "YOUR_SECRET_TOKEN";

    let client = reqwest::Client::new();
    let response = client
        .get("http://127.0.0.1:40325/running")
        .header("Authorization", format!("Bearer {token}"))
        .send()
        .await?;

    println!("{}", response.status());
    println!("{}", response.text().await?);
    Ok(())
}
using System;
using System.Net.Http;
using System.Net.Http.Headers;
using System.Threading.Tasks;

class Program
{
    static async Task Main()
    {
        // Permanent JWT from Settings → Automation API.
        var token = "YOUR_SECRET_TOKEN";

        using var client = new HttpClient();
        client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", token);

        var request = new HttpRequestMessage(HttpMethod.Get, "http://127.0.0.1:40325/running");

        var response = await client.SendAsync(request);
        Console.WriteLine((int)response.StatusCode);
        Console.WriteLine(await response.Content.ReadAsStringAsync());
    }
}
// build: c++ -std=c++17 main.cpp -lcurl
#include <curl/curl.h>

#include <iostream>
#include <string>

static size_t write_cb(char *ptr, size_t size, size_t nmemb, void *userdata) {
    static_cast<std::string *>(userdata)->append(ptr, size * nmemb);
    return size * nmemb;
}

int main() {
    // Permanent JWT from Settings → Automation API.
    const std::string token = "YOUR_SECRET_TOKEN";

    curl_global_init(CURL_GLOBAL_DEFAULT);
    CURL *curl = curl_easy_init();
    if (!curl) {
        std::cerr << "curl_easy_init failed\n";
        curl_global_cleanup();
        return 1;
    }

    struct curl_slist *headers = nullptr;
    headers = curl_slist_append(headers, ("Authorization: Bearer " + token).c_str());

    std::string response;
    curl_easy_setopt(curl, CURLOPT_URL, "http://127.0.0.1:40325/running");
    curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headers);
    curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, write_cb);
    curl_easy_setopt(curl, CURLOPT_WRITEDATA, &response);

    const CURLcode rc = curl_easy_perform(curl);
    if (rc != CURLE_OK) {
        std::cerr << curl_easy_strerror(rc) << "\n";
    } else {
        long status = 0;
        curl_easy_getinfo(curl, CURLINFO_RESPONSE_CODE, &status);
        std::cout << status << "\n" << response << "\n";
    }

    curl_slist_free_all(headers);
    curl_easy_cleanup(curl);
    curl_global_cleanup();
    return rc == CURLE_OK ? 0 : 1;
}
200Running profiles.
[
  {
    "profile_id": "text",
    "pid": 1,
    "cdp": {
      "port": 1,
      "http_url": "http://127.0.0.1:53217",
      "web_socket_debugger_url": "ws://127.0.0.1:53217/devtools/browser/ab12-..."
    }
  }
]

Last updated on

On this page