Aurorium Local API v1

The Local API allows scripts running on your computer to manage Aurorium profiles, browser sessions, folders, proxies, and cookies. The server starts with the desktop application and is available only on the same computer.

#Quick start

  1. Start Aurorium and sign in to your account.
  2. Open Automation → API and generate an API key.
  3. Save the key immediately: the backend displays it only once.
  4. Send the key with every request using Authorization: Bearer <api_key>.
bash
curl "http://127.0.0.1:50325/api/v1/health" \
  -H "Authorization: Bearer $AURORIUM_API_KEY"

Base URL:

text
http://127.0.0.1:50325/api/v1

The server listens on 127.0.0.1 only, not on an external network interface. The current fixed port is 50325.

#Response format

Successful results and application errors use the same response envelope:

json
{
  "code": 0,
  "msg": "success",
  "data": {},
  "request_id": "req_0d30b83f3fbb43e6a2e1b255e21d24b8"
}
  • code = 0 means success.
  • code != 0 means an application error; checking only the HTTP status is not sufficient.
  • Store request_id in your integration logs for diagnostics.
  • The server usually returns HTTP 200 even for an application error.
  • If the JSON body exceeds 5 MiB, the API returns code: 1001 and msg: "request body too large".

Error example:

json
{
  "code": 1201,
  "msg": "profile not found",
  "data": null,
  "request_id": "req_7f3ab37ea65048f99ebd0fdbe6f4da63"
}

#Common parameters

List endpoints accept:

ParameterDefaultLimit
page1minimum 1
page_size50maximum 200; larger values are capped at 200

List response data format:

json
{
  "list": [],
  "page": 1,
  "page_size": 50,
  "total": 0
}

#Endpoint overview

MethodPathPurpose
GET/healthApplication and cloud connection readiness
GET/versionApplication and API versions
GET/profileList non-archived profiles
POST/profileCreate a profile
GET/profile/:idGet profile details
PATCH/profile/:idPartially update a profile
DELETE/profile/:idDelete a profile
GET/folderList folders
POST/folderCreate a folder
PUT/folder/:idRename a folder
DELETE/folder/:idDelete a folder
GET/browser/statusGet profile launch status
GET/browser/activeList running profiles
POST/browser/startStart a profile with CDP
POST/browser/stopStop a profile
POST/browser/stop-allStop local profiles
POST/proxy/checkCheck a proxy
PUT/profile/:id/proxyReplace a profile proxy
GET/profile/:id/cookiesExport cookies
POST/profile/:id/cookies/importImport cookies
GET/deviceList account devices
GET/catalogGet allowed fingerprint values

#System

#GET /health

Returns local application readiness, cloud connection state, and the current device ID.

json
{
  "ready": true,
  "cloud_connected": true,
  "device_id": "device-id-or-null"
}

Authentication is required even for the health check.

#GET /version

json
{
  "app_version": "0.3.1",
  "core_version": null,
  "api_version": "v1"
}

core_version is not implemented yet and always returns null.

#Profiles

#GET /profile

Query parameters:

ParameterValuesDescription
folder_idObjectIdFilter by folder
namestringSearch by name
statusall, running, idleDefaults to all
page, page_sizeintegerPagination

List item:

json
{
  "profile_id": "507f1f77bcf86cd799439011",
  "name": "Automation profile",
  "folder_id": null,
  "status": "idle",
  "location": null,
  "os": "windows",
  "os_version": "Windows 11",
  "core": "chrome",
  "core_version": "134",
  "description": "",
  "created_at": "2026-07-24T10:00:00Z",
  "updated_at": "2026-07-24T10:00:00Z"
}

Archived profiles are not returned. The running|idle filter is applied on the client only after the page has been loaded, so total and the number of items on the page may not match the filtered list.

#POST /profile

Minimal request:

json
{
  "name": "Automation profile"
}

Supported fields:

FieldTypeRequiredNotes
namestringyesNon-empty name
descriptionstringnoDefaults to ""
folder_idstring or nullnoMongo ObjectId; null means no folder
tagsarraynoDefaults to []
osstringnowindows, macos, linux
os_versionstringnoOS version hint for fingerprint generation, such as "11" or "Tahoe"; see /catalog for recommended values
is_armbooleannoARM hint; inferred from the GPU vendor when omitted
proxyobjectnoInline proxy in the format below
proxy_idstringnoExisting proxy reference; proxy takes precedence
launch_argumentsstringnoLaunch arguments as one string
start_pagestringnoStart page
fingerprintobjectnoPartial fingerprint overrides

