PersonaHub Automation API
Use PersonaHub's local HTTP API to manage profiles, proxies, fingerprints, and website credentials, then launch browsers and connect over CDP for web automation.
The PersonaHub automation API lets you create and manage profiles, configure proxies and fingerprints, manage saved website credentials, and launch or close profile browsers.
Reading pages, clicking, typing, and taking screenshots require CDP or a compatible automation tool after the browser starts.
1. Before you start
- Open the PersonaHub desktop app and sign in.
- Enable the API in the app's automation settings, copy the API key, and check the port.
- Make sure the browser engine is ready before launching a profile.
- Keep the app running, signed in, and connected to the internet while using the API.
The API can only access the signed-in account's profiles. Profile creation is subject to the account's quota.
| Setting | Default |
|---|---|
| HTTP base URL | http://127.0.0.1:43110 |
| Automation server | Disabled |
| Listen address | 127.0.0.1; changes to 0.0.0.0 when remote access is enabled |
| Port range | 1–65535, configurable in settings |
For remote access, replace 127.0.0.1 with the address of the computer running PersonaHub. Browsers, debugging ports, and returned file paths belong to that computer.
2. Conventions
2.1 Authentication
Every request except GET /health requires:
Authorization: Bearer <API_KEY>For requests with a body, also send:
Content-Type: application/jsonThe API key does not replace account sign-in or grant additional account permissions.
2.2 Requests and responses
- Request bodies must be JSON objects, not arrays, strings, or
null. - Request bodies are limited to 256 KiB. An oversized request may have its connection closed directly.
- All successful endpoints listed here return
200, including creation and deletion. - Responses use JSON and include
Cache-Control: no-store. - Profile and credential path IDs are UUIDs. Invalid path IDs return
404. - Replace
:id,:passwordId,:otpId, and:passkeyIdwith actual IDs. - List endpoints do not support pagination parameters.
PATCHpreserves omitted fields; nested-field rules are described below. Do not usenullin place of an omitted field.
Error response:
{
"error": "Error description",
"code": "not_found"
}Handle errors using the HTTP status and code, not the wording or language of error.
3. Quick start
These commands use Bash/zsh syntax. Replace the API key and the UUID of an existing profile before running them.
export PERSONA_API_BASE='http://127.0.0.1:43110'
export PERSONA_API_KEY='<API_KEY>'
curl -sS "$PERSONA_API_BASE/health"
curl -sS "$PERSONA_API_BASE/v1/engine" \
-H "Authorization: Bearer $PERSONA_API_KEY"
curl -sS "$PERSONA_API_BASE/v1/profiles" \
-H "Authorization: Bearer $PERSONA_API_KEY"
export PROFILE_ID='<PROFILE_UUID>'
curl -sS -X POST "$PERSONA_API_BASE/v1/profiles/$PROFILE_ID/launch" \
-H "Authorization: Bearer $PERSONA_API_KEY" \
-H 'Content-Type: application/json' \
-d '{"startupUrl":"https://example.com","extraArgs":["--remote-debugging-port=9222"]}'A successful launch returns:
{"ok": true}This confirms browser startup, not that a page, website login, or CDP endpoint is ready. Once the debugging port is available, query it with:
curl -sS http://127.0.0.1:9222/json/versionConnect using the returned webSocketDebuggerUrl, or the CDP HTTP address if your automation tool supports it. Port 43110 is the automation API port; 9222 is the example browser debugging port. Assign different debugging ports when enabling CDP for multiple profiles at once.
Close the browser started through the API:
curl -sS -X POST "$PERSONA_API_BASE/v1/profiles/$PROFILE_ID/close" \
-H "Authorization: Bearer $PERSONA_API_KEY"4. Service status and account entitlements
| Method | Path | Purpose | Success response |
|---|---|---|---|
| GET | /health | Server health; no authentication required | { "ok": true } |
| GET | /v1/engine | Browser engine status | { "ready": true, "version": "..." } |
| GET | /v1/account/entitlements | Current account entitlements | { "entitlements": {...} } |
A successful /health response does not confirm account sign-in or engine readiness. The version returned by /v1/engine is the browser engine version, not the app version, and is an empty string when unavailable. ready does not indicate that a profile has launched or that CDP is available.
The entitlements object contains:
| Field | Type | Description |
|---|---|---|
tier | string | Plan identifier |
maxProfiles | number | Profile limit |
usedProfiles | number | Profiles currently counted toward the limit |
renewsAt | string or null | Renewal time |
cancelAt | string or null | Cancellation time |
status | string or null | Subscription status |
5. Profiles
| Method | Path | Purpose | Success response |
|---|---|---|---|
| GET | /v1/profiles | List profiles | { "profiles": [...] } |
| POST | /v1/profiles | Create a profile | { "profile": {...} } |
| GET | /v1/profiles/:id | Get profile details | { "profile": {...} } |
| PATCH | /v1/profiles/:id | Update a profile | { "profile": {...} } |
| DELETE | /v1/profiles/:id | Delete a profile and its corresponding local data and cache | { "ok": true } |
5.1 Create and update fields
| Field | Type | Required on creation | Description |
|---|---|---|---|
name | string | Yes | Nonempty after trimming; up to 120 characters |
startupUrl | string | No | Default startup URL; HTTP/HTTPS, up to 2048 characters; an empty string leaves it unset |
extraArgs | string | No | Saved launch arguments, separated by whitespace; up to 4096 characters; defaults to an empty string |
proxy | object | No | Profile proxy settings, described below |
fingerprint | object | No | Fingerprint settings, described below |
proxyIpInfo | object | No | Known proxy exit information; skips automatic detection |
acceptProxyChain | boolean | No | Whether to accept the app's configured proxy chain; defaults to true |
appearanceLabel | string | No | Browser appearance label |
appearanceBackgroundColor | string | No | Appearance background color, such as #2563EB |
appearanceForegroundColor | string | No | Appearance foreground color, such as #FFFFFF |
Minimal creation body:
{"name": "Automation profile"}Omitted settings use defaults on creation. Updates to proxy and fingerprint change only the supplied subfields. Proxy detection may affect the timezone, as described in section 5.4.
Example partial update:
PATCH /v1/profiles/:id{
"name": "Automation profile A",
"startupUrl": "https://example.com",
"extraArgs": "--remote-debugging-port=9222"
}Here, extraArgs is a string, unlike the string array used by the launch endpoints. Saved arguments do not support shell-style quoting; pass an argument containing spaces as one item in the launch endpoint's extraArgs array. Set startupUrl or extraArgs to an empty string in an update to clear its saved value.
5.2 Proxy settings
Configure the proxy in the profile's proxy field.
| Field | Type | Creation default | Description |
|---|---|---|---|
protocol | string | socks5 | http, https, or socks5 |
host | string | "" | Proxy hostname or IP; an empty string means no profile-specific proxy |
port | number | 1080 | Integer from 1 to 65535 |
username | string | "" | Proxy authentication username |
password | string | "" | Proxy authentication password |
bypassList | string | localhost;127.0.0.1 | Proxy bypass rules separated by semicolons |
{
"name": "US profile",
"proxy": {
"protocol": "socks5",
"host": "proxy.example.com",
"port": 1080,
"username": "<PROXY_USERNAME>",
"password": "<PROXY_PASSWORD>"
}
}Leaving the profile-specific proxy unset does not force a direct connection. App proxy-chain or system proxy settings may still affect the connection.
5.3 Fingerprint settings
| Field | Type | Creation default | Description |
|---|---|---|---|
browserVersion | string | "" | Reported version, up to 32 characters; empty or auto selects the highest available version matching the engine's major version |
hardwareConcurrency | number | Random | CPU thread count; integer from 1 to 256 |
cpuPerformance | number | From random preset | CPU performance tier; integer from 0 to 4 |
deviceMemory | number | Random | Reported memory: 2, 4, 8, 16, or 32 GB; does not allocate physical memory |
speechVoicesMode | string | override | none: no override; override: full override; append_google: append Google voices only |
fontAllowlistOverride | boolean | true | Apply the preset font allowlist for the host system |
disableCanvasNoise | boolean | false | Disable pixel noise in Canvas 2D readback and image exports; noise stays enabled by default. Does not affect WebGL, WebGPU, or other noise. Relaunch after changes |
webrtcIpPolicy | string | disable_non_proxied_udp | WebRTC IP policy |
timezone | string | America/New_York | IANA timezone; proxy detection may supply a default timezone |
acceptLanguages | string | en-US,en | Comma-separated language list |
Each creation randomly selects 8/12/16/20/24/32 CPU threads and 16/32 GB of memory. The random preset uses performance tier 3 for 8 threads and 4 otherwise. Explicit fields override the corresponding preset values. Updates preserve omitted fields, and launches do not randomize them again.
cpuPerformance tiers: 0 = Unknown, 1 = Low, 2 = Mid, 3 = High, 4 = Ultra.
Supported webrtcIpPolicy values:
disable_non_proxied_udpdefault_public_interface_onlydefault_public_and_private_interfacesdefault
UDP-enabled modes may expose direct IP addresses instead of the node IP. Close and relaunch the browser after changes.
5.4 Proxy exit information
When a proxy is configured without exit information, the API detects it automatically. A failed check returns proxy_probe_failed.
If you already have detection results, provide proxyIpInfo:
| Field | Type | Required | Description |
|---|---|---|---|
ip | string | Yes | Nonempty proxy exit IP |
country | string | No | Two-letter country or region code, such as US |
region, city | string | No | Region and city |
timezone | string | No | IANA timezone |
latitude, longitude | number | No | Coordinates |
asn, org | string | No | ASN and network organization |
- If the request does not explicitly provide a nonempty
fingerprint.timezoneand the detected or supplied exit information includes a timezone, that timezone is used. - Automatic detection does not change
acceptLanguages. Supply it explicitly to change the language list.
5.5 Profile responses
Each list entry contains id, name, startupUrl, extraArgs, createdAt, updatedAt, and optional lastLaunchedAt.
Detail, creation, and update responses also contain:
proxy: proxy connection settings, including the authentication password.fingerprint: fingerprint settings.acceptProxyChain: whether the profile accepts the app's proxy chain.appearanceLabel,appearanceBackgroundColor, andappearanceForegroundColor: appearance settings.
6. Browser lifecycle
| Method | Path | Purpose | Success response |
|---|---|---|---|
| POST | /v1/profiles/:id/launch | Launch the profile browser | { "ok": true } |
| POST | /v1/profiles/:id/command | Get a launch command without starting the browser | { "executable": "...", "args": [...] } |
| POST | /v1/profiles/:id/close | Close a browser started through launch | { "ok": true } |
6.1 Launch options
launch and command accept the same body. Send {} if no temporary options are needed.
| Field | Type | Required | Description |
|---|---|---|---|
startupUrl | string | No | URL for this launch; omitted or empty uses the profile's saved URL |
extraArgs | string[] | No | Arguments for this launch, appended after saved launch arguments |
{
"startupUrl": "https://example.com",
"extraArgs": ["--remote-debugging-port=9222"]
}Launch arguments include the profile's saved arguments, the app's global launch arguments, and this call's extraArgs, in that order. Clearing the profile's saved arguments does not clear the app's global arguments.
These options apply only to this call and do not change the profile's saved values. extraArgs cannot override the data directory or browser lifecycle arguments managed by PersonaHub.
A successful launch only confirms browser startup. Calling it again may close and restart that profile. Do not use it to poll browser status.
6.2 Launch command
The command response contains:
| Field | Type | Description |
|---|---|---|
executable | string | Path to the browser executable |
args | string[] | Complete launch arguments |
Pass the returned values directly to a process-spawning API on the computer running PersonaHub. Do not concatenate them into a shell command or override the data directory.
For --remote-debugging-pipe, use command and have the caller start the process with the debugging pipes connected. launch does not return debugging pipes.
6.3 Usage limits
- Keep the PersonaHub desktop app running while using the browser.
closedoes not manage browsers launched from the app UI or processes started by the caller usingcommand.- If no API launch is available to close, the API returns
404with codenot_running. The firstcloserequest can still succeed after the browser has exited on its own, so do not use this endpoint to check whether it is running. - A successful
closemeans closure was requested, not that the browser has exited. - Do not launch multiple instances of the same profile concurrently.
7. Saved website credentials
7.1 Website passwords
| Method | Path | Purpose | Success response |
|---|---|---|---|
| GET | /v1/profiles/:id/passwords | List summaries without passwords | { "credentials": [...] } |
| POST | /v1/profiles/:id/passwords | Save a website password | { "ok": true } |
| GET | /v1/profiles/:id/passwords/:passwordId | Get a credential, including its password | { "credential": {...} } |
| PATCH | /v1/profiles/:id/passwords/:passwordId | Update a website password | { "ok": true } |
| DELETE | /v1/profiles/:id/passwords/:passwordId | Delete a website password | { "ok": true } |
Save request:
{
"origin": "https://example.com",
"username": "user@example.com",
"password": "<WEBSITE_PASSWORD>"
}| Field | Rules |
|---|---|
origin | Required HTTP/HTTPS URL; up to 2048 characters |
username | Required and nonempty; up to 512 characters |
password | Required and nonempty; up to 2048 characters |
PATCH requires at least one of these fields. Omitted fields keep their current values; empty strings are not allowed. signon_realm is generated automatically and is not accepted as a request field.
Summaries contain id, origin, signon_realm, and username; single-credential responses also include password. Saving the same sign-on realm and username updates the existing entry. Saving returns no ID; query the list afterward to obtain it.
Changes are provided to the browser on a subsequent launch. Deletion does not change the website account or remove credentials already loaded by a running browser. Later browser sync may overwrite changes or recreate deleted entries.
7.2 TOTP codes
| Method | Path | Purpose | Success response |
|---|---|---|---|
| GET | /v1/profiles/:id/otp | List entry metadata | { "entries": [...] } |
| POST | /v1/profiles/:id/otp | Save or update a TOTP entry | { "entry": {...} } |
| DELETE | /v1/profiles/:id/otp/:otpId | Remove an entry | { "ok": true } |
| GET | /v1/profiles/:id/otp/:otpId/code | Generate the current code | { "id": "...", "code": "...", "expiresAt": "..." } |
Save fields:
| Field | Type | Required | Description |
|---|---|---|---|
secret | string | Yes | Base32 secret; up to 256 characters after removing whitespace and uppercasing; not an otpauth:// URL |
label | string | No | Up to 120 characters; derived from issuer and account when omitted, or Authenticator if both are empty |
issuer | string | No | Up to 120 characters; defaults to an empty string |
accountName | string | No | Up to 180 characters; defaults to an empty string |
algorithm | string | No | SHA1, SHA256, or SHA512; defaults to SHA1 |
digits | number | No | 6 or 8; defaults to 6 |
period | number | No | Period in seconds; integer from 15 to 120; defaults to 30 |
List and save responses include id, label, issuer, accountName, algorithm, digits, and period. They do not return the secret.
Within the same profile, the same normalized secret updates or restores the existing entry. A different secret creates a new entry. Omitted metadata and settings use defaults on each save; they do not preserve existing values.
Example code response:
{
"id": "<OTP_UUID>",
"code": "012345",
"expiresAt": "2026-09-17T08:00:30.000Z"
}code is a string; preserve leading zeroes. Codes use the clock on the computer running PersonaHub. expiresAt is a UTC ISO timestamp. The API does not submit the code. Saving or deleting an entry does not enable or disable two-step verification on the website.
7.3 Passkeys
| Method | Path | Purpose | Success response |
|---|---|---|---|
| GET | /v1/profiles/:id/passkeys | List passkey metadata | { "entries": [...] } |
| DELETE | /v1/profiles/:id/passkeys/:passkeyId | Remove a saved entry | { "ok": true } |
Each entry contains id, rpId, userName, and userDisplayName. Private keys are not returned. The automation API has no endpoint for creating or importing passkeys.
Deletion affects subsequent launches. It does not unregister the credential on the website or remove copies already loaded by a running browser. See the passkey guide for plan requirements when using passkeys in the browser.
8. Common errors
| HTTP status | code | Meaning |
|---|---|---|
| 400 | body_invalid | Invalid JSON |
| 400 | body_not_object | The top-level request value is not an object |
| 400 | input_invalid | Fingerprint, website password, or TOTP fields are invalid |
| 400 | profile_name_required / profile_name_too_long | Missing or oversized profile name |
| 400 | startup_url_invalid / startup_url_too_long | Invalid startup URL type, format, or length |
| 400 | launch_args_too_long | Saved launch arguments are too long |
| 400 | extra_args_invalid | Temporary arguments are not a string array or include a protected argument |
| 400 | proxy_invalid | Proxy settings are not an object |
| 400 | protocol_invalid | Unsupported proxy protocol |
| 400 | proxy_port_invalid | Invalid proxy port |
| 400 | proxy_ip_info_invalid | Invalid proxy exit information or missing IP |
| 400 | proxy_probe_failed | Proxy check failed |
| 400 | password_account_taken | Updated sign-on realm and username conflict with another credential |
| 400 | otp_code_failed | Failed to generate a TOTP code |
| 401 | unauthorized | Missing or incorrect API key |
| 401 | not_authenticated | Desktop account is signed out or its session has expired |
| 403 | profile_quota_exceeded | Account profile limit reached |
| 404 | not_found | Resource or route not found, or invalid path ID |
| 404 | not_running | No API launch available to close |
| 405 | method_not_allowed | Unsupported HTTP method |
| 413 | body_too_large | Request body exceeds the limit; the connection may close directly |
| 500 | automation_api_error | Request processing failed |
| 503 | console_session_not_ready | The desktop session is not ready |
| 503 | browser_engine_not_ready | The browser engine is not ready |