Skip to content
← Back to Home

Local API

Last checked against the contract: September 2026

In development. The local API is not in the build you can download today: in every released Liminal nothing listens and a connection is refused. This page is the contract it is being built to, published so a script can be written before it ships. It says nothing about a date.

A script on the same machine turns a profile’s browser into something it can drive. The first version of the interface does one thing — it answers whether Liminal is running and whether anyone is signed in — and everything after it, starting a profile and the addresses Puppeteer, Playwright and Selenium connect to, is built on top of the same service, the same key and the same address file described here.

Turning it on

Off by default, and reachable from this computer only.

The switch
Open Settings → More Settings → API & Automation and turn on Local API. Until you do, nothing listens: the port is not opened, and a script gets a refused connection rather than an empty answer.
This computer only
The service accepts connections on 127.0.0.1 and nowhere else. Another machine on your network cannot reach it, and there is no setting that opens it up — a script runs beside Liminal, not against it over the network.
The port
The default is 48361, a port of Liminal’s own so it does not collide with another browser already listening on the machine. Type a different one, or press Random free port and let the app pick. The change takes effect at once, without restarting Liminal.
When the port is taken
If the port cannot be bound, the screen says Port in use and the address file reports port_in_use. Nothing listens until you choose another port, so a script that reads the file knows the difference between "off" and "could not start".

The key

One key, shown once, kept where your operating system keeps secrets.

Copy it when it appears
Enabling the API issues a key of 64 lowercase hexadecimal characters and shows it once. Leave the screen and it is hidden: the app cannot show it again, it can only issue a new one.
Where it is stored
In Keychain on macOS and Credential Manager on Windows — never in a settings file, a sync snapshot or a log, and never in the address file below. Keep your copy the way you keep any other credential your script uses.
Revoking it
Regenerate key issues a new key and stops accepting the old one immediately, with no restart of the app and no change to the port. A script still holding the old key is refused from the next request on.
Sending it
Every request carries the key in one header: Authorization: Bearer followed by the key itself. There is no query parameter and no cookie, and a request without the header is refused like a request with a wrong key.

Where a script finds the address

The app writes its address to a file, so nothing has to be typed twice.

The file
The settings screen shows the absolute path to Local API/status.json inside Liminal’s user-data directory. Read it instead of hardcoding a port: it follows the port you set and the one Random free port picked.
What it holds
Four fields — enabled, status, address, port — and no secret of any kind.
{"enabled":true,"status":"running","address":"http://127.0.0.1:48361","port":48361}
When the API is off
The file stays where it is and says so: off with an empty address and no port. The same shape, a different state — a script reads one file to learn everything.
{"enabled":false,"status":"off","address":"","port":0}
It is replaced, never half-written
Every change — turning the API on or off, a new port, a port that could not be bound — rewrites the file atomically. A script that reads it during a change sees the old contents or the new ones, never a truncated line.

The status request

One request in this version: is Liminal running, and is anyone signed in.

The call
A GET to /v1/status at the address from the file, with the key in the header.
curl -H 'Authorization: Bearer <key>' http://127.0.0.1:48361/v1/status
The answer
HTTP 200, with the running build’s version and whether the app has someone signed in. A false signedIn is not an error — the API answers, and the profile operations that come later are what will need an account.
{"status":"running","version":"<version>","signedIn":true}
A missing or revoked key
HTTP 401, and the code invalid_key — permanent, and the thing to branch on. The message beside it is the app’s own wording for a person reading a log; treat it as text that can change, not as part of the contract.
{"error":{"code":"invalid_key","message":"Неверный ключ"}}
Address it exactly as the file does
Use 127.0.0.1 and the port from the file. A request that arrives naming any other host is not answered, even when it reaches the same port — the service replies to its own address only.
What an older Liminal does
Nothing: no port is opened, so a script connecting to it is refused. That refusal is how a script tells a build without the local API from one that has it turned off — in the second case the address file exists and says off.

What this version does and does not do

Said plainly, so nothing here reads as a promise it is not.

Status, and nothing else yet
Listing profiles, starting and stopping one, and the CDP address that Puppeteer, Playwright and Selenium connect to are the next step on this same service. They are not in this version, and this page grows when they arrive.
Which plans it is for
Every plan, the free one included. The local API is not a paid tier: a script on your own machine is how many people use an anti-detect browser at all, and putting it behind a plan would be a tax on that.Plans
How often a script may ask
There is no quota tied to your plan. The service protects itself from being flooded, which a script written for it will not notice.
A profile under automation is the same profile
It keeps its fingerprint, its proxy and its cookies, and it reaches the network through its proxy exactly as it does when you open it by hand. The API is a way in, not a second mode of the browser.Data & Security

The release that turns this page from a contract into a feature will be in the changelog. A question about the contract before then, or a value here that does not match what your build does: [email protected].