Skip to content

Lifecycle tools

Lifecycle tools manage the full lifespan of browser instances — creating isolated sessions, querying what is alive, and tearing sessions down cleanly. Reach for these tools at the boundaries of a workflow: browser_create_instance to open a session, browser_list_instances to inspect what is currently active, browser_health to check server status without launching a browser, and browser_destroy_instance to shut everything down when the work is done.

browser_create_instance

Create a new isolated Camoufox browser instance with its own process and BrowserForge fingerprint.

Signature

async def browser_create_instance(
    name: str,
    *,
    profile_dir: str | None = None,
    headless: bool | Literal["virtual"] | None = None,
    proxy: dict[str, str] | None = None,
    humanize: bool | float | None = None,
    window: tuple[int, int] | None = None,
    block_images: bool | None = None,
    block_webrtc: bool | None = None,
    block_webgl: bool | None = None,
    camoufox_os: tuple[str, ...] | None = None,
    locale: str | None = None,
    geoip: bool | None = None,
    firefox_user_prefs: dict[str, Any] | None = None,
    camoufox_args: tuple[str, ...] | None = None,
    enable_cache: bool | None = None,
    ff_version: int | None = None,
) -> dict[str, Any]

Parameters

Name Type Default Description
name str — Name for the new instance. Case-sensitive, must be unique across live instances.
profile_dir str \| None None Path to a persistent profile directory. None (default) creates an ephemeral session without a reusable profile. Temporary browser files may still be written. When a path is given, Camoufox loads or creates that directory.

Every parameter below is a per-instance camoufox override. Each defaults to None, meaning "use the server-level config default" (set via BROWSER_MCP_* env vars or CLI flags — see Configuration). Passing a non-None value overrides that default for this instance only, leaving every other instance and the server default untouched. The full precedence order is: this parameter > CLI flag > BROWSER_MCP_* env var > built-in default.

Name Type Server default it overrides Description
headless bool \| "virtual" \| None True True for headless mode (no visible window). False for a visible window. "virtual" uses a virtual framebuffer (Xvfb) on Linux.
proxy dict[str, str] \| None None (no proxy) Proxy configuration dict. Accepted keys: server (required, e.g. "socks5://host:port"), username, password, bypass.
humanize bool \| float \| None True True enables cursor humanization with a maximum movement duration of 1.5 seconds; False disables it; a float sets that maximum in seconds.
window tuple[int, int] \| None None (Camoufox default) Browser window size as (width, height). Use browser_resize to set the page viewport.
block_images bool \| None False Block image loads.
block_webrtc bool \| None True Block WebRTC (prevents IP leaks through STUN/TURN).
block_webgl bool \| None False Block WebGL.
camoufox_os tuple[str, ...] \| None None (Camoufox default) OS fingerprint pool to sample from, e.g. ("windows", "macos").
locale str \| None None (Camoufox default) Locale string, e.g. "en-US".
geoip bool \| None None (automatic) Derive geolocation/timezone/locale from the public IP. When unset, a proxy enables GeoIP; explicit False disables it.
firefox_user_prefs dict[str, Any] \| None {} (none) Extra about:config Firefox preferences to set, e.g. {"privacy.trackingprotection.enabled": True}.
camoufox_args tuple[str, ...] \| None () (none) Extra CLI args passed through to the underlying Firefox process.
enable_cache bool \| None True Enable Camoufox's disk cache.
ff_version int \| None None (Camoufox default) Pin a specific Firefox major version for the fingerprint.

Returns — see response envelope. data shape:

{
  "name": "main",
  "instance_id": "launch-uuid",
  "status": "live",
  "mode": "ephemeral",
  "profile_dir": null,
  "page_count": 0,
  "active_url": null,
  "idle_seconds": 0.0,
  "created_at": "2026-04-22T10:00:00+00:00"
}

mode is "ephemeral" when profile_dir is None, "persistent" otherwise. This is the same InstanceSummary shape returned by browser_list_instances and browser_health — see the field table under browser_list_instances below.

