前阵子 Vercel 官宣了一个新工具,名字很直白:Vercel Browser Automation,翻译过来就是“Vercel 为 AI Agent 专门做的浏览器自动化服务”。这个工具解决的是我做 Agent 过程中最挠头的问题——让模型不只停留在“读接口、调模型、写代码”的层面,而是真的能打开一个浏览器,像人一样访问网页、点按钮、填表单、抓内容。
接触过的同学应该都有同感:本地 Node 环境里装 Puppeteer / Playwright 并不难,难的是让它们跑在服务器上、跑在无头容器里、跑在需要稳定长时间运行的 Agent 任务中。Vercel 这次把浏览器直接搬到了云上,Agent 通过一个 SDK 就能申请一个远程浏览器会话,再用自然语言或代码驱动它干活。对搞 AI 应用、自动化测试、数据采集的人来说,都值得花二十分钟看完这篇文章。
我下面会把为什么要用云端浏览器、这个工具的核心设计逻辑、安装到跑通的完整流程,以及我实测中踩过的坑全部捋一遍。如果你准备在项目里接入 AI Agent 浏览器能力,这篇可以做一份直接照抄的作业。
1. 为什么 AI Agent 必须“会开浏览器”
这部分先聊背景,不然你会发现光看官方 README 根本不知道它解决的是哪个具体问题。
1.1 只靠 API 交不了差的 Agent 任务
大模型本身只能处理文本和图片信息,但现实世界里的业务动作大量发生在网页上。举个例子,我帮朋友做过一个自动比价的小工具:几个电商平台都没有开放稳定的价格查询 API,想拿到实时价格只能去页面里找。如果 Agent 只会调 API,这种任务一步都走不动。
类似的需求还有:自动登录后台导出报表、定时去抢活动页面的名额、在 SaaS 系统里批量新建订单、根据搜索结果整理情报。这些任务对模型来说难度都不大,真正难的是“操作网页”这个物理动作。没有浏览器能力,Agent 就像一个推理能力很强但手被绑住的人,什么任务都只能停在“思考”阶段。
我知道有人会说,可以拿爬虫硬解析 HTML。但今天的网页普遍是 JavaScript 渲染出来的,页面上的按钮、弹窗、动态列表全都要等脚本执行完才出现在 DOM 里。用普通 HTTP 请求拿到的 HTML 往往只是一层空壳。浏览器自动化的价值就在于:它执行了真实的渲染流程,给到 Agent 的是一个跟人看到的一样的页面状态。
1.2 自建浏览器自动化的成本被低估了
过去 Agent 想操作网页,常规路线是本地装一个 Playwright 或者 Puppeteer,项目里维护一堆选择器,再自己处理登录态、页面等待、反爬策略。你自己电脑上跑 demo 没问题,一旦要上线就有连锁问题:无头浏览器在容器里安装字体和依赖、多任务并发导致资源占用飙升、崩溃后的重启策略、长时间会话的内存泄漏。
这些坑我基本都踩过一遍。最早我把 Puppeteer 塞进一个云函数,每次调用冷启动要在函数里下载 Chromium,一个任务跑下来光等待时间就超过实际操作时间。后来改成常驻服务器进程,又要处理多租户隔离,生怕某个 Agent 把共享浏览器目录写坏。所以当我看到 Vercel 把“浏览器实例”做成一款云服务时,第一反应是:这条路终于有人走通了——把运维复杂度收走,只暴露一个简单接口,跟模型工具调用天然契合。
1.3 这个工具真正适合的三类人
- 做 AI Agent 应用的人:想把浏览器变成模型的一个 tool,让 Agent 自主完成信息收集和页面操作。
- 做 Web 自动化脚本的人:受够了本地环境维护,希望用云浏览器降低部署成本。
- 做智能测试或数据采集的人:需要大量并发页面执行场景,但又不想养一批浏览器集群。
如果你属于以上任意一类,建议继续往下看。核心特性、安装方法、避坑记录都在后面。
需要模型API调用? 免费领10W Token,多模型网关一键接入 Claude、DeepSeek 等主流模型。
2. 核心特性与工作原理拆解
Vercel 这套浏览器自动化,本质上是一个远程浏览器服务。本地不用装浏览器,你只需要通过接口申请一个云端的浏览器页面实例,然后把指令发给它。
2.1 关键点一:云端会话,本地零依赖
我实测前最担心的是它会不会又要求本地装 Chromium。实际用下来完全不涉及,SDK 内部封装了和云端服务的通信,所有渲染、DOM、截图都在远端完成。集成到项目里只需要一个网络请求就能申请到浏览器会话,本地即使是一个特别精简的运行环境也能跑通。
这种设计的直接好处是部署下限很低。你在自己电脑上写好的 Agent 脚本,可以直接丢到服务端跑,不用担心服务器缺了某个系统库导致浏览器起不来。并发扩展也变成了云服务本身要解决的问题,我们自己的项目只管发请求、收结果。
2.2 关键点二:接口按“Agent 动作”设计,而不是按“浏览器 API”设计
老牌自动化框架暴露的接口通常偏底层,比如“启动浏览器”“创建上下文”“找到某个元素然后点击”。但 AI Agent 的使用场景不太一样,它说话的粒度更接近人类指令,比如“打开首页,搜索某关键词,把第一屏结果存下来”。
Vercel 这套工具在设计上把这个特点考虑进去了。它提供的接口大多是更上层的动作化接口:导航到某个 URL、点击页面里的文字或按钮、在输入框填入内容、提取当前页面文本、返回当前截图。Agent 选择要调用的工具时,一眼就能看出来“这个 function 是干嘛的”,不需要把底层 CDP 命令翻译成业务语言。
这个设计思路我特别喜欢。你想想,让模型去决定用 DOM.querySelector 还是 page.click 都是次要的,真正重要的是模型能不能理解“点一下页面上某处”这个高级意图。动作粒度接近人类习惯,模型就越容易做对。
2.3 关键点三:会话保持与上下文延续
Agent 执行一个复杂任务通常需要连续操作页面几十步,比如先登录、再搜索、再逐条打开结果页面。这期间浏览器状态不能丢。这套工具通过返回会话 ID 来维持上下文,同一个会话 ID 对应的页面状态、Cookie、localStorage 都是连续的。
我之前用无头浏览器最折腾的就是登录态管理。有些系统有复杂的验证流程,每次重新登录都很麻烦。有了会话保持机制,可以把关键登录步骤执行一次,后续任务直接复用会话,省掉了大量重复工作。
2.4 计费模型与配额
云浏览器的计费逻辑和我预想的一致,按会话的运行时长和资源规格计费,而不是按调用次数。单次短任务通常秒级计费,长时间挂着的会话才会明显产生费用。开发阶段一般有免费额度,具体配额会随产品迭代调整,建议直接用免费额度把整个流程跑通,再评估付费成本。
我个人的成本经验是:一个 30 步左右的页面操作任务,实际有效计费时间大概在 1 到 3 分钟,偶尔网络响应慢会拉长。一定要设置会话超时时间,否则 Agent 遇到页面卡死,会话无人回收,费用会一直累积(这个坑后面单独讲)。
3. 安装与接入完整流程
这一节直接上操作。整个接入可以分成几步:注册账号、开通服务、安装依赖、写第一段代码。我用的是目前公开仓库里比较常见的接入方式,包结构如果后续版本有调整,以官方文档为准。
3.1 前置条件
在开始前,先把下面这几样准备好:
- Node.js 18 及以上版本,我本地用的是 20 LTS。
- npm 或 pnpm,如果你用 Bun 也没问题,后面命令基本通用。
- 一个 Vercel 账号。没有的话去 vercel.com 注册,普通免费账号就能进入控制台,但开通浏览器自动化和领取 API Token 是在账号设置或项目设置里完成的。
登录账号后,我推荐先创建一个空项目来存放代码,因为后面在控制台开通云浏览器服务、绑定 API 权限时,跟项目关联会清晰些。当然你也可以只在本地建目录,不部署,不影响调用。
3.2 创建 API Token
在 Vercel 控制台的账号设置里找到 API Tokens 页面,点击创建。创建时注意权限范围,如果你只想开发调试,可以选最小权限;如果后面要部署到线上,再按需扩大权限。
创建成功后,把 Token 复制下来保存到一个不会泄露到 Git 仓库的地方。本地调试阶段我会直接写进 .env.local 文件,例如:
bash复制# .env.local
VERCEL_BROWSER_API_KEY=你的_token
注意:这个 Token 就相当于账号密码,一旦提交到了公开仓库,立刻去控制台吊销重建。我见过不止一个人把 Token 硬编码进代码又推到 GitHub,几小时内就被别人盗刷了资源。
3.3 安装依赖包
在项目根目录执行安装命令:
bash复制npm install @vercel/browser-automation
如果你打算配合 Vercel AI SDK 使用,需要再装 AI SDK 相关依赖:
bash复制npm install ai @ai-sdk/openai
我本地的包已经迭代过两个小版本,前一个版本的导出名称和现在的略有不同。当你发现导入报错时,优先去官方仓库看最新示例,不要盲目照抄网上旧代码。这也是我自己的一个习惯——这个产品迭代太快,文档更新往往比第三方教程及时。
3.4 最小可用示例
安装完成后,写一个最简单的脚本,验证整个链路是否打通。
先创建一个 basic-demo.mjs,内容如下:
javascript复制import { VercelBrowser } from "@vercel/browser-automation";
import "dotenv/config";
const browser = new VercelBrowser({
apiKey: process.env.VERCEL_BROWSER_API_KEY,
});
// 1. 申请一个云端浏览器会话
const session = await browser.createSession({
timeoutMs: 5 * 60 * 1000, // 会话 5 分钟无操作后自动回收
});
try {
// 2. 访问一个页面
await session.navigate("https://example.com");
// 3. 把当前页面的可见文本提取出来
const content = await session.extractText();
console.log(content.substring(0, 500));
// 4. 截图,便于人工确认页面状态
await session.screenshot({ path: "./first-page.png" });
} finally {
// 5. 无论成功失败,都要主动关闭会话
await session.close();
}
执行前先确认环境变量已加载,然后运行:
bash复制node basic-demo.mjs
如果一切正常,你会看到 example.com 页面上那段经典的英文示例文本被打印出来,同时目录下多出一张截图文件。到这步,说明你的本地环境和远程浏览器服务已经打通了。
3.5 拿到一个“能自主操作”的 Agent 示例
基础链路通了,接下来把它升级成一个真正让模型驱动的 Agent。思路是:把浏览器动作注册成 function tool,模型在生成过程中会决定何时调用。
下面这段代码是我项目里的简化版本,模型收到用户指令后会自主决定调用哪些浏览器动作:
javascript复制import { openai } from "@ai-sdk/openai";
import { generateText, tool } from "ai";
import { z } from "zod";
import { VercelBrowser } from "@vercel/browser-automation";
import "dotenv/config";
const browser = new VercelBrowser({
apiKey: process.env.VERCEL_BROWSER_API_KEY,
});
// 这个工具让 Agent 打开任意 URL
const navigateTool = tool({
description: "在浏览器中打开一个 URL,用于访问网页内容",
parameters: z.object({
url: z.string().describe("要访问的完整 URL,包含协议头"),
}),
execute: async ({ url }) => {
const session = await browser.createSession({ timeoutMs: 30000 });
try {
await session.navigate(url);
const text = await session.extractText();
return { pageText: text.substring(0, 2000) };
} finally {
await session.close();
}
},
});
const result = await generateText({
model: openai("gpt-4o"),
tools: { navigateTool },
prompt: "打开 https://vercel.com 首页,然后告诉我页面上主要展示了什么内容",
});
console.log(result.text);
这里有几个设计意图值得说一下:
- 我在工具内部创建会话后主动 close,避免每一个导航动作都留一个挂起的会话,减少费用浪费。
- 返回给模型的文本做了截断,控制 token 消耗。
z.object的结构化参数使得模型知道必须传 url,而且 url 格式是明确的。
如果你跑通了这段代码,那恭喜你,基本的“模型指哪浏览器打哪”已经实现了。
4. 实操过程与关键环节的实现细节
打通了样例只是第一步,真正写生产级 Agent 还有很多细节需要补。我挑几个最容易影响任务成功率的地方详细展开。
4.1 页面加载与元素等待策略
浏览器自动化最常见的问题就是“元素还没加载出来就点击”。网页里大量内容是异步渲染的,页面导航返回后,主框架可能已经就绪,但内部的按钮和数据区还在请求中。
实际操作中我建议遵循以下策略:
- 优先使用命令自带的“自动等待可交互”行为。Vercel 这套工具很多动作默认会等到目标元素出现才执行,这个特性值得利用。
- 需要手动等待时,用固定等待要克制。每页固定睡 3 到 5 秒会大幅拉长任务时长,增加成本。
- 最可靠的方案是提供一个“重试判断”逻辑:动作失败后,重新提取页面文本或检查指定文本是否出现,如果未出现再重试。
我实测中最稳定的一套模板是这样:
javascript复制async function retryUntil(page, fn, expect, maxRetry = 3) {
for (let i = 0; i < maxRetry; i++) {
try {
const result = await fn();
if (await expect(result)) return result;
} catch (e) {
// 记录这一次的失败信息
}
await sleep(1500);
}
throw new Error("重试多次仍然失败,页面可能结构变了或网络异常");
}
这套模板特别适合“点击后页面跳转再点击下一页元素”的序列。把网络抖动、渲染延迟都容忍掉了,同时不会盲目等待太久。
4.2 登录态与验证码处理
做真实业务时,很多页面都需要登录。跨任务的登录态复用是提效重点。我的做法是把登录成功后的会话 ID 存在缓存里,下次任务直接复用。
如果登录过程中出现了验证码,不要指望模型盲猜。实战经验是这类环节尽量人工介入一次,比如让 Agent 在遇到验证码时截图推送给人工,人工在外部完成验证后,Agent 再通过已保持的登录会话继续执行。我在一个内部工具里就是用这种“前几步人工登录 + 后续全自动”的模式,稳定运行了几个月。
4.3 会话超时与资源释放
这一节必须画重点。云浏览器资源是计费的,会话创建后如果因为逻辑异常没有关闭,会一直挂到服务端最长时限。遇到一次页面崩溃加上异常处理丢东西,就可能白白烧掉几十分钟计费时间。
建议从三个层面控制:
- 每个
createSession都要传timeoutMs,给一个业务能接受的最长执行时间。 - 所有操作包在
try/finally中,异常也要执行session.close()。 - 在服务端加一层兜底:任务完成后统一清理没有正常关闭的会话,可以做成定时任务,也可以用 Vercel Cron。
这三个层面缺一不可。try/finally 防的是代码层面异常,定时清理防的是进程被杀或网络断连这些异常情况。
4.4 页面结构变化与选择器维护
写 Web 自动化的人都有同感:网站改版是常态,本周写得清清楚楚的选择器,下周可能全部失效。页面结构变化导致的失败是浏览器自动化项目中最常见的故障来源。
我的应对思路是尽量让模型根据页面语义操作,而不是把它绑死在特定 DOM 选择器上。比如按钮更新了文案,用“点击页面上包含‘提交订单’文案的元素”这种描述,比写死某个 CSS 类名健壮得多。Vercel 这套工具的高层动作接口刚好支持这类语义级操作,这是它跟传统自动化框架体验上最大的区别。
不过仍要承认,云端浏览器无法覆盖极端复杂的页面交互,比如那种重度的拖拽画布编辑器、特殊的富文本编辑框。遇到这类极端场景,还是老老实实找网站方要 API 或人工处理。
5. 常见问题与排查技巧实录
我把自己踩过的坑按问题现象整理成了一份速查表,遇到类似情况可以照表排查:
| 问题现象 | 可能原因 | 排查和解决办法 |
|---|---|---|
| 创建会话返回 401 | API Token 没配对或权限不足 | 检查环境变量是否加载,重新生成 Token 后更新 |
| Agent 报错说找不到输入框 | 页面未加载完或输入框在 iframe 里 | 先等下异步元素,再输出页面文本看实际渲染结果 |
| 页面访问速度极慢 | 目标网站对海外节点做了网络限速 | 绕开对地区敏感的站点,或降低任务并发量 |
| Token 消耗异常高 | 每次动作都把整页文本传给模型 | 截取正文区域,去除脚本和导航菜单 |
| 会话频繁超时被回收 | 任务周期过长 | 拆分成多个子任务,用保存状态的方式衔接 |
| 点击后没有反应 | 页面弹窗拦截或按钮被遮挡 | 截图观察当前状态,必要时模拟页面顶部弹窗的关闭操作 |
| 免费额度耗尽后突然不可用 | 未关注配额告警提醒 | 设置配额告警,或者直接升级为付费方案 |
表格里每一条都是我遇到过的真实情况,下面挑几个单独展开聊。
5.1 模型把整页文本都吞了
第一次接 AI Agent 时,我以为给模型的上下文越丰富越好,于是每次动作后都把整页文本返回给模型。结果发现一次简单操作要消耗好几万 token,且页面导航越多消耗越离谱。
解决思路是提取内容时做重点过滤,优先正文区域,忽略头部导航、底部版权、脚本生成的无意义字符。现在我通常会把页面截成几个区块,分别提取文本,再拼接成结构化摘要返回给模型,token 消耗直接下降一个量级。
5.2 iframe 里的输入框死活找不到
有一次 Agent 要操作一个嵌在 iframe 里的表单,普通的文本提取和点击都碰不到它。排查后发现工具对 iframe 内容的支持是分层的,需要通过专门的 frame 切换接口进入内层文档。
如果你遇到类似问题,优先观察返回的页面数据结构里有没有 iframe 相关的入口。没有显式入口就要考虑换交互策略,比如用页面里的链接直接构造目标 URL,绕过 iframe。
5.3 登录环节反复失败
我遇到最多的情况是登录按钮触发了双重人机校验。页面提示“检测到异常环境”或者要求滑块验证,直接导致任务中断。
这个问题的核心判断是:不要跟反自动化策略硬刚。我后来开发的方案是允许 Agent 发起人工协助请求,界面端把当前页面截图推给值守者,值守者在自己的浏览器里确认后,远程会话继续往下走。这个机制虽然增加了一点人工成本,但整体任务完成率从不到五成提升到了九成以上。
6. 一些值得提前规划的后续扩展
前面几节覆盖了从安装到上线的基本路径。最后分享几个我在实际项目里沉淀下来的拓展思路。
- 与定时任务搭配:把浏览器 Agent 注册成 Vercel Cron 任务,每天早上定时去目标站点采集数据,把结果写到数据库或发送通知。
- 与消息通道配合:我经常把 Agent 的操作结果截图直接推送到群机器人,方便非技术人员也能看到每一步操作过程。
- 多会话并行:真实任务里的验证码登录通常会成为瓶颈,一次登录后会产生多个可用会话,并行消费相同登录态,可以明显提升大批量页面处理速度。
- 构建可观测面板:记录每次操作的动作序列、耗时、token、费用,对优化 prompt 和定位页面结构变化会有很大帮助。
我最深的体验是,云端浏览器这套东西的价值不在于省掉装一个 Chromium,而在于把“浏览器能力”从需要自己运维的底层资源,变成像数据库、对象存储一样按需调用的云资源。AI Agent 因为这一点,才能真正突破“只会说不会做”的瓶颈。
工具还在快速迭代,接口和配额都会变化,希望这篇实测记录能帮你在接入时少走几步弯路。如果你按文中的步骤搭通了,或者遇到了我上面没覆盖到的问题,欢迎在自己的项目实践中继续摸索——这种东西,只有跑过真实任务才能体会到里面各种细节的分量。
