Developers

Local API

Available on every planREST over HTTP · JSONCDP endpoint per profile

The Kryptix desktop app runs a small HTTP server on your own machine. Anything you can do in the app — create profiles, assign proxies, launch and stop them, import cookies, run RPA flows — you can do from a script. Launching a profile for automation also gives you a Chrome DevTools Protocol endpoint for Puppeteer, Playwright or Selenium.

Basics

  • Base URL: http://127.0.0.1:8777. The port can be changed in Settings → Local API; the app must be running and signed in.
  • Local only. The server listens on the loopback interface and refuses requests that do not come from your machine. It is not reachable from the network.
  • Format. Send JSON with Content-Type: application/json. Most endpoints are POST; a few read-only ones are GET. Responses are JSON.
  • Profile IDs are the id strings returned by /api/state and /api/create.

Authentication

By default the API trusts any program running on your computer. To require a key, open Settings → Local API, generate a key, save, and send it with every request as the X-Api-Key header (or as a ?key= query parameter). Requests without a valid key get 401.

curl http://127.0.0.1:8777/api/state -H "X-Api-Key: YOUR_KEY"

Profiles

GET/api/state

Everything the app knows: profiles (with their persona summary, folder, proxy and running state), folders and the option lists used by the profile editor.

Response

{
  "profiles": [
    { "id": "7f3c…", "name": "acme-07", "folder": "general", "proxy": "socks5://user:pass@host:1080",
      "running": false, "tags": ["ads"], "notes": "",
      "summary": { "os": "Windows 11", "gpu": "NVIDIA GeForce RTX 3060", "cpu": 8, "ram": 16,
                   "locale": "de", "timezone": "Europe/Berlin", "screen": "1920x1080", "webrtc": "proxy-only" },
      "profile": { "...": "full persona JSON" } }
  ],
  "folders": [ { "id": "general", "name": "General" } ],
  "options": { "osFamilies": [ "..." ], "regions": [ "..." ], "screens": [ "..." ] }
}
POST/api/create

Create one or more profiles. Leave fields empty and set randomizeDevice to get a fresh, consistent persona per profile. With matchIp the language, timezone and location follow the exit IP of the proxy.

{
  "folder": "general",            // optional folder id
  "name": "acme",                 // optional; bulk creates "acme 1", "acme 2", …
  "count": 3,                     // 1–200
  "matchIp": true,                // language / timezone / geo from the proxy's exit IP
  "randomizeDevice": true,        // new persona per profile (ignores device fields below)
  "region": "de",                 // used when matchIp is false; see options.regions
  "fields": {
    "osFamily": "windows",        // windows | windows10 | macos | linux
    "platformVersion": "19.0.0",  // optional, see options.windows / macVersions / linuxVersions
    "webglRenderer": "",          // optional, exact renderer string from /api/gpus
    "cores": 8, "memory": 16,     // optional
    "resolution": "1920x1080",
    "proxy": "socks5://user:pass@host:1080",   // http://, https:// or socks5://; host:port:user:pass also accepted
    "udpProxy": false,            // route WebRTC / QUIC UDP through a UDP-capable SOCKS5 proxy
    "canvas": "real", "audio": "real", "clientRects": "real",   // real | noise | off
    "webrtc": "proxy-only",       // real | proxy-only | proxy-public-ip
    "tags": ["ads", "eu"]
  }
}

Response

{ "created": ["7f3c…", "a91e…", "c0d2…"], "warning": "" }
POST/api/update

Change a profile's persona fields and/or metadata. Only the keys you send are changed; the fingerprint seed is kept.

{ "id": "7f3c…",
  "fields": { "proxy": "http://user:pass@host:8080", "resolution": "1366x768" },
  "meta":   { "name": "acme-07", "folder": "general", "tags": ["ads"], "notes": "", "proxy": "http://user:pass@host:8080" } }

Response

{ "ok": true }
POST/api/clone

Duplicate a profile with a new identity (new id, new fingerprint seed). Cookies are not copied.

{ "id": "7f3c…" }

Response

{ "id": "e5b7…" }
POST/api/delete

Delete a profile and all of its data. Irreversible.

{ "id": "7f3c…" }

Response

{ "ok": true }
GET/api/gpus?os=windows&mode=smart

Renderer strings you can put into fields.webglRenderer. os: windows | windows10 | macos | linux (Linux also needs &pv= kernel version from options.linuxVersions). mode: smart (consistent with this computer) | normal (whole list).

Response

{ "os": "windows", "mode": "smart", "gpus": [ { "vendor": "Google Inc. (NVIDIA)", "renderer": "ANGLE (NVIDIA, …)", "name": "…" } ] }

Launch & stop

POST/api/launch

Open a profile window (no automation endpoint). Returns immediately.

{ "id": "7f3c…" }

Response

{ "status": "started" }
POST/api/launchmany

Open several profiles at once.

{ "ids": ["7f3c…", "a91e…"] }

Response

{ "results": { "7f3c…": "started", "a91e…": "already open" } }
POST/api/stop

Close a profile. force kills it if it does not close gracefully.

{ "id": "7f3c…", "force": false }

Response

{ "status": "stopped" }
POST/api/stopmany

Close several profiles.

{ "ids": ["7f3c…", "a91e…"] }
POST/api/stopall

Close every running profile.

POST/api/open

Open a URL in a profile that is already running.

{ "id": "7f3c…", "url": "https://example.com" }

Automation (CDP)

Start a profile through /api/automation/start and attach your own tool to the returned Chrome DevTools Protocol endpoint. Fingerprint, proxy and leak protection are all applied by Kryptix before your code connects, so the session looks exactly like one opened by hand. Never start the browser executable yourself.

POST/api/automation/start

