Files
obscura/docs/Environment-variables.md
2026-09-30 14:04:12 +00:00

8.6 KiB

Runtime

OBSCURA_ALLOW_PRIVATE_NETWORK

Allow fetches to loopback (127.0.0.0/8), RFC1918 (10.0.0.0/8, 172.16.0.0/12, 192.168.0.0/16), and link-local (169.254.0.0/16, including the 169.254.169.254 cloud-metadata endpoint) addresses. The deny-set also covers the unspecified address (0.0.0.0 / ::), IPv6 unique-local (fc00::/7), and any IPv4-mapped form of the above. Off by default to block SSRF.

The guard validates at DNS-resolution time as well as on literal hosts, so a public hostname that resolves to a forbidden address is rejected at connect time (DNS-rebinding safe), not just hosts written as raw IPs.

Truthy values: 1, true, yes, on.

OBSCURA_ALLOW_PRIVATE_NETWORK=1 obscura fetch http://localhost:8080

Per-process equivalent: --allow-private-network on any subcommand.

OBSCURA_NAV_TIMEOUT_MS

Hard ceiling on a single navigation. Default 30000 (30 seconds). Applies to Page.navigate and the CLI fetch command.

OBSCURA_NAV_TIMEOUT_MS=60000 obscura serve

OBSCURA_NAV_CHAIN_LIMIT

How many documents a navigation chain may load, the first navigation included. Default 10, which allows the requested document and nine navigations the page itself triggers via location assignments or form submissions. Raise the value for an endpoint that chains longer for good reasons, such as an SSO handover across several providers. The low default is what stops a page that resets location on every load.

A zero is raised to 1. This loads the requested document. If the page wants to chain further afterwards, the call reports an error, as at any other limit. A value the engine does not read as a number is replaced by the default. This also applies to a negative value and to a value with a trailing space.

The time budget is not tied to this limit. A longer chain usually also needs a higher OBSCURA_NAV_TIMEOUT_MS, because its default of 30 seconds applies to the whole chain and not to the individual document.

OBSCURA_NAV_CHAIN_LIMIT=20 obscura serve

OBSCURA_SCRIPT_DEADLINE_MS

Soft deadline for the complete page script-execution phase, including classic scripts and ES modules. Default 30000 (30 seconds). Raise it for a heavy SPA whose initial module is responsible for mounting an otherwise empty document. The engine also uses this value as a hard V8 watchdog budget, with a one-second grace period, so a synchronous script cannot run forever.

OBSCURA_SCRIPT_DEADLINE_MS=60000 obscura serve

OBSCURA_MODULE_BUDGET_MS

Per-module graph-loading and evaluation budget for modules that enhance an already-rendered page. Default 3000 (3 seconds). Raise it when a module such as the Vite HMR client legitimately needs longer to evaluate:

OBSCURA_MODULE_BUDGET_MS=10000 obscura serve

This shorter budget applies when the document body already contains more than 50 descendant nodes, where modules are normally progressive enhancement and should not delay navigation indefinitely. For an unmounted SPA shell, Obscura instead gives each module the full OBSCURA_SCRIPT_DEADLINE_MS budget so the app has time to mount. Module network requests remain independently bounded by OBSCURA_FETCH_TIMEOUT_MS.

OBSCURA_CDP_COMMAND_TIMEOUT_MS

Per-command deadline for the CDP server. A hung page (a runaway Runtime.evaluate, a synchronous DOM op) is terminated after this budget so one bad session cannot hold the shared V8 lock and stall the others. Default 60000 (60 seconds); 0 disables it. Navigation self-bounds via OBSCURA_NAV_TIMEOUT_MS well under this.

OBSCURA_CDP_COMMAND_TIMEOUT_MS=30000 obscura serve

OBSCURA_CDP_TOKEN

Bearer token for the CDP discovery and WebSocket endpoints. It is optional on loopback. A non-loopback bind is refused unless this is set to at least 32 bytes. Pass it as Authorization: Bearer <token> in the CDP client's headers.

OBSCURA_CDP_TOKEN="$(openssl rand -hex 32)" obscura serve --host 0.0.0.0

OBSCURA_FETCH_TIMEOUT_MS

Request timeout for scripted fetch(), XMLHttpRequest, and ES-module loads. Without it a request to a server that accepts the connection but never responds (including a CORS preflight) hangs forever and the XHR is stuck with no completion event. Default 30000 (30 seconds).