Errors — emits error_type codes (see envelope error codes):

  • instance_already_exists — that name is reserved by a live instance, pending launch, or unfinished cleanup.
  • instance_limit_exceeded — the BROWSER_MCP_MAX_INSTANCES cap has been reached; destroy an existing instance first.
  • profile_dir_in_use — that profile is reserved by a live instance, pending launch, or unfinished cleanup.

Example

Request:

{
  "name": "browser_create_instance",
  "arguments": {
    "name": "main"
  }
}

Response:

{
  "status": "success",
  "instance": "main",
  "data": {
    "name": "main",
    "instance_id": "launch-uuid",
    "status": "live",
    "mode": "ephemeral",
    "profile_dir": null,
    "page_count": 0,
    "active_url": null,
    "idle_seconds": 0.0,
    "created_at": "2026-04-22T10:00:00+00:00"
  }
}

Notes — No pages exist immediately after creation. The first tool that needs a page (e.g. browser_navigate) creates one implicitly. For persistent instances, BrowserForge rolls a fresh fingerprint on each launch even when reusing an existing profile_dir — stored cookies and localStorage are preserved, but the fingerprint signals change. See Instances & isolation for a full discussion of ephemeral vs. persistent modes.

browser_destroy_instance

Shut down an instance and free all its resources.

Signature

async def browser_destroy_instance(name: str) -> dict[str, Any]

Parameters

Name Type Default Description
name str — Instance name.

Returns — see response envelope. data is an empty object ({}).

Errors — emits error_type codes (see envelope error codes):

  • instance_not_found — no instance with that name is currently live.

Example

Request:

{
  "name": "browser_destroy_instance",
  "arguments": {
    "name": "main"
  }
}

Response:

{
  "status": "success",
  "instance": "main",
  "data": {}
}

Notes — Camoufox is terminated and all in-memory browser state is discarded. If the instance was created with a profile_dir, that directory and its contents are left intact on disk — the profile survives for the next browser_create_instance call. To close a single tab while keeping the instance alive, use browser_close instead.

browser_list_instances

Return summaries of all currently live instances.

Signature

async def browser_list_instances() -> dict[str, Any]

Parameters

No parameters.

Returns — see response envelope. data shape:

{
  "instances": [
    {
      "name": "main",
      "instance_id": "launch-uuid",
      "status": "live",
      "mode": "ephemeral",
      "profile_dir": null,
      "page_count": 1,
      "active_url": "https://example.com",
      "idle_seconds": 12.3,
      "created_at": "2026-04-22T10:00:00+00:00"
    }
  ]
}

Each entry in instances has:

Field Type Description
name str Instance name.
status str Instance status, "live" or "crashed" — see crash detection.
mode str "ephemeral" or "persistent".
profile_dir str \| null Absolute path to the profile directory, or null for ephemeral instances.
page_count int Number of open tabs in the instance.
active_url str \| null URL of the currently active page, or null when no pages are open.
idle_seconds float Seconds since the last tool operation on this instance.
created_at str ISO 8601 timestamp (UTC) of when the instance was created.

Errors — emits error_type codes (see envelope error codes):

  • internal_error

Example

Request:

{
  "name": "browser_list_instances",
  "arguments": {}
}

Response:

{
  "status": "success",
  "instance": null,
  "data": {
    "instances": [
      {
        "name": "main",
        "instance_id": "launch-uuid",
        "status": "live",
        "mode": "ephemeral",
        "profile_dir": null,
        "page_count": 2,
        "active_url": "https://example.com",
        "idle_seconds": 12.3,
        "created_at": "2026-04-22T10:00:00+00:00"
      }
    ]
  }
}

Notes — Never raises a domain error — if no instances exist the list is empty. instance in the envelope is null because this is a server-level tool that does not target a specific instance.

browser_health

Report server health without launching a browser.

Signature

