A browser session lifecycle an agent can reason about
Create, inspect, connect and close Cloudflare Browser Run sessions without confusing access links with persistent browser state.
Make browser cleanup observable, distinguish a closed page from an ended session and reconcile uncertain provider outcomes.
A browser task has at least two results: the work result and the resource lifecycle result. A failed extraction may still have a successfully closed browser; a useful research response may still report cleanup_pending. Track these results independently so a completed answer does not hide ongoing runtime. In Lupin, closing a tab, disconnecting a CDP client and ending a session are different operations. Only the session end route explicitly closes the provider browser and records its end. Build your task record around the session identifier rather than the lifetime of a local client connection.
Creating a session requires api_key_create, while ending it requires api_key_delete. Check both capabilities before allocation, especially for a key designed for an automated worker. A key that can start work but cannot clean it up creates avoidable operational dependence. Public research requires both permissions because it owns a temporary browser's full lifecycle. Human verification, billing readiness and provider configuration still apply. A bootstrap key does not gain cleanup or creation authority from knowing a session name. Permission design should cover the complete authorized operation, including its expected failure path.
Save the session_id as soon as creation returns and place the end request in a finally-style cleanup block. Preserve useful evidence before closure because the browser's cookies and page state will not be available afterward. If the main action fails, keep that error alongside the cleanup outcome rather than replacing it with a generic success message. For research, inspect session_closed and cleanup_pending in the returned payload. If a caller times out before receiving the response, reconcile the known operation and resource before allocating another browser to repeat the same work.
const session = await lupin.browsers.create({ name: "bounded-task" });
try {
// Perform the authorized work and save its evidence.
} finally {
await lupin.browsers.end(session.session_id);
}The browser end route checks the provider session and records an end time after closure. Provider failures surface as errors. If creation succeeds upstream but saving the registry fails, Lupin attempts compensating closure, but an interrupted request can still need operator inspection. Keep the resource or operation identity available for that investigation. Do not interpret a connection error as proof that the browser disappeared; the access link, the client socket and the underlying runtime can fail independently. Likewise, browser_provider_changed describes an old provider identity that needs a new session, not a reason to reuse an incompatible resource.
An actionable cleanup alert contains the session identifier, workspace, attempted end time and sanitized error category. It excludes live-view links, CDP tokens and private page content. Retry only the appropriate lifecycle operation within the current policy, and escalate when the provider outcome remains unknown. Listing sessions can help reconcile an externally ended browser with the registry. Once closure is confirmed, mark the resource finished and keep the saved evidence for review. Do not keep it running solely to preserve a page that should have been summarized or exported into the task record before cleanup.
Reviewed against the current Lupin route, provider adapter and shared input contracts, plus the linked official references. Examples were not run against live services.
Prepared with AI assistance by Lupin editorial. How we research and maintain these guides.