Local API Reference
Complete reference for the Local API built into the Antybrowser desktop app. Control profiles, proxies, groups and automations from any script — served from http://localhost:5173.
What is the Local API?
Unlike a typical SaaS API, nothing runs in the cloud: the desktop app itself hosts a REST server on your computer. That means low latency, no per-request billing, and full control — but you need the app running, and by default only programs on this computer can reach it.
Base URL
http://localhost:5173The port is configurable in Settings → API of the desktop app (default 5173). The API only answers on the machine running the desktop app unless you expose it — see the exposure guide below.
Authentication
Every request except GET /api/status requires your Local API key in the x-api-key header. The key is generated inside the desktop app — this website never issues or stores it.
curl -H 'x-api-key: YOUR_API_KEY' http://localhost:5173/api/profiles
Open the Antybrowser desktop app → Settings → API to generate and copy your key.
Quick start
Three calls to verify everything works. Replace YOUR_API_KEY with the key from the desktop app.
# 1. Check the API is running (no key needed) curl http://localhost:5173/api/status # {"success":true,"status":"connected","version":"1.4.2"} # 2. List your profiles curl -H 'x-api-key: YOUR_API_KEY' http://localhost:5173/api/profiles # 3. Start a profile and grab its debug port curl -X POST -H 'x-api-key: YOUR_API_KEY' http://localhost:5173/api/profiles/1/start # {"success":true,"data":{"debugPort":9222}}
Profiles
Create, launch, update and delete browser profiles — the core of the API.
/api/profilesList Profiles
List all profiles.
Example request
curl -X GET 'http://localhost:5173/api/profiles' \ -H 'x-api-key: YOUR_API_KEY'
Response
[ { "id": 784, "name": "My Profile", "directoryName": "6014b28f3a9c4d1e8b2a5c7d9e0f1a2b", "browserType": "Chrome", "osFingerprint": "Windows", "groupId": 12, "proxyId": 388, "status": "Ready", "screenResolution": "1920x1080", "screenMaximizable": false, "language": "en-US", "acceptLanguage": "Based on proxy", "timezone": "Based on proxy", "useFingerprint": true, "platformVersion": "15.0.0", "brandVersion": "155.0.8059.26", "gpuVendor": "auto", "hardwareConcurrency": "8", "deviceMemory": "8", "hidden": false, "trash": false, "needsSync": true, "lastSyncedAt": "2026-10-25T09:00:00.000Z", "createdAt": "2026-01-15T09:30:00.000Z", "updatedAt": "2026-01-15T09:30:00.000Z" } ]
| Field | Description |
|---|---|
| id | Numeric profile id used in every other endpoint. |
| directoryName | Local folder id (uuid) backing this profile. |
| status | Lifecycle status: "Ready", "Running", "Starting"… |
| groupId / proxyId | Assigned group/proxy ids, or null. Flat numbers — not nested objects. |
| browserType | Brand: Chrome, Edge, Opera, Vivaldi or Brave. |
| useFingerprint / platformVersion / brandVersion / gpuVendor … | The stored identity surface (only emitted while Fingerprint Protection is on). |
| hidden / trash | hidden is included in this list; trashed profiles are not. |
| fingerprintId | Server-owned noise seed. Read-only — never sent on create/update. |
/api/profiles/:idGet Profile
Get a single profile by ID.
Path parameters
| Field | Description |
|---|---|
| :id (number) | Required. Profile ID |
Example request
curl -X GET 'http://localhost:5173/api/profiles/<id>' \ -H 'x-api-key: YOUR_API_KEY'
Response
{ "id": 784, "name": "My Profile", "directoryName": "6014b28f3a9c4d1e8b2a5c7d9e0f1a2b", "browserType": "Chrome", "osFingerprint": "Windows", "status": "Ready", "debugPort": null, "lastPid": null, "language": "en-US", "timezone": "Based on proxy", "screenResolution": "1920x1080", "useFingerprint": true, "brandVersion": "155.0.8059.26", "trash": false, "hidden": false, "createdAt": "2026-01-15T09:30:00.000Z" }
| Field | Description |
|---|---|
| id | Profile id. |
| name | Display name. |
| status | Lifecycle status, e.g. "Ready" or "Running". |
| debugPort | Always null on the row — read the live port from the start response. |
| trash | true when the profile sits in Trash (a deleted paid-plan profile). |
/api/profilesCreate Profile
Create a new profile.
Request body
| Field | Type | Description | |
|---|---|---|---|
| name | string | required | Profile name |
| directoryName | string | optional | Local folder id (uuid). Generated if omitted |
| browserType | string | optional | Browser brandone of: Chrome, Edge, Opera, Vivaldi, Brave |
| browserVersion | string | optional | Pinned browser build (rarely used) |
| osFingerprint | string | optional | Platform identityone of: Windows, MacOS, Linux, Android, iPhone, Android Tablet, iPad |
| groupId | number | optional | Group ID |
| proxyId | number | optional | Proxy ID |
| notes | string | optional | Notes |
| startUrl | string | optional | URL to open on launch |
| customFlags | string | optional | Extra Chromium flags |
| status | string | optional | Initial status |
| hidden | boolean | optional | Hide from the list |
| language | string | optional | Browser language (e.g. en-US) |
| acceptLanguage | string | optional | Accept-Language header (default: based on proxy) |
| timezone | string | optional | Timezone ID or 'Based on proxy' |
| screenResolution | string | optional | Screen resolution (e.g. 1920x1080) |
| screenMaximizable | boolean | optional | Allow maximizing while reporting the spoofed screen |
| useFingerprint | boolean | optional | Enable fingerprint protection |
| platformVersion | string | optional | OS version (e.g. Windows 15.0.0) |
| brandVersion | string | optional | Browser version (e.g. Chrome 155.0.8059.26) |
| engineVersion | string | optional | Chromium version (derived from brandVersion) |
| gpuVendor | string | optional | GPU vendor (auto = this device's GPU)one of: auto, nvidia, amd, intel, qualcomm, arm, powervr, samsung |
| gpuModel | string | optional | GPU model |
| hardwareConcurrency | string | number | optional | CPU cores (empty = auto) |
| deviceMemory | string | number | optional | Device memory in GB (empty = auto) |
| deviceScaleFactor | string | number | optional | Device pixel ratio (empty = auto) |
| mobileModel | string | optional | Phone/tablet model |
| mobileVersion | string | optional | Android version (12-17) |
| chPlatform | string | optional | Sec-CH-UA platform |
| chPlatformVersion | string | optional | Sec-CH-UA platform version |
| chArch | string | optional | Sec-CH-UA architecture |
| chBitness | string | optional | Sec-CH-UA bitness |
| chModel | string | optional | Sec-CH-UA model |
| chMobile | string | number | optional | Sec-CH-UA-Mobile |
| disableSpoofing | string | optional | Spoof features to turn off (canvas,gpu,audio,clientrects,battery,netinfo,permissions) |
| locationMode | string | optional | Geolocation modeone of: , proxy, manual |
| locationLatitude | string | optional | Latitude (-90..90) |
| locationLongitude | string | optional | Longitude (-180..180) |
| locationAccuracy | string | optional | Accuracy in meters |
| webrtcMode | string | optional | WebRTC IP modeone of: proxy, manual, hidden, off |
| webrtcIp | string | optional | WebRTC IP for webrtcMode=manual (IPv4 or IPv6) |
| restoreSession | boolean | optional | Restore open tabs on startup |
| lowBandwidth | boolean | optional | Disable images and heavy resources |
{ "name": "My New Profile", "browserType": "Chrome", "osFingerprint": "Windows", "language": "en-US", "useFingerprint": true, "brandVersion": "155.0.8059.26", "screenResolution": "1920x1080" }
Example request
curl -X POST 'http://localhost:5173/api/profiles' \ -H 'x-api-key: YOUR_API_KEY' \ -H 'Content-Type: application/json' \ -d '{ "name": "My New Profile", "browserType": "Chrome", "osFingerprint": "Windows", "language": "en-US", "screenResolution": "1920x1080", "useFingerprint": true, "brandVersion": "155.0.8059.26" }'
Response
{ "id": 42, "name": "My New Profile", "directoryName": "b7a1c9d42e5f4a8b9c0d3e4f5a6b7c8d", "browserType": "Chrome", "osFingerprint": "Windows", "language": "en-US", "acceptLanguage": "Based on proxy", "timezone": "Based on proxy", "useFingerprint": true, "fingerprintId": "3ebc627d73f4501f", "brandVersion": "155.0.8059.26", "screenResolution": "1920x1080", "status": "Idle", "needsSync": true, "createdAt": "2026-01-15T09:30:00.000Z" }
| Field | Description |
|---|---|
| id | Newly created profile id — use it for start/update/extension calls. |
| directoryName | Echoed back, or generated (uuid) when you omitted it. |
| fingerprintId | Server-generated noise seed. Whatever you send is ignored. |
| acceptLanguage / timezone | Default to "Based on proxy" when omitted. |
| status | Initial status, usually "Idle". |
/api/profiles/:id/startStart Profile
Start a profile. Returns the debug port for Selenium/Puppeteer.
Path parameters
| Field | Description |
|---|---|
| :id (number) | Required. Profile ID |
Example request
curl -X POST 'http://localhost:5173/api/profiles/<id>/start' \ -H 'x-api-key: YOUR_API_KEY'
Response
{ "success": true, "data": { "debugPort": 52395 } }
| Field | Description |
|---|---|
| success | true when the browser process launched. |
| data.debugPort | Chrome DevTools port — attach Selenium/Puppeteer to it. Read it from HERE (the profile row's own debugPort stays null). |
/api/profiles/:id/stopStop Profile
Stop a running profile.
Path parameters
| Field | Description |
|---|---|
| :id (number) | Required. Profile ID |
Example request
curl -X POST 'http://localhost:5173/api/profiles/<id>/stop' \ -H 'x-api-key: YOUR_API_KEY'
Response
{ "success": true, "message": "Profile stop requested" }
| Field | Description |
|---|---|
| success | true when the stop was requested (idempotent — a non-running profile still succeeds). |
| message | Human-readable confirmation. |
/api/profiles/:id/duplicateDuplicate Profile
Duplicate a profile.
Path parameters
| Field | Description |
|---|---|
| :id (number) | Required. Profile ID |
Request body
| Field | Type | Description | |
|---|---|---|---|
| name | string | optional | Name for the copy (default: Copy of <source>) |
| directoryName | string | optional | Folder id for the copy (generated if omitted) |
{}Example request
curl -X POST 'http://localhost:5173/api/profiles/<id>/duplicate' \ -H 'x-api-key: YOUR_API_KEY'
Response
{ "id": 43, "name": "Copy of My Profile", "directoryName": "c3d4e5f67a8b4c9d8e0f1a2b3c4d5e6f", "browserType": "Chrome", "osFingerprint": "Windows", "status": "Idle", "createdAt": "2026-01-15T10:00:00.000Z" }
| Field | Description |
|---|---|
| id | Id of the new copy. |
| name | "Copy of <source>" unless you pass `name`. |
| directoryName | Fresh folder id for the copy. |
/api/profiles/:idUpdate Profile
Update a profile.
Path parameters
| Field | Description |
|---|---|
| :id (number) | Required. Profile ID |
Request body
| Field | Type | Description | |
|---|---|---|---|
| name | string | optional | New name |
| directoryName | string | optional | Local folder id (do not change) |
| browserType | string | optional | Browser brandone of: Chrome, Edge, Opera, Vivaldi, Brave |
| browserVersion | string | optional | Pinned browser build |
| osFingerprint | string | optional | Platform identityone of: Windows, MacOS, Linux, Android, iPhone, Android Tablet, iPad |
| groupId | number | optional | New group ID |
| proxyId | number | optional | New proxy ID |
| notes | string | optional | New notes |
| startUrl | string | optional | URL to open on launch |
| customFlags | string | optional | Extra Chromium flags |
| status | string | optional | Status override |
| hidden | boolean | optional | Hide from the list |
| language | string | optional | New language (e.g. en-US) |
| acceptLanguage | string | optional | New Accept-Language header |
| timezone | string | optional | New timezone |
| screenResolution | string | optional | New resolution (e.g. 1920x1080) |
| screenMaximizable | boolean | optional | Allow maximizing while reporting the spoofed screen |
| useFingerprint | boolean | optional | Enable fingerprint protection |
| platformVersion | string | optional | OS version |
| brandVersion | string | optional | Browser version |
| engineVersion | string | optional | Chromium version |
| gpuVendor | string | optional | GPU vendor (auto = this device's GPU)one of: auto, nvidia, amd, intel, qualcomm, arm, powervr, samsung |
| gpuModel | string | optional | GPU model |
| hardwareConcurrency | string | number | optional | CPU cores (empty = auto) |
| deviceMemory | string | number | optional | Device memory in GB (empty = auto) |
| deviceScaleFactor | string | number | optional | Device pixel ratio (empty = auto) |
| mobileModel | string | optional | Phone/tablet model |
| mobileVersion | string | optional | Android version |
| chPlatform | string | optional | Sec-CH-UA platform |
| chPlatformVersion | string | optional | Sec-CH-UA platform version |
| chArch | string | optional | Sec-CH-UA architecture |
| chBitness | string | optional | Sec-CH-UA bitness |
| chModel | string | optional | Sec-CH-UA model |
| chMobile | string | number | optional | Sec-CH-UA-Mobile |
| disableSpoofing | string | optional | Spoof features to turn off (canvas,gpu,audio,clientrects,battery,netinfo,permissions) |
| locationMode | string | optional | Geolocation modeone of: , proxy, manual |
| locationLatitude | string | optional | Latitude (-90..90) |
| locationLongitude | string | optional | Longitude (-180..180) |
| locationAccuracy | string | optional | Accuracy in meters |
| webrtcMode | string | optional | WebRTC IP modeone of: proxy, manual, hidden, off |
| webrtcIp | string | optional | WebRTC IP for webrtcMode=manual (IPv4 or IPv6) |
| restoreSession | boolean | optional | Restore open tabs on startup |
| lowBandwidth | boolean | optional | Disable images and heavy resources |
{ "name": "Updated Name", "notes": "Updated notes" }
Example request
curl -X PUT 'http://localhost:5173/api/profiles/<id>' \ -H 'x-api-key: YOUR_API_KEY' \ -H 'Content-Type: application/json' \ -d '{ "name": "Updated Name", "notes": "Updated notes" }'
Response
{ "id": 42, "name": "Updated Name", "notes": "Updated notes", "status": "Idle", "browserType": "Chrome", "updatedAt": "2026-01-15T10:05:00.000Z" }
| Field | Description |
|---|---|
| id | Profile id that was updated. |
| name / notes | New values are reflected in the returned full row. |
| fingerprintId | Server-owned; cannot be set through this endpoint. |
/api/profiles/:idDelete Profile
Delete a profile. Paid plans move it to Trash; free plans delete it.
Path parameters
| Field | Description |
|---|---|
| :id (number) | Required. Profile ID |
Example request
curl -X DELETE 'http://localhost:5173/api/profiles/<id>' \ -H 'x-api-key: YOUR_API_KEY'
Response
{ "success": true, "message": "Profile deleted" }
| Field | Description |
|---|---|
| success | true when the delete was accepted. |
| message | Confirmation. On paid plans the row is moved to Trash (recoverable); free plans delete permanently. The local folder stays on disk either way. |
Automations
Run your visual automations against a specific profile.
/api/automationsList Automations
List all automations.
Example request
curl -X GET 'http://localhost:5173/api/automations' \ -H 'x-api-key: YOUR_API_KEY'
Response
[ { "id": 7, "name": "Login Checker", "description": null, "detectedVariables": "[\"day\"]", "customVariables": "{}", "lastRun": null, "status": "idle", "createdAt": "2026-07-10T09:12:04.000Z", "updatedAt": "2026-07-10T07:12:10.000Z" } ]
| Field | Description |
|---|---|
| id | Automation id for the Run endpoint. |
| name / description | Automation label. |
| detectedVariables / customVariables | JSON strings (parse them). The heavy workflow nodes/edges are stripped here — fetch the full definition from the website API. |
| status | "idle", "running", "failed"… |
/api/automations/:id/runRun Automation
Run an automation on a profile.
Path parameters
| Field | Description |
|---|---|
| :id (number) | Required. Automation ID |
Request body
| Field | Type | Description | |
|---|---|---|---|
| profileId | number | required | Profile to run on |
| deleteCookies | boolean | optional | Delete cookies first |
| variables | object | optional | Custom variables |
{ "profileId": 1, "deleteCookies": false, "variables": { "MY_VAR": "some_value" } }
Example request
curl -X POST 'http://localhost:5173/api/automations/<id>/run' \ -H 'x-api-key: YOUR_API_KEY' \ -H 'Content-Type: application/json' \ -d '{ "profileId": 1, "deleteCookies": false, "variables": { "MY_VAR": "some_value" } }'
Response
{ "success": true, "message": "Automation completed", "variables": { "MY_VAR": "some_value" } }
| Field | Description |
|---|---|
| success | true when the run finished without throwing. |
| message | Human-readable result. |
| variables | Final variable map (input variables plus anything the run set). |
Proxies
Manage proxies with built-in connectivity checks and geo/ASN enrichment.
/api/proxiesList Proxies
List all proxies.
Example request
curl -X GET 'http://localhost:5173/api/proxies' \ -H 'x-api-key: YOUR_API_KEY'
Response
[ { "id": 775, "name": "46.16.131.48", "host": "proxy.packetstream.io", "port": 31111, "type": "https", "username": "user", "password": "pass", "status": "active", "lastCheckAt": "2026-10-25T16:44:26.000Z", "ip": "46.16.131.48", "country": "Ireland", "countryCode": "IE", "city": "Dublin", "region": "Dublin", "isp": "BrainStorm Network, Inc", "asn": "AS136258 BrainStorm Network, Inc", "timezone": "Europe/Dublin", "errorMessage": null, "exitOs": "Linux", "exitOsConfidence": "high", "ipChangeCount": 0 } ]
| Field | Description |
|---|---|
| id | Proxy id for get/update/delete endpoints. |
| type | "http" | "https" | "socks4" | "socks5". |
| status | "active" after a successful check; "inactive" when unreachable. |
| ip / country / isp / asn | Auto-enriched geo/ASN data from the last check. |
| exitOs / exitOsConfidence | OS family the exit's TCP/IP stack looks like (from the exit probe), or null. |
| errorMessage | Last failure reason, or null. |
/api/proxies/:idGet Proxy
Get a single proxy by ID.
Path parameters
| Field | Description |
|---|---|
| :id (number) | Required. Proxy ID |
Example request
curl -X GET 'http://localhost:5173/api/proxies/<id>' \ -H 'x-api-key: YOUR_API_KEY'
Response
{ "id": 775, "name": "46.16.131.48", "host": "proxy.packetstream.io", "port": 31111, "type": "https", "username": "user", "password": "pass", "status": "active", "exitOs": "Linux" }
| Field | Description |
|---|---|
| host / port / type | Connection details you originally submitted. |
| status | Last known health, e.g. "active". |
/api/proxiesCreate Proxy
Add a proxy. The connection is checked before saving.
Request body
| Field | Type | Description | |
|---|---|---|---|
| name | string | required | Proxy name |
| host | string | required | Proxy host/IP |
| port | number | required | Proxy port |
| username | string | optional | Username |
| password | string | optional | Password |
| type | string | optional | Proxy type (detected if omitted)one of: http, https, socks4, socks5 |
{ "name": "US Proxy 1", "host": "192.168.1.1", "port": 8080, "username": "user", "password": "pass", "type": "http" }
Example request
curl -X POST 'http://localhost:5173/api/proxies' \ -H 'x-api-key: YOUR_API_KEY' \ -H 'Content-Type: application/json' \ -d '{ "name": "US Proxy 1", "host": "192.168.1.1", "port": 8080, "username": "user", "password": "pass", "type": "http" }'
Response
{ "id": 4, "name": "US Proxy 1", "host": "203.0.113.7", "port": 8080, "username": "user", "password": "pass", "type": "http", "status": "active", "ip": "203.0.113.7", "country": "United States", "countryCode": "US", "city": "New York", "region": "New York", "isp": "Example ISP", "timezone": "America/New_York", "asn": "AS64500 Example Network", "lastCheckAt": "2026-01-15T09:45:00.000Z" }
| Field | Description |
|---|---|
| id | New proxy id. |
| status | Always "active" — the connection was validated before saving. |
| ip/country/city/isp/asn | Geo/ASN auto-enriched from the connectivity check. |
/api/proxies/:idUpdate Proxy
Update a proxy.
Path parameters
| Field | Description |
|---|---|
| :id (number) | Required. Proxy ID |
Request body
| Field | Type | Description | |
|---|---|---|---|
| name | string | optional | Proxy name |
| host | string | optional | Proxy host/IP |
| port | number | optional | Proxy port |
| username | string | optional | Username |
| password | string | optional | Password |
| type | string | optional | Proxy typeone of: http, https, socks4, socks5 |
{ "name": "Updated Proxy" }
Example request
curl -X PUT 'http://localhost:5173/api/proxies/<id>' \ -H 'x-api-key: YOUR_API_KEY' \ -H 'Content-Type: application/json' \ -d '{ "name": "Updated Proxy" }'
Response
{ "id": 4, "name": "Updated Proxy", "host": "203.0.113.7", "port": 8080, "type": "http", "status": "active" }
| Field | Description |
|---|---|
| id | Proxy id that was updated. |
| … | Only the fields you sent are changed; the full object is returned. No re-validation runs. |
/api/proxies/:idDelete Proxy
Delete a proxy.
Path parameters
| Field | Description |
|---|---|
| :id (number) | Required. Proxy ID |
Example request
curl -X DELETE 'http://localhost:5173/api/proxies/<id>' \ -H 'x-api-key: YOUR_API_KEY'
Response
HTTP/1.1 204 No Content
| Field | Description |
|---|---|
| (no body) | A successful delete returns 204 with an empty body — there is no JSON payload. |
Extensions
List and remove uploaded extensions (uploading stays a UI action).
/api/extensionsList Extensions
List all extensions.
Example request
curl -X GET 'http://localhost:5173/api/extensions' \ -H 'x-api-key: YOUR_API_KEY'
Response
[ { "id": 23, "type": "url", "name": "User-Agent Switcher and Manager", "description": null, "version": "0.6.7", "guid": "8ff39855-0284-43eb-a545-b32ab5a238ae", "source": "https://chromewebstore.google.com/detail/…", "s3Key": null, "localPath": "C:\\Users\\you\\AppData\\Local\\Antybrowser\\Extensions\\bhchdcejhohfmigjafbampogmaanbfkg", "iconUrl": "/api/extensions/23/icon", "size": 5762668, "synced": false, "needsSync": false } ]
| Field | Description |
|---|---|
| id | Extension id used when assigning to profiles. |
| guid | Chrome Web Store id (or an internal GUID for sideloaded zips). |
| localPath | Machine-specific absolute path on the machine that installed it — never use it verbatim on another OS. |
| s3Key | Cloud storage key of the uploaded archive. |
/api/extensions/:idDelete Extension
Delete an extension.
Path parameters
| Field | Description |
|---|---|
| :id (number) | Required. Extension ID |
Example request
curl -X DELETE 'http://localhost:5173/api/extensions/<id>' \ -H 'x-api-key: YOUR_API_KEY'
Response
HTTP/1.1 204 No Content
| Field | Description |
|---|---|
| (no body) | A successful delete returns 204 with an empty body. |
Groups
Organize profiles into groups.
/api/groupsList Groups
List all groups.
Example request
curl -X GET 'http://localhost:5173/api/groups' \ -H 'x-api-key: YOUR_API_KEY'
Response
[ { "id": 7, "name": "Ebay", "description": "", "color": "blue", "displayOrder": 0 } ]
| Field | Description |
|---|---|
| id | Group id — pass as `groupId` when creating/updating profiles. |
| color | "blue" | "red" | "green" | "yellow" | "purple" | "gray". |
| displayOrder | Sort position in the sidebar. |
/api/groupsCreate Group
Create a group.
Request body
| Field | Type | Description | |
|---|---|---|---|
| name | string | required | Group name |
| description | string | optional | Group description |
| color | string | optional | Colorone of: blue, red, green, yellow, purple, gray |
{ "name": "My Group", "description": "", "color": "blue" }
Example request
curl -X POST 'http://localhost:5173/api/groups' \ -H 'x-api-key: YOUR_API_KEY' \ -H 'Content-Type: application/json' \ -d '{ "name": "My Group", "color": "blue" }'
Response
{ "id": 3, "name": "My Group", "description": "", "color": "blue", "displayOrder": 0 }
| Field | Description |
|---|---|
| id | New group id. |
| color | Defaults to "blue" when omitted. |
/api/groups/:idUpdate Group
Update a group.
Path parameters
| Field | Description |
|---|---|
| :id (number) | Required. Group ID |
Request body
| Field | Type | Description | |
|---|---|---|---|
| name | string | optional | Group name |
| description | string | optional | Group description |
| color | string | optional | Colorone of: blue, red, green, yellow, purple, gray |
{ "name": "Updated Name", "color": "red" }
Example request
curl -X PUT 'http://localhost:5173/api/groups/<id>' \ -H 'x-api-key: YOUR_API_KEY' \ -H 'Content-Type: application/json' \ -d '{ "name": "Updated Name", "color": "red" }'
Response
{ "id": 3, "name": "Updated Name", "description": "", "color": "red", "displayOrder": 0 }
| Field | Description |
|---|---|
| id | Group id that was updated. |
| … | Only the fields you sent are changed; the full object is returned. |
/api/groups/:idDelete Group
Delete a group.
Path parameters
| Field | Description |
|---|---|
| :id (number) | Required. Group ID |
Example request
curl -X DELETE 'http://localhost:5173/api/groups/<id>' \ -H 'x-api-key: YOUR_API_KEY'
Response
{ "success": true, "message": "Group deleted" }
| Field | Description |
|---|---|
| success | true when the group was removed (profiles in the group are kept). |
Exposing the Local API
The API runs on your machine, so reaching it from another device (or the internet) takes extra steps. Four routes, from easiest to most robust:
By default the Local API binds to 127.0.0.1 only — firewall rules and router port-forwarding alone can't reach it, because nothing is listening on the network interface. Exposing it always starts with the desktop app binding to 0.0.0.0.
the app's “Expose on network” toggle (LAN)
By default the Local API only listens on 127.0.0.1, so no firewall or router setting can reach it — the app itself must rebind to 0.0.0.0 first. The desktop app does both steps together.
- 1
Enable the toggle
In the desktop app open Settings → API and turn on “Expose on network”. The server restarts listening on 0.0.0.0 instead of 127.0.0.1.
- 2
Approve the firewall prompt
The app adds an inbound rule for the API port automatically. On Windows this raises a UAC prompt; approve it. If the prompt fails or you decline, the app shows a dialog with the exact manual commands for your OS.
# Windows (elevated PowerShell) — what the app runs for you netsh advfirewall firewall add rule name="Antybrowser Local API" dir=in action=allow protocol=TCP localport=5173
- 3
Reach it from other devices on your network
Use your computer's LAN IP instead of localhost — e.g. http://192.168.1.42:5173. The API page in the app shows this address.
router port forwarding (internet access)
Opening the port in the OS firewall only allows traffic through your machine — to reach it from outside your network you must also forward a port on your router to that machine.
- 1
Give your machine a stable LAN address
Either reserve a DHCP address for the machine in your router, or set a static LAN IP (e.g. 192.168.1.42). Port forwarding breaks whenever the target's LAN IP changes.
- 2
Forward the port
Log into your router admin page (usually http://192.168.1.1 or http://192.168.0.1), find “Port forwarding” (sometimes under NAT / Advanced), and create a rule: external port 5173 → your machine's LAN IP, protocol TCP. Your ISP may also block inbound ports — a business/static plan usually allows them.
- 3
Point clients at your public IP
Call http://YOUR_PUBLIC_IP:5173 from anywhere. Home IPs change, so pair this with DDNS (router-supported or a client like ddclient) if you need a stable hostname.
- 4
Only expose the port you configured
Keep the API on its default port 5173 (or any port you choose in Settings → API) and forward exactly that one. Never forward broad port ranges to this machine.
a tunnel (no router config, quick test)
A tunnel gives you a public HTTPS URL that forwards to localhost — no firewall or router changes at all, which makes it the easiest way to test from another device.
- 1
Pick a tunnel and run it on the API machine
ngrok, cloudflared, localtunnel and similar tools all work. Example with ngrok:
ngrok http 5173
- 2
Use the generated URL
The tool prints a public URL (e.g. https://a1b2-c3d4.ngrok-free.app). Requests to that URL are forwarded to http://localhost:5173 on your machine — the x-api-key header still applies.
- 3
Mind the caveat
Free tunnels show interstitial pages, change URLs on restart, and put your API behind someone else's domain. Fine for testing — for production-like use, prefer Option D.
a VPS / dedicated server (by far the easiest for always-on)
If you actually want a stable public endpoint, hosting the API on a server is dramatically simpler than exposing your personal computer: the machine already has a public IP, no port forwarding exists to break, and firewall rules are a single command.
- 1
Run the API where the public IP already is
A small VPS (even 1 vCPU / 1 GB) gets you a static public IP and no NAT. Point your automation at it instead of opening ports on your home network.
- 2
Open the port with one command
On the server, allow only the API port — no UAC dialogs, no home-router UI:
# Ubuntu/Debian (ufw) sudo ufw allow 5173/tcp # RHEL/Fedora (firewalld) sudo firewall-cmd --permanent --add-port=5173/tcp && sudo firewall-cmd --reload
- 3
Put it behind HTTPS
Terminate TLS with nginx/Caddy in front of the API, or use your panel's firewall + a domain. Unlike home setups, TLS here is a one-time config, not a project.
- 4
Add an SSH tunnel as a zero-exposure alternative
If you don't need a public endpoint at all, keep the server's port closed and tunnel to it on demand:
ssh -N -L 5173:127.0.0.1:5173 user@your-vps # then call http://localhost:5173 locally
Whatever route you choose: the x-api-key header is the only thing standing between the internet and control of your browser profiles. Never forward the port without that key, prefer a tunnel/HTTPS for anything beyond your own LAN, and turn “Expose on network” back off when you're done.
Runs locally, no rate limits
All requests are served by the desktop app on your own machine — there is no cloud endpoint, no rate limit, and no data leaves your computer unless the operation itself (e.g. profile sync) requires it. A Cloud, Developer, Agency, or Enterprise plan is required for API access.