OBSCURA_FETCH_TIMEOUT_MS=15000 obscura serve

OBSCURA_PROXY

Default proxy URL used by obscura-worker for the parallel scrape command when no --proxy flag is set.

OBSCURA_PROXY=http://proxy.example.com:8080 obscura scrape - < urls.txt

Stealth and identity

These tune the browser identity the engine presents so it stays internally consistent. See Configure stealth and proxies for the full picture.

OBSCURA_BLOCK_TRACKERS

Controls the tracker blocklist used by the stealth HTTP transport. It is on by default so --stealth retains its current privacy-first behavior. Set it to 0, false, no, or off to keep the stealth TLS/browser fingerprint while allowing tracker requests.

The setting is read when a stealth client is created. Values are case-insensitive and surrounding whitespace is ignored; unset, empty, and unrecognized values keep blocking enabled. Non-stealth transport settings and SSRF protection are unchanged.

OBSCURA_BLOCK_TRACKERS=0 obscura --stealth fetch https://example.com

OBSCURA_TIMEZONE

Pins the process timezone before V8/ICU reads it, so Date (getTimezoneOffset, toString) and Intl.DateTimeFormat report one consistent zone. Default Europe/Berlin. Set it to match the exit IP's region.

OBSCURA_TIMEZONE=America/New_York obscura serve

OBSCURA_GEOLOCATION

Override the coordinates the navigator.geolocation shim reports, as lat,lon. Without it the shim reports a fixed default. Keep it consistent with OBSCURA_TIMEZONE and the proxy region.

OBSCURA_GEOLOCATION="40.7128,-74.0060" obscura serve

OBSCURA_PROFILE

Pin a specific browser profile from the built-in pool by index (0-based). Each profile keeps navigator.platform, userAgentData, the UA string, and the GPU renderer internally consistent. Without it a single stable profile is used.

OBSCURA_PROFILE=2 obscura serve

OBSCURA_ROTATE_PROFILE

Opt into picking a random profile per browser context instead of the stable default. Leave it off when you pin a TLS fingerprint, proxy region, or timezone, since a rotated profile would no longer match those.

OBSCURA_ROTATE_PROFILE=1 obscura serve

MCP

OBSCURA_MCP_ALLOWED_ORIGINS

Comma-separated Origin allowlist for the HTTP MCP transport (obscura mcp --http). Browser requests are refused by default; when set, only listed origins are accepted. Native, non-browser MCP clients (which send no Origin) are always allowed.

OBSCURA_MCP_ALLOWED_ORIGINS="https://app.example.com" obscura mcp --http --host 0.0.0.0

OBSCURA_MCP_TOKEN

Bearer token for MCP HTTP requests. It is optional on loopback. A non-loopback bind is refused unless this is set to at least 32 bytes.

OBSCURA_MCP_TOKEN="$(openssl rand -hex 32)" obscura mcp --http --host 0.0.0.0

Logging

RUST_LOG

Standard tracing filter. Common settings:

RUST_LOG=obscura=info obscura serve
RUST_LOG=obscura=debug obscura serve
RUST_LOG=obscura_cdp=trace,obscura_browser=debug obscura serve

--verbose on the CLI is equivalent to RUST_LOG=obscura=info.

Build

OPENSSL_NO_VENDOR

Forces cargo build to use the system OpenSSL instead of compiling the vendored copy. Set to 1 on hosts where the vendored OpenSSL fails (older VPS with AVX-512 issues).

OPENSSL_NO_VENDOR=1 cargo build --release --features render

V8

V8 flags are passed via --v8-flags, not environment variables:

obscura --v8-flags "--max-old-space-size=2048 --expose-gc" serve

Defaults are --max-old-space-size=4096 --max-semi-space-size=4 --optimize-for-size on 64-bit systems. In the current V8, --optimize-for-size overrides the requested semi-space cap to 1 MiB, not 4 MiB. The old-generation ceiling remains 4 GB.

User flags are appended after the defaults, but V8 applies flag implications afterwards. To change the young-generation cap, also disable size optimization, for example obscura --v8-flags "--no-optimize-for-size --max-semi-space-size=8" serve. This can reduce GC CPU at the cost of more memory; measure the complete workload before adopting it. Use --v8-flags "--print-flag-values" to inspect the effective settings after V8 initialization.

HTTP proxy environment

Obscura does not honor HTTP_PROXY / HTTPS_PROXY / NO_PROXY. Use --proxy or OBSCURA_PROXY.