browser 模板提供雲原生瀏覽器運行環境,支援通過標準的 Chrome DevTools Protocol(CDP)over WebSocket 遠端控制運行在雲端隔離容器中的瀏覽器執行個體,原生相容 Puppeteer、Playwright 等自動化架構。
browser 模板不是開通即用,需要先從官方 browser 鏡像構建一個帶名稱的自訂模板,再用該模板建立沙箱。本頁只介紹能力、預設配置、構建與最小驗證、端點差異;BrowserUse、LangChain 等架構接入的完整教程見使用 Browser Use Sandbox。
功能特性
| 特性 | 說明 |
| 瀏覽器自動化 | 內建 Chromium/Chrome 瀏覽器,支援完整 Web 標準,原生相容 Puppeteer、Playwright 等自動化架構 |
| CDP 遠端控制 | 通過標準 CDP 協議 over WebSocket 精準操控動態渲染頁面(SPA),穩定維持登入態與 Session |
| VNC 即時可視化 | 內建 VNC 服務,支援通過 noVNC 用戶端即時查看瀏覽器案頭環境,方便調試和監控 |
| 安全隔離 | 每個 browser 沙箱執行個體擁有獨立的檔案系統和進程空間 |
| 傳輸加密 | 所有資料面端點(CDP 和 VNC)均使用 WSS(WebSocket Secure)協議,全程加密 |
預設配置
| 配置項 | 預設值 | 說明 |
| 容器鏡像 | fc-e2b-registry.cn-beijing.cr.aliyuncs.com/runtime/browser:v0.0.44 |
預置 browser 鏡像 |
| 預設連接埠 | 3000 | 沙箱服務監聽連接埠 |
| CPU | 4 vCPU | 推薦起始規格 |
| 記憶體 | 8192 MB | 推薦起始規格 |
| 磁碟大小 | 15360 MB | 建議 15 GB 以獲得充足的臨時儲存空間 |
構建與最小驗證
browser 模板的用法分為兩個階段:先構建模板(從 browser 鏡像固化出一個帶名稱的模板),再運行模板(建立沙箱、等待健全狀態檢查、通過 CDP 開啟頁面並截圖)。
樣本使用北京地區鏡像。其他地區請將鏡像地址中的地區替換為雲沙箱接入地區,並保持版本為 v0.0.44;E2B_API_KEY、E2B_API_URL、E2B_DOMAIN 也需通過環境變數(如 .env 或 export)配置為同一地區,SDK 會自動讀取,無需在方法調用中顯式傳入。串連 CDP/VNC 端點時需在要求標頭攜帶 X-Access-Token:Python SDK 通過內部屬性 sbx._envd_access_token 擷取(後續版本可能重新命名或移除),JS SDK 通過 sbx.envdAccessToken 擷取(TypeScript 中為 protected 修飾,運行時可直接讀取)。
準備本地環境
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:使用如下 package.json,然後執行 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"
}
}
構建 browser 模板
從 browser 鏡像構建一個帶名稱的模板,構建時指定 CPU 與記憶體規格(推薦 4 vCPU / 8192 MB)。
Python:
"""browser 模板構建樣本。"""
import os
from dotenv import load_dotenv
from e2b import Template, default_build_logger
load_dotenv()
# SDK 自動讀取 E2B_API_KEY / E2B_API_URL / E2B_DOMAIN 環境變數。
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 模板構建樣本。
import { Template, defaultBuildLogger } from 'e2b';
// SDK 自動讀取 E2B_API_KEY / E2B_API_URL / E2B_DOMAIN 環境變數。
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}`);
運行模板並驗證
建立沙箱後,先輪詢 /health 等待 browser 服務就緒,再通過 CDP 端點串連 Playwright 開啟目標頁並截圖。
Python:
"""browser 模板運行樣本:建立沙箱 -> 等待健全狀態檢查 -> CDP 自動化 -> 截圖。"""
import time
from e2b_code_interpreter import Sandbox
from playwright.sync_api import sync_playwright
# SDK 自動讀取 E2B_API_KEY / E2B_API_URL / E2B_DOMAIN 環境變數。
BROWSER_PORT = 3000
def wait_until_healthy(sbx: Sandbox, host: str, token: str, timeout: int = 60) -> None:
"""輪詢公網網關 /health 端點,直到 browser 服務就緒或逾時。"""
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 服務在 {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 # 公網網關要求 X-Access-Token,否則 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 模板運行樣本:建立沙箱 -> 等待健全狀態檢查 -> CDP 自動化 -> 截圖。
import { Sandbox } from '@e2b/code-interpreter';
import { chromium } from 'playwright-core';
// SDK 自動讀取 E2B_API_KEY / E2B_API_URL / E2B_DOMAIN 環境變數。
const BROWSER_PORT = 3000;
const sleep = (ms) => new Promise((resolve) => setTimeout(resolve, ms));
/** 輪詢公網網關 /health 端點,直到 browser 服務就緒或逾時。 */
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; // 服務未起時 curl 非 0 退出,異常同樣攜帶 stdout
}
if ((result.stdout || '').trim() === '200') return;
await sleep(2000);
}
throw new Error(`browser 服務在 ${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; // 公網網關要求 X-Access-Token,否則 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 端點
browser 模板通過 3000 連接埠暴露以下端點,均需在要求標頭攜帶 X-Access-Token 鑒權,<sandbox-host> 通過 SDK 的 sbx.get_host(3000) 擷取:
| 端點 | 路徑 | 用途 |
| 健全狀態檢查 | https://<sandbox-host>/health |
判斷 browser 服務是否啟動完成 |
| CDP 自動化 | wss://<sandbox-host>/ws/automation |
瀏覽器自動化,相容 Puppeteer 和 Playwright |
| VNC 即時資料流 | wss://<sandbox-host>/ws/livestream |
即時查看瀏覽器案頭,可通過 noVNC 用戶端查看 |
在沙箱內部可先探測 CDP WebSocket 握手是否正常,返回 101 Switching Protocols 即說明端點可升級為 WebSocket:
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
收到 101 Switching Protocols 後,服務端會繼續發送 WebSocket 資料幀,curl 可能一直等待到 -m 4 逾時並返回退出碼 28。這不表示握手失敗,應以響應中是否包含 101 Switching Protocols 為準。
瀏覽器 WebSocket API 不支援在握手時設定自訂要求標頭,因此 noVNC 等純瀏覽器用戶端無法攜帶 X-Access-Token,直接連接會返回 403。需使用支援自訂要求標頭的 WebSocket 用戶端(如 wscat、Python websockets)攜帶 X-Access-Token 完成 RFB 握手。如果只需查看結果,可通過 CDP 串連後調用 page.screenshot() 截圖。
視窗與螢幕尺寸
browser 鏡像 v0.0.37 起,瀏覽器視窗與虛擬螢幕尺寸由鏡像中的三個環境變數控制:
| 環境變數 | 作用 | 預設值 |
RESOLUTION |
Xvfb 虛擬螢幕解析度(寬x高x色深) | 1680x1050x24 |
BROWSER_WINDOW_SIZE |
Chrome 啟動視窗大小(--window-size) |
取 RESOLUTION 的寬高 |
VNC_CLIP |
VNC 即時資料流的畫面裁剪地區 | 與視窗大小一致 |
Sandbox.create 的 envs 參數只注入沙箱內的命令執行進程,不會影響瀏覽器棧。因此調整視窗尺寸需要先用 Dockerfile 把環境變數烤進自訂鏡像,推送到鏡像倉庫後再通過 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
構建模板時將 FROM_IMAGE 替換為該自訂鏡像地址即可,其他地區請將鏡像地址中的地區替換為雲沙箱接入地區。視窗尺寸同時決定 VNC 即時資料流的畫面範圍;頁面內視口仍由 Puppeteer、Playwright 等用戶端通過 CDP 自行設定。
使用限制
| 限制項 | 約束 |
| 瀏覽器支援 | 目前內建 Chromium/Chrome 瀏覽器 |
相關文檔
-
使用 Browser Use Sandbox(BrowserUse、Puppeteer 等架構接入完整教程)
-
All-In-One 模板(需要同時使用瀏覽器和代碼執行能力時選擇)