使用 Browser Use Sandbox

更新时间:
复制 MD 格式

Browser Use Sandbox 面向需要访问网页、点击按钮、填写表单、截图归档或抓取动态页面的 Agent。推荐基于 browser 模板 创建沙箱:3000 端口提供 browser 服务,可通过 CDP 连接 Puppeteer、Playwright 或 BrowserUse。

如果任务只涉及网页访问、点击、截图、下载文件和轻量结果提取,使用 Browser Use Sandbox 即可。如果浏览器产物还需要在同一会话中交给 Python/Node.js 做数据清洗、表格分析或报告生成,优先使用 AIO Sandbox

适用场景

场景说明
网页数据采集访问动态页面,提取标题、正文、表格、链接或业务字段
运营后台自动化登录后台,填写表单,点击按钮,下载报表或截图归档
页面巡检定时打开页面,验证关键元素、截图、性能或可用性
轻量 E2E 测试在隔离浏览器环境中运行端到端测试,避免污染 CI Worker
浏览器工具型 Agent让 Agent 通过 BrowserUse 等框架完成多步骤网页任务

推荐流程

  1. browser 模板 构建业务模板,例如 my-browser-template

  2. 使用模板创建沙箱,并设置合理的超时时间。

  3. 通过 sandbox.get_host(3000) 获取 browser 服务公网 host。

  4. 轮询 /health,确认 browser 服务已经就绪。

  5. 通过 wss://<sandbox-host>/ws/automation 连接 Puppeteer、Playwright 或 BrowserUse。

  6. 执行网页访问、点击、输入、截图、PDF 生成或下载。

  7. 将结构化结果、截图、HTML、PDF 或下载文件保存到沙箱任务目录。

  8. 业务侧读取结果后销毁沙箱。

准备本地环境

以下示例使用 Node.js 和 Puppeteer Core。业务侧不需要安装完整浏览器,因为 Chromium/Chrome 已运行在 browser 沙箱中。

{
  "name": "browser-use-sandbox-demo",
  "version": "1.0.0",
  "type": "module",
  "dependencies": {
    "e2b": "^2.31.0",
    "puppeteer-core": "^24.0.0"
  }
}

Puppeteer 示例

示例流程如下:

  1. 创建 my-browser-template 沙箱。

  2. 等待 browser 服务 /health 返回 200。

  3. 通过 CDP 连接云端浏览器。

  4. 打开 https://example.com,提取页面信息并保存截图。

import { writeFile } from "node:fs/promises";
import puppeteer from "puppeteer-core";
import { Sandbox } from "e2b";

const TEMPLATE = process.env.E2B_BROWSER_TEMPLATE || "my-browser-template";

const BROWSER_PORT = 3000;
const TARGET_URL = "https://example.com";
const TASK_DIR = "/tmp/browser-task";
const SCREENSHOT_PATH = `${TASK_DIR}/browser-example.png`;

const sleep = (ms) => new Promise((resolve) => setTimeout(resolve, ms));

function toArrayBuffer(bytes) {
  return bytes.buffer.slice(bytes.byteOffset, bytes.byteOffset + bytes.byteLength);
}

async function waitUntilHealthy(sandbox, host, token, timeoutMs = 60_000) {
  const tokenHeader = token ? `-H 'X-Access-Token: ${token}' ` : "";
  const deadline = Date.now() + timeoutMs;

  while (Date.now() < deadline) {
    let result;
    try {
      result = await sandbox.commands.run(
        `curl -sS -o /dev/null -w '%{http_code}' -m 4 ` +
          tokenHeader +
          `https://${host}/health`,
        { timeoutMs: 10_000 },
      );
    } catch (error) {
      result = error;
    }

    const code = (result.stdout || "").trim();
    if (code === "200") {
      return;
    }
    await sleep(2_000);
  }

  throw new Error(`browser 服务在 ${timeoutMs}ms 内未就绪`);
}

