All Products
Search
Document Center

Function Compute:Browser template

Last Updated:Sep 16, 2026

The browser template provides a cloud-native browser runtime. It lets you remotely control a browser instance running in an isolated cloud container over the standard Chrome DevTools Protocol (CDP) over WebSocket, with native compatibility for automation frameworks such as Puppeteer and Playwright.

The browser template is not a ready-to-use built-in template: you must first build a named custom template from the official browser image, then create sandboxes from it. This page covers only capabilities, default configuration, build and minimal verification, and endpoint differences. For the full framework-integration tutorials (BrowserUse, LangChain, and more), see Use Browser Use Sandbox.

Features

FeatureDescription
Browser automationShips with Chromium/Chrome, supports full web standards, natively compatible with Puppeteer, Playwright, and other automation frameworks
CDP remote controlPrecisely drive dynamically rendered pages (SPAs) over the standard CDP protocol over WebSocket, while reliably maintaining login state and sessions
Real-time VNCBuilt-in VNC service lets you view the browser desktop in real time through a noVNC client, making debugging and monitoring easy
Secure isolationEach browser sandbox instance has its own file system and process space
Encrypted transportAll data-plane endpoints (CDP and VNC) use the WSS (WebSocket Secure) protocol, encrypted end to end

Default configuration

ItemDefaultDescription
Container imagefc-e2b-registry.cn-beijing.cr.aliyuncs.com/runtime/browser:v0.0.44Prebuilt browser image
Default port3000Port the sandbox service listens on
CPU4 vCPURecommended starting specification
Memory8192 MBRecommended starting specification
Disk size10240 MB10 GB is recommended for sufficient temporary storage

Build and minimal verification

Usage has two phases: first build the template (materialize a named template from the browser image), then run the template (create a sandbox, wait for the health check, open a page over CDP, and take a screenshot).

Note

The example uses the Beijing image. For another region, replace the region segment in the image address with the FC Agent Sandbox endpoint region and keep the v0.0.44 tag. Set E2B_API_KEY, E2B_API_URL, and E2B_DOMAIN (through .env or export) to that same region. The SDK reads them automatically, so you do not need to pass them into method calls. When you connect to the CDP/VNC endpoints, include the X-Access-Token header for authentication: the Python SDK exposes it through the internal attribute sbx._envd_access_token (which may be renamed or removed in future versions), and the JS SDK exposes sbx.envdAccessToken (declared protected in TypeScript, but readable at runtime).

Prepare the local environment

Python:

uv venv .venv --python 3.12
source .venv/bin/activate
uv pip install e2b==2.31.0 e2b-code-interpreter==2.8.1 'playwright>=1.49.0'
playwright install chromium

Node.js: use the following package.json, then run npm install.

{
  "name": "browser-template-demo",
  "version": "1.0.0",
  "type": "module",
  "dependencies": {
    "@e2b/code-interpreter": "^2.6.1",
    "e2b": "^2.31.0",
    "playwright-core": "^1.49.0"
  }
}

Build the browser template

Build a named template from the browser image, specifying CPU and memory (4 vCPU / 8192 MB recommended) at build time.

Python:

"""Browser template build example."""

import os

from dotenv import load_dotenv
from e2b import Template, default_build_logger

load_dotenv()

# The SDK reads E2B_API_KEY / E2B_API_URL / E2B_DOMAIN automatically.
FROM_IMAGE = "fc-e2b-registry.cn-beijing.cr.aliyuncs.com/runtime/browser:v0.0.44"

build = Template.build(
    Template().from_image(FROM_IMAGE),
    name="my-browser-template",
    cpu_count=4,
    memory_mb=8192,
    on_build_logs=default_build_logger(),
)
print(f"template_id: {build.template_id}")

Node.js:

// Browser template build example.
import { Template, defaultBuildLogger } from 'e2b';

// The SDK reads E2B_API_KEY / E2B_API_URL / E2B_DOMAIN automatically.
const FROM_IMAGE =
  'fc-e2b-registry.cn-beijing.cr.aliyuncs.com/runtime/browser:v0.0.44';

const build = await Template.build(Template().fromImage(FROM_IMAGE), 'my-browser-template', {
  cpuCount: 4,
  memoryMB: 8192,
  onBuildLogs: defaultBuildLogger(),
});
console.log(`template_id: ${build.templateId}`);

Run the template and verify

After creating the sandbox, poll /health until the browser service is ready, then connect Playwright over the CDP endpoint to open the target page and take a screenshot.

Python:

"""Browser template run example: create sandbox -> wait for health check -> CDP automation -> screenshot."""

import time

from e2b_code_interpreter import Sandbox
from playwright.sync_api import sync_playwright

# The SDK reads E2B_API_KEY / E2B_API_URL / E2B_DOMAIN automatically.
BROWSER_PORT = 3000


def wait_until_healthy(sbx: Sandbox, host: str, token: str, timeout: int = 60) -> None:
    """Poll the public gateway /health endpoint until the browser service is ready or times out."""
    token_header = f"-H 'X-Access-Token: {token}' " if token else ""
    deadline = time.time() + timeout
    while time.time() < deadline:
        result = sbx.commands.run(
            f"curl -sS -o /dev/null -w '%{{http_code}}' -m 4 {token_header}https://{host}/health",
            timeout=10,
        )
        if "".join(result.stdout or []).strip() == "200":
            return
        time.sleep(2)
    raise TimeoutError(f"browser service not ready within {timeout}s")


