Local vs remote control
- Local control (default): the Gateway starts the loopback control service and can launch a local browser.
Targetless actions can launch it (for example,
open,navigate, orapus browser start). Actions that name a tab bytargetId, tab id, or label never start a stopped browser, because a new browser cannot contain that tab; start the browser or open a new tab, then select a current target. - Remote control (node host): run a node host (see Nodes for pairing and Node host CLI for
apus node run) on the machine that has the browser; the Gateway proxies browser actions to it. - Remote CDP: set
browser.profiles.<name>.cdpUrl(orbrowser.cdpUrl) to attach to a remote Chromium-based browser. In this case, Apus will not launch a local browser. - For externally managed CDP services on loopback (for example Browserless in
Docker published to
127.0.0.1), also setattachOnly: true. Loopback CDP withoutattachOnlyis treated as a local Apus-managed browser profile. headlessonly affects local managed profiles that Apus launches. It does not restart or change existing-session or remote CDP browsers.executablePathfollows the same local managed profile rule. Changing it on a running local managed profile marks that profile for restart/reconcile so the next launch uses the new binary.
Stopping behavior differs by profile mode:
- local managed profiles:
apus browser stopstops the browser process that Apus launched - attach-only and remote CDP profiles:
apus browser stopcloses the active control session and releases Playwright/CDP emulation overrides (viewport, color scheme, locale, timezone, offline mode, and similar state), even though no browser process was launched by Apus
Remote CDP URLs can include auth:
- Query tokens (e.g.,
https://provider.example?token=<token>) - HTTP Basic auth (e.g.,
https://user:pass@provider.example)
Apus preserves the auth when calling /json/* endpoints and when connecting
to the CDP WebSocket. Prefer environment variables or secrets managers for
tokens instead of committing them to config files.
Node browser proxy (zero-config default)
If you run a node host on the machine that has your browser, Apus can
auto-route browser tool calls to that node when the Gateway host has no local
browser capability. Automatic routing prefers the host, including a stopped
managed browser whose executable is installed. Explicit target="node", a
node selector, or gateway.nodes.browser.node overrides that preference;
target="host" always stays on the host.
The selected host profile owns existing-session, extension, attach-only, and remote-CDP connections even when no managed-browser executable is installed. Launch failures, invalid executable settings, permission errors, and page-action failures stay on that owner; Apus does not replay them on another machine. Automatic host fallback from a selected node is allowed only before the selected node handles a request. Once an action reaches the node, its follow-up snapshot or settings stay on that node instead of switching browsers.
Standalone runs such as apus agent exec use the host browser when no
Gateway or node route is selected. They do not need Gateway credentials for
local browser control. Sandbox routing and host-control restrictions still apply.
To discover browser nodes through a local Gateway from a standalone run, set
gateway.nodes.browser.mode="auto"; discovery runs only when local capability is
unavailable. An explicit node target or pin, remote
Gateway configuration, or APUS_GATEWAY_URL also keeps node discovery
enabled. Explicit node targets and pins retain connection and authentication
errors.
Notes:
- The node host exposes its local browser control server via a proxy command.
- Profiles come from the node's own
browser.profilesconfig (same as local). - The proxy command never allows persistent profile mutations (
create-profile,delete-profile,reset-profile) regardless ofallowProfiles; make those changes on the node directly. nodeHost.browserProxy.allowProfilesis optional. Leave it empty for the legacy/default behavior: all configured profiles remain reachable through the proxy.- If you set
nodeHost.browserProxy.allowProfiles, Apus treats it as a least-privilege boundary limiting which profile names the proxy will target. - Requests keep their selected profile while preparing work. The node rechecks proxy and profile access before browser actions, including after startup or upload preparation.
- Disable if you don't want it:
- On the node:
nodeHost.browserProxy.enabled=false - On the gateway:
gateway.nodes.browser.mode="off"(also accepts"auto"to prefer the host and fall back to a single connected browser node, or"manual"to require an explicit node selection or configured pin)
- On the node:
Browserless (hosted remote CDP)
Browserless is a hosted Chromium service that exposes CDP connection URLs over HTTPS and WebSocket. Apus can use either form, but for a remote browser profile the simplest option is the direct WebSocket URL from Browserless' connection docs.
Example:
{
browser: {
enabled: true,
defaultProfile: "browserless",
profiles: {
browserless: {
cdpUrl: "wss://production-sfo.browserless.io?token=<BROWSERLESS_API_KEY>",
},
},
},
}
Notes:
- Replace
<BROWSERLESS_API_KEY>with your real Browserless token. - Choose the region endpoint that matches your Browserless account (see their docs).
- If Browserless gives you an HTTPS base URL, you can either convert it to
wss://for a direct CDP connection or keep the HTTPS URL and let Apus discover/json/version.
Browserless Docker on the same host
When Browserless is self-hosted in Docker and Apus runs on the host, treat Browserless as an externally managed CDP service:
{
browser: {
enabled: true,
defaultProfile: "browserless",
profiles: {
browserless: {
cdpUrl: "ws://127.0.0.1:3000",
attachOnly: true,
},
},
},
}
The address in browser.profiles.browserless.cdpUrl must be reachable from the
Apus process. Browserless must also advertise a matching reachable endpoint;
set Browserless EXTERNAL to that same public-to-Apus WebSocket base, such
as ws://127.0.0.1:3000, ws://browserless:3000, or a stable private Docker
network address. If /json/version returns webSocketDebuggerUrl pointing at
an address Apus cannot reach, CDP HTTP can look healthy while the WebSocket
attach still fails.
Do not leave attachOnly unset for a loopback Browserless profile. Without
attachOnly, Apus treats the loopback port as a local managed browser
profile and may report that the port is in use but not owned by Apus.
Direct WebSocket CDP providers
Some hosted browser services expose a direct WebSocket endpoint rather than
the standard HTTP-based CDP discovery (/json/version). Apus accepts three
CDP URL shapes and picks the right connection strategy automatically:
- HTTP(S) discovery -
http://host[:port]orhttps://host[:port]. Apus calls/json/versionto discover the WebSocket debugger URL, then connects. No WebSocket fallback. - Direct WebSocket endpoints -
ws://host[:port]/devtools/<kind>/<id>orwss://...with a/devtools/browser|page|worker|shared_worker|service_worker/<id>path. Apus connects directly via a WebSocket handshake and skips/json/versionentirely. - Bare WebSocket roots -
ws://host[:port]orwss://host[:port]with no/devtools/...path (e.g. Browserless, Browserbase). Apus tries HTTP/json/versiondiscovery first (normalising the scheme tohttp/https); if discovery returns awebSocketDebuggerUrlit is used, otherwise Apus falls back to a direct WebSocket handshake at the bare root. If the advertised WebSocket endpoint rejects the CDP handshake but the configured bare root accepts it, Apus falls back to that root as well. This lets a barews://pointed at a local Chrome still connect, since Chrome only accepts WebSocket upgrades on the specific per-target path from/json/version, while hosted providers can still use their root WebSocket endpoint when their discovery endpoint advertises a short-lived URL that is not suitable for Playwright CDP.
apus browser doctor uses the same discovery-first, WebSocket-fallback
logic as runtime attach, so a bare-root URL that connects successfully is not
reported as unreachable by diagnostics.
Browserbase
Browserbase is a cloud platform for running headless browsers with built-in CAPTCHA solving, stealth mode, and residential proxies.
{
browser: {
enabled: true,
defaultProfile: "browserbase",
profiles: {
browserbase: {
cdpUrl: "wss://connect.browserbase.com?apiKey=<BROWSERBASE_API_KEY>",
},
},
},
}
Notes:
- Sign up and copy your API Key from the Overview dashboard.
- Replace
<BROWSERBASE_API_KEY>with your real Browserbase API key. - Browserbase auto-creates a browser session on WebSocket connect, so no manual session creation step is needed.
- See pricing for current free-tier limits and paid plans.
- See the Browserbase docs for full API reference, SDK guides, and integration examples.
Notte
Notte is a cloud platform for running headless browsers with built-in stealth, residential proxies, and a CDP-native WebSocket gateway.
{
browser: {
enabled: true,
defaultProfile: "notte",
profiles: {
notte: {
cdpUrl: "wss://us-prod.notte.cc/sessions/connect?token=<NOTTE_API_KEY>",
},
},
},
}
Notes:
- Sign up and copy your API Key from the console settings page.
- Replace
<NOTTE_API_KEY>with your real Notte API key. - Notte auto-creates a browser session on WebSocket connect, so no manual session creation step is needed. The session is destroyed when the WebSocket disconnects.
- See pricing for current free-tier limits and paid plans.
- See the Notte docs for full API reference, SDK guides, and integration examples.