Guides
Configuration
Every setting of BrowserHive is a key that you can set in three places: an environment variable, the config file, or a CLI flag. This page explains how they combine. The configuration reference lists every key with its type, default and constraints.
Precedence
Section titled “Precedence”Lowest to highest. Rightmost wins.
defaults < environment variables < browserhive.config.json < CLI flagsWhen a key comes from more than one source, the startup log says which value won:
config: maxSessions=8 (cli) shadows config-file=4, env=2browserhive config show prints the effective value and source of every key, and the dashboard’s System page shows the same table. Secrets such as authTokens and otelHeaders are always shown as <redacted>. A value the config file reads from an environment variable names it: (config-file via $OTLP_HOST) (see References).
Naming
Section titled “Naming”Each key has one camelCase name; the other spellings are derived from it:
| Key | CLI flag | Environment variable | Config file |
|---|---|---|---|
maxSessions |
--maxSessions 8 |
BROWSERHIVE_MAX_SESSIONS=8 |
"maxSessions": 8 |
sessionLease |
--sessionLease 2h |
BROWSERHIVE_SESSION_LEASE=2h |
"sessionLease": "2h" |
allowInsecureBind |
--allowInsecureBind |
BROWSERHIVE_ALLOW_INSECURE_BIND=true |
"allowInsecureBind": true |
Rules:
- CLI flags are case-sensitive camelCase.
--maxsessionsor any kebab-case spelling is an unknown flag; the error suggests the camelCase spelling. - Booleans:
--adminsets true;--admin=falseor--noAdminsets false.--admin false(with a space) is not accepted, so a boolean never swallows the next argument. - Durations take
ms,s,m,hord(30m,2h). A bare number is milliseconds. - Sizes take
B,KiB,MiB,GiB,KB,MBorGB. A bare number is bytes. - Lists are comma-separated on the CLI and in env (
--otelSignals traces,logs), and JSON arrays in the file. - Maps are
k=v,k2=v2on the CLI and in env, and JSON objects in the file.
Fail fast
Section titled “Fail fast”Configuration problems stop the process before it binds a port or opens the database, with exit code 64 and a message that names the source:
browserhive: unknown flag '--maxSession'. Did you mean '--maxSessions'? Run 'browserhive --help'.browserhive: invalid value for --sessionLease: '2 hours'. Expected a duration like '2h', '30m', '90s', '500ms', or an integer of milliseconds.browserhive: BROWSERHIVE_PORT is set but empty. Unset it or provide a value.browserhive: 'otelHeaders' in /etc/browserhive/browserhive.config.json references {env:OTLP_TOKEN}, but OTLP_TOKEN is not set. Set it, or write a default as {env:OTLP_TOKEN:-<value>}.Unknown BROWSERHIVE_* environment variables and unknown keys in the config file fail the same way. An empty value is an error, not “unset”. Some combinations are rejected too, for example humanize=true with stealth=off, or admin=true with transport=stdio. The full list is under cross-field rules.
Check a configuration without starting the server:
browserhive config validateThe config file
Section titled “The config file”browserhive.config.json is plain JSON (no comments). BrowserHive uses the first file it finds:
--config <path>(orBROWSERHIVE_CONFIG). A missing file here is an error../browserhive.config.jsonin the current directory.<data-dir>/browserhive.config.json.
Relative paths inside the file resolve against the file’s directory. A config file found in the data directory may not change dataDir.
For editor completion, write the JSON Schema next to your file and reference it:
browserhive config schema > browserhive.schema.json{ "$schema": "./browserhive.schema.json", "transport": "http", "host": "127.0.0.1", "port": 9876, "admin": true, "auth": "token", "persistence": "persistent", "maxSessions": 6, "sessionLease": "2h", "attentionTimeout": "6h", "minAttentionWait": "30m", "stealth": "standard", "humanize": true, "vault": "bitwarden", "blocklist": "./blocklist.txt", "blocklistWatch": true, "retentionDays": 14, "retentionBytes": "2GiB", "logLevel": "info,sessions=debug", "logFormat": "auto", "otel": true, "otelEndpoint": "http://127.0.0.1:4318", "otelServiceName": "browserhive-lab"}The same schema is published in this repository as config.schema.json.
If the file contains a token in authTokens, keep it readable only by you (chmod 600); doctor warns otherwise. Better, keep the token out of the file: "authTokens": "ci-runner:{env:CI_TOKEN}" reads it from the environment (see References), and doctor has nothing to warn about.
References
Section titled “References”A string in browserhive.config.json can read an environment variable. The file can then be checked in and shared, while secrets and per-machine values come from the environment:
{ "otel": true, "otelEndpoint": "http://{env:OTLP_HOST:-127.0.0.1}:4318", "otelHeaders": { "Authorization": "Bearer {env:OTLP_TOKEN}" }, "authTokens": ["ci-runner:{env:CI_TOKEN}"], "maxSessions": "{env:MAX_SESSIONS:-4}"}| Write | Gets |
|---|---|
{env:NAME} |
The value of NAME. Startup stops with an error if NAME is not set or is empty. |
{env:NAME:-default} |
The value of NAME, or default when NAME is not set or is empty. |
{{env:NAME}} |
The literal text {env:NAME}. |
- A reference can be the whole value or part of it, including array elements and object values such as the headers in
otelHeaders. The result is read exactly as the key’s environment variable would be:"maxSessions": "{env:MAX_SESSIONS}"accepts8orunbounded, and"authTokens": "{env:BH_TOKENS}"accepts a comma-separated list. For numbers and booleans, write the reference as a string:"port": "{env:PORT}". - Each value is read once. A variable whose own value contains
{env:…}is used as it is, never expanded again. - Only the config file is expanded. On the command line and in
BROWSERHIVE_*variables your shell already does this (--authTokens "ci-runner:$CI_TOKEN"); BrowserHive leaves{env:…}there untouched and prints a warning. envis the only kind of reference, written in lower case. Text that looks like another kind, such as{file:/run/secrets/token}or{ENV:NAME}, stops startup with a message that says how to keep it literal: double the braces,{{file:/run/secrets/token}}.${env:NAME}, the OpenTelemetry Collector’s spelling, stops startup with a hint to drop the$. Other braces, such as{trace_id}inotelTraceUrlTemplate, are left alone.- On Windows, variable names are case-insensitive, as they are in the OS.
- A relative path that comes from a reference, as in
"blocklist": "{env:BLOCKLIST}", resolves against the config file’s directory, like every path in the file.
Every place that shows the configuration names the variable:
config: otelEndpoint=http://collector.internal:4318 (config-file via $OTLP_HOST) shadows env=http://127.0.0.1:4318config: otelHeaders=<redacted> (config-file via $OTLP_TOKEN) shadows env(otel)=<redacted>browserhive config showprintsconfig-file via $OTLP_HOSTin the SOURCE column, andconfig-file via $MAX_SESSIONS (default)when the default was used.browserhive config show --jsonandGET /api/v1/system/configaddrefs(the variables and whether each default was used) andtemplate(the value as written in the file).- On the dashboard’s System page, a
$NAMEchip sits next to the source. Select it to see whether the variable was set and the value as written. The Only values from references switch lists just those keys. browserhive doctorcounts the values that came from references and warns about each variable that was not set, so its default is in use.
Secrets stay hidden. For authTokens and otelHeaders, BrowserHive shows the variable’s name but never its value or the text around it in the file, and it scrubs the value from logs. The same happens for any key whose variable name contains a word such as token, secret, password, apikey or credential: for that run the key is shown as <redacted> everywhere, even its values from other sources. Error messages name the key, the file and the variable, not the line.
Most used keys
Section titled “Most used keys”| Key | Default | Purpose |
|---|---|---|
transport |
http |
http or stdio |
host, port |
127.0.0.1, 9876 |
bind address, shared by MCP, API, WebSocket and dashboard |
admin |
false |
dashboard, REST API, live view, traces |
auth |
off |
token requires bearer tokens on /mcp and scopes sessions to their owner |
persistence |
memory |
default for launch_session: memory, persistent, storage-state |
vault |
off |
bitwarden enables credential injection |
stealth |
standard |
off, standard or max; see also fingerprint and humanize |
defaultChannel |
chromium |
the browser sessions use: the bundled chromium, or the installed chrome or edge (choosing the browser) |
sandbox |
auto |
Chromium’s sandbox: auto wherever the machine allows it, on required (refuses to start otherwise), off never (security) |
maxSessions |
derived from RAM | concurrent session cap, or unbounded |
publicUrl |
unset | the address where you reach the dashboard from elsewhere (a Tailscale name, a reverse proxy, a tunnel); notification links use it (public address) |
allowedHosts |
none | extra Host names to accept, such as the name a reverse proxy forwards |
sessionLease |
2h |
idle sessions are closed after this long |
blocklist |
unset | URL blocklist file |
dataDir |
OS default | where state lives |
logLevel, logFormat |
info, auto |
logging; logLevel accepts per-module levels like info,sessions=debug |
recordToolResults |
full |
how much of each tool result is stored |
otel, otelEndpoint |
false |
OpenTelemetry export |
maxSessions defaults to min(floor(RAM in GiB / 1.5), 20). trace defaults to the value of admin, and fingerprint defaults to true only when stealth=max.
Environment-only deployments
Section titled “Environment-only deployments”For a service manager (systemd EnvironmentFile, docker --env-file):
BROWSERHIVE_TRANSPORT=httpBROWSERHIVE_HOST=0.0.0.0BROWSERHIVE_PORT=9876BROWSERHIVE_AUTH=tokenBROWSERHIVE_AUTH_TOKENS=ci-runner:REPLACE_WITH_32_PLUS_CHARSBROWSERHIVE_ADMIN=trueBROWSERHIVE_DATA_DIR=/var/lib/browserhiveBROWSERHIVE_LOG_FORMAT=jsonBROWSERHIVE_OTEL=trueOTEL_EXPORTER_OTLP_ENDPOINT=http://otel-collector:4318Standard OTEL_* variables are honoured below BROWSERHIVE_* ones; see the reference.
Per-session settings are tool arguments
Section titled “Per-session settings are tool arguments”An agent can override some defaults for one session through launch_session arguments: persistence_mode, headless, channel, stealth, fingerprint, humanize, disable_evaluate, vault_enabled, context_options and launch_options. These are not configuration and never appear in config show. See launch_session.
Runtime changes
Section titled “Runtime changes”Most keys need a restart. logLevel, logFormat and otelTraceUrlTemplate can be changed while the server runs (the log level from the dashboard’s System page or PATCH /api/v1/system/log-level).