Example with a proxy:

json
{
  "name": "Profile with proxy",
  "os": "windows",
  "proxy": {
    "type": "socks5",
    "host": "127.0.0.1",
    "port": 1080,
    "user": "login",
    "password": "secret"
  }
}

Profile creation is asynchronous on the backend. The Local API waits for the completion event and normally returns the complete profile model. If the follow-up read fails, only profile_id may be returned.

#GET /profile/:id

Returns a list item with additional proxy and fingerprint objects. A proxy password is never returned as plain text; when present, it is replaced with ******.

#PATCH /profile/:id

Partially updates a profile:

json
{
  "name": "New name",
  "description": "Updated through API",
  "folder_id": null,
  "fingerprint": {
    "timezone_mode": "manual",
    "timezone": "Europe/Moscow"
  }
}

An empty body is a successful no-op. Metadata is applied immediately. Fingerprint changes are applied immediately when the profile is stopped; for a running profile they are deferred until the next launch and listed in deferred_fields.

json
{
  "profile_id": "507f1f77bcf86cd799439011",
  "deferred_fields": ["fingerprint.timezone_mode", "fingerprint.timezone"]
}

For a stopped profile, deferred_fields is always empty.

#DELETE /profile/:id

The force=true query stops a profile running on the current device before deletion. Without force, such a profile returns 1203.

json
{
  "profile_id": "507f1f77bcf86cd799439011",
  "deleted": true
}

Deletion is idempotent for a syntactically valid ObjectId: a backend “not found” response is currently treated as an already deleted profile.

#Fingerprint

The fingerprint object in POST and PATCH supports partial updates to these fields:

FieldType or values
timezone_modeauto, manual
timezonestring or null
language_modeauto, manual
languagesstring[]; the first item is used
languagestring; shorthand alternative
screen_resolutionstring
webrtc_modereal, replace
canvas_noiseboolean
webgl_image_noiseboolean
webgl_vendorstring or null
webgl_rendererstring or null
audio_noiseboolean
client_rects_noiseboolean
hardware_concurrencynumber
device_memorynumber
do_not_trackdefault, true
os_versionstring
dns_modereal, manual
dns_serverstring or null
geolocation{mode, latitude, longitude, accuracy}
media_devices{audio_inputs, audio_outputs, video_inputs}

Use /catalog to retrieve compatible OS, GPU, CPU, RAM, screen, timezone, and language values.

#Folders

#GET /folder

Supports name, page, and page_size.

json
{
  "folder_id": "507f1f77bcf86cd799439012",
  "name": "QA",
  "profile_count": 3,
  "system": false
}

#POST /folder

json
{ "name": "QA" }

#PUT /folder/:id

json
{ "name": "QA automation" }

#DELETE /folder/:id

Profiles are not deleted with a folder. The backend moves team profiles to the system folder and personal profiles to the no-folder state.

json
{
  "folder_id": "507f1f77bcf86cd799439012",
  "deleted": true,
  "moved_profiles": 3,
  "moved_to": null
}

moved_profiles and moved_to are calculated before deletion on a best-effort basis and may be inaccurate when cloud state cannot be read.

#Browser lifecycle

#GET /browser/status?profile_id=:id

Returns idle or running, the launch device, and locally available process coordinates.

#GET /browser/active

The scope query accepts:

  • this_device — profiles running locally; the default;
  • account — profiles running across all account devices according to the cloud registry.

Standard pagination is supported.

#POST /browser/start

json
{
  "profile_id": "507f1f77bcf86cd799439011",
  "headless": false,
  "open_urls": ["https://example.com"],
  "launch_args": ["--window-size=1280,800"],
  "load_extensions": true
}

Successful response:

json
{
  "profile_id": "507f1f77bcf86cd799439011",
  "already_running": false,
  "debug_port": 51432,
  "ws": "ws://127.0.0.1:51432/devtools/browser/...",
  "webdriver": null,
  "pid": 12345,
  "lease": {
    "device_id": "device-id",
    "device_name": "Workstation",
    "is_current_device": true
  }
}

Starting a profile again on the current device is idempotent. A profile running on another device returns 1204. If the required browser core is missing or downloading, the Local API returns 1304; this method does not download it automatically.