let sandbox;

try {
  sandbox = await Sandbox.create(TEMPLATE, {
    timeoutMs: 300_000,
  });

  const host = sandbox.getHost(BROWSER_PORT);
  const token = sandbox.envdAccessToken;

  await sandbox.files.makeDir(TASK_DIR);
  await waitUntilHealthy(sandbox, host, token);

  const browser = await puppeteer.connect({
    browserWSEndpoint: `wss://${host}/ws/automation`,
    headers: token ? { "X-Access-Token": token } : {},
  });

  const page = await browser.newPage();
  await page.setViewport({ width: 1365, height: 768 });
  await page.goto(TARGET_URL, {
    waitUntil: "networkidle2",
    timeout: 60_000,
  });

  const screenshot = await page.screenshot({ fullPage: true });
  await sandbox.files.write(SCREENSHOT_PATH, toArrayBuffer(screenshot));
  await writeFile("browser-example.png", screenshot);

  const result = await page.evaluate(() => ({
    url: location.href,
    title: document.title,
    text: document.body.innerText.replace(/\s+/g, " ").slice(0, 500),
  }));

  await browser.close();
  console.log(result);
} finally {
  if (sandbox) {
    await sandbox.kill();
  }
}

BrowserUse 接入

对于以自然语言驱动网页操作的 Agent,可以让 BrowserUse 连接 browser 沙箱暴露的 CDP 地址。业务服务负责创建和销毁沙箱;BrowserUse 只连接这个沙箱中的浏览器会话。

import asyncio
import os

from browser_use import Agent, BrowserSession, ChatOpenAI
from browser_use.browser import BrowserProfile
from e2b import Sandbox

BROWSER_PORT = 3000


async def main():
    browser_session = None
    sandbox = Sandbox.create(
        template=os.environ.get("E2B_BROWSER_TEMPLATE", "my-browser-template"),
        timeout=600,
    )

    try:
        host = sandbox.get_host(BROWSER_PORT)
        cdp_url = f"wss://{host}/ws/automation"

        browser_session = BrowserSession(
            cdp_url=cdp_url,
            browser_profile=BrowserProfile(
                headless=False,
                keep_alive=True,
            ),
            headers={"X-Access-Token": sandbox._envd_access_token},
        )

        agent = Agent(
            task="访问 https://example.com,提取页面标题并总结首屏正文",
            llm=ChatOpenAI(
                model=os.environ.get("QWEN_MODEL", "qwen-vl-max"),
                api_key=os.environ["DASHSCOPE_API_KEY"],
                base_url="https://dashscope.aliyuncs.com/compatible-mode/v1",
            ),
            browser_session=browser_session,
            use_vision=True,
        )
        result = await agent.run()
        print(result)
    finally:
        if browser_session is not None:
            await browser_session.stop()
        sandbox.kill()


if __name__ == "__main__":
    asyncio.run(main())

这类接入方式适合搜索、比较、填写表单、点击确认和生成截图证据。需要稳定产物时,让 Agent 把关键结果写成 JSON,同时保留截图或 HTML 片段,便于人工复核和问题追踪。

上线建议

  • 把每个浏览器任务限制在明确的 URL 范围内,必要时增加域名白名单。

  • 限制下载文件类型、单文件大小、总输出大小和任务生命周期。

  • 页面内容可能包含 prompt injection。不要让 Agent 未经校验地执行网页中的指令。

  • 登录态、Cookie、账号凭证和业务 Token 应按任务隔离,通过运行时注入,不写入模板。

  • 记录 URL、截图、关键 DOM 摘要、工具调用轨迹和结果文件路径。

  • 如果需要人工观察或调试,可通过 wss://<sandbox-host>/ws/livestream 连接 noVNC。

  • 如果任务需要在浏览器操作后继续运行 Python/Node.js 脚本处理数据,使用 AIO Sandbox

相关功能