Skip to content

Instances & isolation

justpen-browser-mcp manages named instances up to a configured capacity. Each instance is its own Camoufox process — a separate stealth-patched Firefox — with its own BrowserForge fingerprint and separate browser session state.

Why instances matter

A single server process can drive:

  • Parallel logged-in sessions — one instance per user / tenant, no cookie bleed.
  • Clean-slate flows — use an ephemeral instance and destroy it after a test to discard its session state. A persistent profile_dir survives destruction; choose a fresh profile directory when you need a new session.
  • Fingerprint diversity — each instance rolls a fresh BrowserForge fingerprint at launch, making parallel sessions look like different real browsers to fingerprinting detectors.
  • Per-instance proxies — route different instances through different outbound proxies without shared state.

Isolation boundaries

Each instance has its own:

Boundary What it covers
OS process Camoufox runs in a separate process; a crash in one instance does not affect others.
BrowserForge fingerprint Canvas, WebGL, font list, timezone, language, and dozens of other signals are independently generated per launch.
Cookies & storage Cookies, localStorage, sessionStorage, and cache are isolated from every other instance.
Optional proxy The proxy parameter scopes a SOCKS5/HTTP proxy to this instance only.
Optional persistent profile The profile_dir parameter pins a Firefox-style profile directory; omit it for an ephemeral instance.

Naming

Instances are identified by a string name of your choice. Names are case-sensitive. Creation and destruction use the name parameter; other tools scoped to an instance use instance. See the Lifecycle tools page for creation and teardown.

Ephemeral vs. persistent

profile_dir=None (the default) creates an ephemeral instance without a reusable persistent profile. Its session is discarded when the instance closes. The browser can still create temporary profile files; ephemeral mode does not guarantee that no files are written to disk.

profile_dir="/path/to/dir" creates a persistent instance. Cookies, localStorage, saved passwords, and other profile data survive across browser_destroy_instance / browser_create_instance cycles. The directory persists on disk even after the instance is destroyed.

Fingerprint re-roll on restart

BrowserForge generates a fresh fingerprint on every Camoufox launch, even for persistent instances. This means the fingerprint will differ between runs of the same profile_dir. The stored profile data (cookies, storage) is still preserved; only the fingerprint signals change.

Instance cap

BROWSER_MCP_MAX_INSTANCES (default 10) sets the maximum number of reserved instances, including launches, live browsers, and unfinished teardown. Attempting to create an instance beyond the cap returns an instance_limit_exceeded error. Invalid values (non-integer, zero, or negative) fall back to 10 with a warning logged to stderr.

Crash detection

Camoufox runs as a separate OS process per instance (see Isolation boundaries), and that process can disconnect or crash independently of the server. The manager listens for that disconnect and flips the instance's internal status to "crashed" — it does not evict the instance immediately.

Eviction happens lazily, on the next tool call that resolves the instance: that call frees the crashed instance's resources asynchronously and returns an instance_crashed error (see envelope error codes) instead of operating on a dead browser. Until that next call happens, browser_list_instances and browser_health will show the instance with status: "crashed".

browser_destroy_instance is the exception to lazy eviction: it works on a crashed instance directly, tearing it down cleanly and returning success, so you don't need to trigger eviction with another tool first.

If the crashed instance was created with a profile_dir, that persistent profile directory survives on disk — a crash does not delete stored cookies or other profile data, same as a clean browser_destroy_instance.

Idle reaper

A background task can automatically close instances that have been idle too long, so long-running servers don't accumulate abandoned browser processes. "Idle" is measured as time since the last tool operation on that instance — the clock is refreshed when serialized work starts and finishes. Busy instances and queued operations are skipped, and the reaper uses monotonic elapsed time.

The reaper is controlled by two settings (see Configuration):

Setting CLI flag Default Description
BROWSER_MCP_IDLE_TTL_SECONDS --idle-ttl 0 Idle threshold in seconds. 0 disables the idle reaper entirely.
BROWSER_MCP_REAPER_INTERVAL_SECONDS --reaper-interval 30 How often (in seconds) the reaper checks for idle/crashed instances.

Disabled by default

The idle reaper only runs when BROWSER_MCP_IDLE_TTL_SECONDS is set above 0. With the default of 0, instances are never closed for being idle — only explicit browser_destroy_instance calls (or a crash) remove them.

When enabled, each reaper pass also closes any lingering "crashed" instances as a backstop — instances usually get evicted the moment a caller touches them again (see crash detection above), but one that nobody calls after crashing would otherwise sit in the registry indefinitely. The crashed-instance backstop always runs when the reaper is active, independent of the idle TTL value.

Reaping only closes the underlying browser process; a persistent instance's profile_dir is left untouched on disk, exactly like browser_destroy_instance.

Why this is stronger than a shared process model

Separate browser processes improve fault containment and let each launch use its own fingerprint and session data. They share the host, network resources, filesystem permissions, and the Python MCP server process. This is not an OS security boundary between untrusted tenants, and it does not promise immunity to timing or fingerprint correlation. Camoufox uses Firefox's JavaScript engine. Use external process/container supervision when stronger containment is needed.

Lifecycle tools

Use these tools to manage instance lifetimes:

Single active page assumption

Within an instance, the MCP surface currently operates on a single active page. Opening a second tab is supported, but most tools target the active page; see Page tools for switching.

Identity, concurrency and teardown

Each launch has a new instance_id; each tab has a stable page_id until it closes. A reused name or tab index does not reuse that identity. The active tab is tracked by its page object, so an unrelated popup or tab removal does not silently retarget subsequent operations.

Actions serialize within an instance; different instances can run concurrently. Launch and teardown do not hold the registry lock while waiting on the browser. BROWSER_MCP_OPERATION_TIMEOUT_SECONDS bounds cooperative operations including queue time. A timeout after execution starts leaves side effects uncertain; use operation metadata before retrying.

Destroy removes an instance from active listings, waits for work to drain, then cancels blocked work and closes resources within BROWSER_MCP_CLOSE_TIMEOUT_SECONDS. Names, capacity slots, and profile directories stay reserved until cleanup is confirmed. Failed or timed-out teardown remains close_failed in browser_health; failed launch rollback appears in failed_launches. Inspect and stop any surviving browser through your process supervisor before restarting the server. Repeated destroy calls do not pretend that an incomplete cleanup succeeded.

Shutdown stops admission permanently for that manager. Calling destroy or shutdown from the instance's own browser_run_code operation is rejected to prevent a self-wait. See process limits.

Explicit page targets

Use page_id from browser_tabs to address a particular live page. Supported page actions resolve it after acquiring the instance lock. They do not change selected-tab state or create a replacement page. A foreign, closed, or unknown ID returns page_not_found, including when a page closes while the action is queued. Omitting the ID retains selected-page behavior and existing automatic page creation. Closing an explicitly targeted unselected page preserves the selected page.

Frame-capable tools also accept frame_id from browser_frames. A frame must belong to the resolved page; see frame refs. Coordinate mouse, screenshot, resize, navigation, and keyboard tools remain page-level. Keyboard input follows actual focus, including focus inside an iframe.