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— theBROWSER_MCP_MAX_INSTANCEScap 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.