sbx = None
try:
    sbx = Sandbox.create(template="my-browser-template", timeout=900)
    host = sbx.get_host(BROWSER_PORT)
    token = sbx._envd_access_token  # the public gateway requires X-Access-Token, otherwise 403
    headers = {"X-Access-Token": token} if token else {}

    wait_until_healthy(sbx, host, token)

    with sync_playwright() as p:
        browser = p.chromium.connect_over_cdp(f"wss://{host}/ws/automation", headers=headers)
        context = browser.contexts[0] if browser.contexts else browser.new_context()
        page = context.new_page()
        page.goto("https://example.com", wait_until="domcontentloaded", timeout=30000)
        print(f"page.title() = {page.title()!r}")
        page.screenshot(path="browser-example.png", full_page=True)
        browser.close()
finally:
    if sbx is not None:
        sbx.kill()

Node.js:

// Browser template run example: create sandbox -> wait for health check -> CDP automation -> screenshot.
import { Sandbox } from '@e2b/code-interpreter';
import { chromium } from 'playwright-core';

// The SDK reads E2B_API_KEY / E2B_API_URL / E2B_DOMAIN automatically.
const BROWSER_PORT = 3000;
const sleep = (ms) => new Promise((resolve) => setTimeout(resolve, ms));

/** Poll the public gateway /health endpoint until the browser service is ready or times out. */
async function waitUntilHealthy(sbx, host, token, timeout = 60) {
  const tokenHeader = token ? `-H 'X-Access-Token: ${token}' ` : '';
  const deadline = Date.now() + timeout * 1000;
  while (Date.now() < deadline) {
    let result;
    try {
      result = await sbx.commands.run(
        `curl -sS -o /dev/null -w '%{http_code}' -m 4 ${tokenHeader}https://${host}/health`,
        { timeoutMs: 10_000 },
      );
    } catch (e) {
      result = e; // while the service is down curl exits non-zero; the exception still carries stdout
    }
    if ((result.stdout || '').trim() === '200') return;
    await sleep(2000);
  }
  throw new Error(`browser service not ready within ${timeout}s`);
}

let sbx = null;
try {
  sbx = await Sandbox.create('my-browser-template', { timeoutMs: 900_000 });
  const host = sbx.getHost(BROWSER_PORT);
  const token = sbx.envdAccessToken; // the public gateway requires X-Access-Token, otherwise 403
  const headers = token ? { 'X-Access-Token': token } : {};

  await waitUntilHealthy(sbx, host, token);

  const browser = await chromium.connectOverCDP(`wss://${host}/ws/automation`, { headers });
  const contexts = browser.contexts();
  const context = contexts.length ? contexts[0] : await browser.newContext();
  const page = await context.newPage();
  await page.goto('https://example.com', { waitUntil: 'domcontentloaded', timeout: 30_000 });
  console.log(`page.title() = ${JSON.stringify(await page.title())}`);
  await page.screenshot({ path: 'browser-example.png', fullPage: true });
  await browser.close();
} finally {
  if (sbx !== null) await sbx.kill();
}

WebSocket endpoints

The browser template exposes the following endpoints through port 3000. All require the X-Access-Token header for authentication, and <sandbox-host> is obtained through the SDK's sbx.get_host(3000):

EndpointPathPurpose
Health checkhttps://<sandbox-host>/healthDetermine whether the browser service has finished starting
CDP automationwss://<sandbox-host>/ws/automationBrowser automation, compatible with Puppeteer and Playwright
VNC livestreamwss://<sandbox-host>/ws/livestreamView the browser desktop in real time, viewable through a noVNC client

Inside the sandbox you can first probe whether the CDP WebSocket handshake works. A 101 Switching Protocols response means the endpoint can be upgraded to a WebSocket connection:

curl -sS -m 4 -i \
  -H 'Connection: Upgrade' -H 'Upgrade: websocket' \
  -H 'Sec-WebSocket-Version: 13' -H 'Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==' \
  http://localhost:3000/ws/automation

After returning 101 Switching Protocols, the server continues sending WebSocket frames. curl may wait until -m 4 expires and exit with code 28. This does not indicate a failed handshake; check whether the response contains 101 Switching Protocols.

Note

The browser WebSocket API cannot set custom headers during the handshake, so pure-browser clients such as noVNC cannot send X-Access-Token and will receive 403 on a direct connection. Use a WebSocket client that supports custom headers (such as wscat or Python websockets) to send X-Access-Token and complete the RFB handshake. If you only need to view the result, connect over CDP and call page.screenshot().

Window and screen size

Since browser image v0.0.37, the browser window and virtual screen size are controlled by three environment variables in the image:

Environment variablePurposeDefault
RESOLUTIONXvfb virtual screen resolution (WxHxdepth)1680x1050x24
BROWSER_WINDOW_SIZEChrome startup window size (--window-size)Width and height from RESOLUTION
VNC_CLIPClipping area of the VNC live streamSame as the window size

The envs parameter of Sandbox.create is only injected into command-execution processes inside the sandbox and does not affect the browser stack. To change the window size, bake the environment variables into a custom image with a Dockerfile, push it to an image registry, and then build the template with from_image:

FROM fc-e2b-registry.cn-beijing.cr.aliyuncs.com/runtime/browser:v0.0.44

ENV RESOLUTION=1920x1080x24
ENV BROWSER_WINDOW_SIZE=1920x1080
ENV VNC_CLIP=1920x1080

Then replace FROM_IMAGE with this custom image address when building the template; for other regions, replace the region in the image address with your sandbox region. The window size also determines the VNC live-stream area; the in-page viewport is still set by the client (Puppeteer, Playwright, and so on) over CDP.

Limitations

ItemConstraint
Browser supportCurrently ships with Chromium/Chrome