#POST /browser/stop

json
{ "profile_id": "507f1f77bcf86cd799439011" }

Stopping is idempotent and returns was_running.

#POST /browser/stop-all

Stops every profile on the current device:

json
{
  "stopped": ["507f1f77bcf86cd799439011"],
  "count": 1
}

#Proxy

Inline proxy format:

FieldTypeNotes
typestringhttp, socks4, socks5, ssh, no_proxy
hoststringRequired except for no_proxy
portinteger/string1..65535, except for no_proxy
userstringOptional
passwordstringOptional
refresh_urlstringOptional

#POST /proxy/check

Provide exactly one source: proxy or profile_id.

json
{
  "proxy": {
    "type": "http",
    "host": "proxy.example.com",
    "port": 8080
  }
}
json
{
  "ok": true,
  "exit_ip": "203.0.113.10",
  "country": "DE",
  "city": "Frankfurt",
  "latitude": 50.11,
  "longitude": 8.68,
  "timezone": null,
  "latency_ms": null
}

#PUT /profile/:id/proxy

The body is the proxy object itself, without a proxy wrapper:

json
{
  "type": "no_proxy"
}

For a running profile, the change is deferred until the next launch and the response contains deferred_fields: ["proxy"].

#Cookies

A cookie uses a flat format:

json
{
  "domain": ".example.com",
  "name": "session",
  "value": "value",
  "path": "/",
  "expires": 1790000000,
  "http_only": true,
  "secure": true,
  "same_site": "lax"
}

expires is Unix time in seconds; 0 or null means a session cookie. same_site accepts unspecified, no_restriction, lax, or strict.

#GET /profile/:id/cookies

Reads the local Chromium SQLite database first and falls back to cookies stored in the cloud when it is unavailable.

#POST /profile/:id/cookies/import

json
{
  "clear": true,
  "cookies": [
    {
      "domain": ".example.com",
      "name": "session",
      "value": "value"
    }
  ]
}
  • clear=true replaces cookies and is the default;
  • clear=false merges them with the existing cloud copy;
  • the profile must be stopped on every device;
  • every accepted cookie must include at least domain and name.

#Devices

#GET /device

Returns a paginated list:

json
{
  "device_id": "device-id",
  "device_name": "Workstation",
  "platform": "windows",
  "is_current_device": true,
  "online": true,
  "last_seen": "2026-07-24T10:00:00Z",
  "running_profiles": 1,
  "running_profile_ids": ["507f1f77bcf86cd799439011"]
}

#Catalog

#GET /catalog

Returns allowed fingerprint values and GPU → CPU/RAM/screen dependencies. Use os=windows|macos|linux to limit the result to one operating system.

The catalog depends on the cloud and returns 1701 when the cloud is unavailable.

#Error codes

CodeMeaning
0Success
1001Invalid JSON or request body too large
1002Unknown endpoint or HTTP method
1003Missing or invalid API key
1101Required parameter is missing
1103Invalid parameter value or format
1201Profile not found
1202Profile is archived
1203Profile is running on this device
1204Profile is running on another device
1301Browser core failed to start
1304Browser core is missing or downloading
1401Invalid proxy configuration
1402Proxy check failed
1501Folder not found
1503A system folder cannot be deleted
1601Invalid cookie format
1602Cookies cannot be imported into a running profile
1701Cloud is unavailable
1901Internal error

#Minimal JavaScript example

js
const baseUrl = "http://127.0.0.1:50325/api/v1";
const token = process.env.AURORIUM_API_KEY;

async function aurorium(path, options = {}) {
  const response = await fetch(`${baseUrl}${path}`, {
    ...options,
    headers: {
      Authorization: `Bearer ${token}`,
      "Content-Type": "application/json",
      ...options.headers,
    },
  });
  const result = await response.json();
  if (result.code !== 0) {
    throw new Error(`[${result.code}] ${result.msg}; ${result.request_id}`);
  }
  return result.data;
}

const profiles = await aurorium("/profile?page_size=10");
console.log(profiles.list);

#Compatibility

  • The API version is included in the URL: /api/v1.
  • Numeric error codes are stable within a major API version.
  • Clients should ignore unknown fields because optional response fields may be added without breaking compatibility.
  • Breaking changes require a new major URL such as /api/v2, or an explicitly agreed migration period.