Oculr API
A local HTTP API that launches browser profiles on your own hardware and hands you a CDP endpoint to drive with Playwright, Puppeteer, Selenium, or MCP.
Overview
Oculr exposes a small HTTP API that runs on the same machine as the app. You ask it to launch a profile, it returns a ready Chrome DevTools Protocol (CDP) endpoint, and you connect any standard automation driver to that endpoint. The profile carries its own fingerprint, storage, and proxy, so each session looks like an ordinary browser on an ordinary device.
The browsers run on hardware you own, either locally or on a server you host. Nothing is rendered in a metered cloud, so there is no per browser hour charge for the sessions themselves.
- Launch a profile over HTTP and receive a CDP endpoint.
- Connect Playwright, Puppeteer, Selenium, or the MCP server to that endpoint.
- Drive the page with the driver you already know.
- Reuse the same profiles from scripts, the MCP server, and the built in agent.
Base URL and token
The API is served by the local Oculr agent. The default base URL looks like http://127.0.0.1:8378. The app shows the exact port and the access token under Settings, so copy both from there rather than hard coding them.
http://127.0.0.1:8378/apiZero config discovery. On startup the agent writes a runtime descriptor so a co-located script can find a running agent without any configuration. It lives at $OCULR_RUNTIME_FILE if set, otherwise ~/.oculr/data/agent.json (the path follows OCULR_DATA_DIR). The file is 0600, written atomically, and removed on a graceful shutdown.
{ "schema": 1, "pid": 4821, "host": "127.0.0.1", "port": 8765, "base_url": "http://127.0.0.1:8765", "app_version": "0.1.3", "api_version": 1, "auth_required": true, "token": "<token, only when published>"}Read base_url to reach the agent. The token field is present only when the agent was told to publish it (the serve daemon publishes by default; the desktop app does not). When auth_required is true and no token is present, supply your own token from Settings. A descriptor can be stale after a hard kill, so validate liveness with a quick GET /api/status before trusting it.
GET /api/status is unauthenticated and returns app_version and api_version. Use it as a liveness and version probe before driving the agent.How it fits together
Every entry point talks to the same local API and the same CDP sessions. A Node script, a Python script, the MCP server, and the built in agent all launch the same profiles and attach over the same protocol. There is no separate automation layer to learn for each one.
| Entry point | How it connects |
|---|---|
| REST scripts | POST a launch, then attach a driver to the CDP endpoint |
| MCP server | profile_* and browser_* tools over the same API |
| Built in agent | natural language and recorded workflows over the same profiles |
Run without the desktop app
The same agent that backs the desktop app can run on its own, with no window, for server side automation. Start it with the serve subcommand of the bundled oculr-agent binary. It serves the same API on the same routes and writes the same runtime descriptor, so scripts discover and drive it exactly as they would the desktop agent.
# Serve the local API headless. Flags are optional.oculr-agent serve --host 127.0.0.1 --port 8765 --data-dir ~/.oculr/data # Discovery only: do not write the auth token into the runtime file.oculr-agent serve --no-publish-token| Flag | Description |
|---|---|
| --host | Bind address. Defaults to 127.0.0.1, or OCULR_HOST. |
| --port | Port to bind. Defaults to 8765, or OCULR_PORT. When the port is unspecified and 8765 is taken, the daemon falls back to a free OS assigned port and publishes it in the descriptor. |
| --data-dir | Profile and SQLite storage dir. Defaults to ~/.oculr/data, or OCULR_DATA_DIR. |
| --no-publish-token | Advertise only discovery fields in the runtime file, not the auth token. |
Unlike the desktop app, serve publishes its auth token in the runtime descriptor by default, so a co-located script reads both base_url and token from agent.json and connects with zero configuration. Pass --no-publish-token to keep the token out of the file and supply it yourself. The daemon shuts down cleanly on SIGINT or SIGTERM and removes its descriptor.