Launch the profile with remote debugging enabled and wait for the endpoint (up to ~12 s). If the profile is already running with CDP, the existing endpoint is returned.

{ "id": "7f3c…" }

Response

{ "ok": true, "status": "started", "port": 51234,
  "browserUrl": "http://127.0.0.1:51234",
  "webSocketDebuggerUrl": "ws://127.0.0.1:51234/devtools/browser/0c3a…" }
GET/api/automation/endpoint?id=7f3c…

Endpoint of a profile that is already running with CDP.

Response

{ "ok": true, "port": 51234, "browserUrl": "http://127.0.0.1:51234", "webSocketDebuggerUrl": "ws://…" }

Proxies

POST/api/proxy/test

Test a proxy and get its exit IP. HTTP, HTTPS and SOCKS5 with authentication are supported.

{ "proxy": "socks5://user:pass@host:1080" }

Response

{ "ok": true, "scheme": "socks5", "query": "203.0.113.7", "country": "Germany", "countryCode": "DE",
  "city": "Frankfurt am Main", "isp": "…", "proxy": true, "hosting": true, "mobile": false }
POST/api/proxy/assign

Assign a list of proxies to a list of profiles, in order (if there are fewer proxies than profiles they repeat). Lines without a scheme get defaultScheme.

{ "ids": ["7f3c…", "a91e…"], "proxies": ["host:1080:user:pass", "socks5://user:pass@host2:1080"], "defaultScheme": "socks5" }
POST/api/ipinfo

Exit IP, country and timezone of a proxy (or of your own connection when proxy is omitted).

{ "proxy": "socks5://user:pass@host:1080" }

Cookies

POST/api/cookies/import

Create one profile per cookie file (Netscape cookies.txt or JSON export). The profile is named after the file; the other fields work exactly like /api/create.

{ "files": [ { "name": "acme-07.txt", "text": "# Netscape HTTP Cookie File\n.example.com\tTRUE\t/\tTRUE\t1800000000\tsid\tabc…" } ],
  "folder": "general", "matchIp": true, "randomizeDevice": true, "fields": { "proxy": "socks5://…" } }

Response

{ "results": [ { "ok": true, "id": "b7a0…", "name": "acme-07", "cookies": 42 } ] }

RPA flows (Pro)

GET/api/rpa/flows

List saved flows.

Response

[ { "id": "signup-flow", "name": "Sign-up flow", "steps": 14, "updatedAt": "2026-10-21T10:00:00" } ]
POST/api/rpa/run

Run a saved flow (id) or an inline flow object (flow) on one or more profiles. Profiles that are closed are opened in RPA mode. Optional: concurrency, startDelay (seconds between starts) and rows (one data row per profile, e.g. from a spreadsheet).

{ "id": "signup-flow", "profileIds": ["7f3c…", "a91e…", "c0d2…"],
  "concurrency": 3, "startDelay": 5,
  "rows": [ { "email": "a@example.com", "name": "Anna" }, { "email": "b@example.com", "name": "Ben" } ] }

Response

{ "ok": true, "jobId": "j_20261021_…", "items": 3, "warnings": [] }
GET/api/rpa/jobs

Running and finished jobs with per-profile progress.

POST/api/rpa/job/cancel

Cancel a running job.

{ "id": "j_20261021_…", "item": null }

Examples

curl

# create 2 profiles with a proxy, persona from the exit IP
curl -s http://127.0.0.1:8777/api/create -H "Content-Type: application/json" -H "X-Api-Key: $KEY" \
  -d '{"count":2,"matchIp":true,"randomizeDevice":true,"fields":{"proxy":"socks5://user:pass@host:1080"}}'

# start one for automation and read the CDP endpoint
curl -s http://127.0.0.1:8777/api/automation/start -H "Content-Type: application/json" -H "X-Api-Key: $KEY" -d '{"id":"7f3c…"}'

Python + Playwright

import requests
from playwright.sync_api import sync_playwright

API = "http://127.0.0.1:8777"
H = {"X-Api-Key": "YOUR_KEY"}

pid = requests.post(f"{API}/api/create", json={
    "count": 1, "matchIp": True, "randomizeDevice": True,
    "fields": {"proxy": "socks5://user:pass@host:1080"}}, headers=H).json()["created"][0]

ep = requests.post(f"{API}/api/automation/start", json={"id": pid}, headers=H).json()

with sync_playwright() as p:
    browser = p.chromium.connect_over_cdp(ep["browserUrl"])
    page = browser.contexts[0].pages[0]
    page.goto("https://example.com")
    print(page.title())

requests.post(f"{API}/api/stop", json={"id": pid}, headers=H)

Node + Puppeteer

import puppeteer from "puppeteer-core";

const API = "http://127.0.0.1:8777", H = { "Content-Type": "application/json", "X-Api-Key": "YOUR_KEY" };
const post = (p, b) => fetch(API + p, { method: "POST", headers: H, body: JSON.stringify(b) }).then(r => r.json());

const { created: [id] } = await post("/api/create", { count: 1, randomizeDevice: true, matchIp: true });
const ep = await post("/api/automation/start", { id });
const browser = await puppeteer.connect({ browserWSEndpoint: ep.webSocketDebuggerUrl });
const page = (await browser.pages())[0];
await page.goto("https://example.com");
browser.disconnect();
await post("/api/stop", { id });

Errors

StatusMeaning
401Missing or wrong X-Api-Key (only when a key is set in Settings).
403Request did not come from this machine, or was sent by a web page from another origin.
404Unknown endpoint.
500The action failed; the JSON body has an error message (for example a profile that does not exist, or a plan without RPA).
Automation endpoints are available on every plan. Running RPA flows (/api/rpa/*) requires the Pro plan; on other plans the request returns an error explaining that.