async def browser_health() -> dict[str, Any]

Parameters

No parameters.

Returns — see response envelope. data shape:

{
  "instance_count": 1,
  "reserved_count": 1,
  "failed_launches": [],
  "max_instances": 10,
  "instances": [
    {
      "name": "main",
      "instance_id": "launch-uuid",
      "status": "live",
      "mode": "ephemeral",
      "profile_dir": null,
      "page_count": 1,
      "active_url": "https://example.com",
      "idle_seconds": 12.3,
      "created_at": "2026-04-22T10:00:00+00:00"
    }
  ],
  "config": {
    "idle_ttl_seconds": 0,
    "transport": "stdio",
    "host": "127.0.0.1",
    "port": 8931,
    "max_instances": 10
  }
}
Field Type Description
instance_count int Number of instances currently registered (including any not yet evicted as "crashed").
max_instances int Effective BROWSER_MCP_MAX_INSTANCES cap.
instances array Per-instance summaries — see below.
config object A snapshot of the server-level config relevant to instance lifecycle.

Each entry in instances has:

Field Type Description
name str Instance name.
status str Instance status, e.g. "live" or "crashed" — see crash detection.
mode str "ephemeral" or "persistent".
profile_dir str \| null Absolute path to the profile directory, or null for ephemeral instances.
page_count int Number of open tabs in the instance.
active_url str \| null URL of the currently active page, or null when no pages are open.
idle_seconds float Seconds since the last tool operation on this instance.
created_at str ISO 8601 timestamp (UTC) of when the instance was created.

config fields:

Field Type Description
idle_ttl_seconds int BROWSER_MCP_IDLE_TTL_SECONDS / --idle-ttl. 0 means the idle reaper is disabled.
transport str Active MCP transport (e.g. "stdio", "http").
host str Bind host, relevant for network transports.
port int Bind port, relevant for network transports.
max_instances int Same value as the top-level max_instances field.

Errors — emits error_type codes (see envelope error codes):

  • internal_error

Example

Request:

{
  "name": "browser_health",
  "arguments": {}
}

Response:

{
  "status": "success",
  "instance": null,
  "data": {
    "instance_count": 1,
    "reserved_count": 1,
    "failed_launches": [],
    "max_instances": 10,
    "instances": [
      {
        "name": "main",
        "instance_id": "launch-uuid",
        "status": "live",
        "mode": "ephemeral",
        "profile_dir": null,
        "page_count": 1,
        "active_url": "https://example.com",
        "idle_seconds": 12.3,
        "created_at": "2026-04-22T10:00:00+00:00"
      }
    ],
    "config": {
      "idle_ttl_seconds": 0,
      "transport": "stdio",
      "host": "127.0.0.1",
      "port": 8931,
      "max_instances": 10
    }
  }
}

Notes — Never launches or otherwise touches a browser process, so it is safe to poll frequently (e.g. from monitoring). instance in the envelope is null because this is a server-level tool. Instances that have crashed but have not yet been evicted (see crash detection) still appear here with status: "crashed" until the next call that resolves them, or until the idle reaper sweeps them up as a backstop.

Lifecycle identities and cleanup status

Every instance summary contains instance_id, unique to that launch. Active listings omit instances already being closed. browser_health additionally shows closing and failed-close records, reserved_count (including pending launches and cleanup), and failed_launches for failed launch rollback. A failed launch cleanup entry contains name, status (closing or close_failed), and a close_error after failure.

Creation reserves the name, capacity and profile before launching. Teardown keeps those reservations until cleanup succeeds. A teardown deadline or cleanup failure returns internal_error and retains the reservation; an earlier outer operation deadline returns operation_timeout while owned cleanup continues. In either case, inspect health and use your process supervisor before restarting the server. See lifecycle behavior.

geoip=None uses the configured default and enables proxy GeoIP automatically when unset. Explicit geoip=False disables that automatic behavior. All instance operations also include the shared operation metadata.