单项目深读

browser-use:让 LLM 直接操控浏览器的 Python Agent 框架

browser-use 用自然语言指令驱动浏览器完成点击、填表与信息提取。

|INS-0015

一句「Find the number of stars of the browser-use repo」,程序打开浏览器、访问页面、读取数字、返回结果——中间没有一行选择器,没有一个 page.click()。这是 browser-use 想让你习惯的编程方式:把「怎么做」交给模型,你只描述「做什么」。

但真正值得拆的不是这个演示,而是它为了让这件事在生产环境里成立,堆了多少层东西。

三条路径,一个内核

README 一上来就把产品拆成三条入口,这个划分本身就说明了项目的定位——它不是「一个库」,而是「一个浏览器 Agent 能力」的三种交付形态:

路径形态谁在跑 Agent浏览器在哪典型使用者
Path 1Fully Hosted CloudBrowser Use 云端云端(stealth、住宅代理、验证码求解)要规模化跑任务、不想管基础设施的团队
Path 2CLI你已有的 Agent(Claude Code、Codex、Cursor 等)本地或云端想给自己手上的编码 Agent 加一双「手」的开发者
Path 3Python Library你自己的 Python 进程本地 Chrome 或云端要把 Agent 嵌进自己应用的工程师

关键区别在 FAQ 里写得很清楚:cloud browser 托管的是浏览器,fully hosted API 连 Agent 一起托管。也就是说,Path 3 里你换成 Browser(use_cloud=True),变化的是「浏览器跑在哪」,Agent 的推理循环仍然在你自己的进程里;而 Path 1 是连这个循环都不用你写。

这三条路径共享同一个内核:一个由 LLM 驱动的「观察—决策—动作」循环。下面按 Path 3 的代码把它拆开。

循环里到底有什么

从 README 的 quickstart 能直接读出四个核心组件,它们构成了 Agent 的最小骨架:

python
import asyncio from browser_use import Agent, Browser, ChatBrowserUse, ChatOpenAI from dotenv import load_dotenv load_dotenv() async def main(): llm = ChatOpenAI(model='gpt-5.6-luna', reasoning_effort='xhigh') # llm = ChatBrowserUse(model='bu-2-0') # Use BU2 instead; requires BROWSER_USE_API_KEY agent = Agent( task="Find the number of stars of the browser-use repo", llm=llm, # browser=Browser(use_cloud=True), # Use a cloud browser; requires BROWSER_USE_API_KEY ) history = await agent.run() print(history.final_result()) if __name__ == "__main__": asyncio.run(main())

四个组件各自的位置:

  • Agent:编排者。持有 task(自然语言目标)、llm(决策模型)、browser(执行环境),暴露 run() 返回一个 history 对象。注意返回值不是字符串而是 history——说明它保留的是完整执行轨迹,final_result() 只是从中取最终答案。这个设计对调试很重要:任务失败时你能回看每一步。
  • llm:决策层。README 给了两条路线,ChatOpenAI 走任意第三方模型,ChatBrowserUse(model='bu-2-0') 走自研的 BU2。两者接口对齐,替换只改一行。
  • Browser:执行层。Browser(use_cloud=True) 是唯一的开关,决定浏览器是本地起还是连云端。README 明确写了云端「no Chrome to install; works in Docker, CI, and serverless」——这是它存在的主要理由,不是性能,是部署形态。
  • history:结果层。承载轨迹与最终输出。

一次 await agent.run() 内部的流转,按 README 的功能描述可以归纳成这样的分层:

  1. 任务层:task 字符串进入 Agent,成为整个循环的目标约束。
  2. 感知层:浏览器把当前页面状态(DOM、可交互元素)整理成模型能读的表示,喂给 LLM。这是整个项目最脏最难的活——网页是给人看的,不是给模型看的。
  3. 决策层:LLM 基于任务 + 当前页面状态,输出下一步动作。
  4. 动作层:动作被执行到浏览器上(点击、输入、导航等),页面状态改变,回到第 2 步。
  5. 终止层:模型判断任务完成,结果写入 history,final_result() 可取。

这个循环没有魔法,难点全在「感知层怎么把网页压成模型能消化的上下文」和「动作层怎么保证执行可靠」——README 没有展开这两块的具体实现,但从它反复强调的能力(stealth、CAPTCHA solving、residential proxies)能反推出:真实网页上的失败大多不是模型不够聪明,而是被反爬挡住、被验证码卡住、被环境差异绊住。

换模型只是换一行,换浏览器也只是换一行

这套抽象的设计意图很明确:把「智能」和「环境」这两个变量解耦。

模型侧,README 的 FAQ 说 ChatBrowserUse 接受带 provider 前缀的模型 ID,也就是说 Claude、GPT、Gemini 都能通过同一个入口调用。官方推荐的是自家的 BU2,理由是「optimized for browser automation」,并指向 model card 和 benchmark 做对比。这里要诚实:README 里没有给出任何具体的成功率数字,只提到 BU Bench V2 是一个「very hard benchmark」,展示的是 60 个任务的子集结果。要选模型,得自己去看那份 benchmark。

环境侧,Browser 的三种形态覆盖了从本地调试到无头部署的全谱:

浏览器形态配置方式前置条件适用场景
本地浏览器默认(不传 browser)本机装有 Chrome开发调试、需要登录态
云端浏览器Browser(use_cloud=True)BROWSER_USE_API_KEYDocker、CI、serverless
已有远程浏览器通过 CDP 连接一个可连的 CDP 端点复用已开着的浏览器会话

第三行来自 README 对 Claude toolsets 集成的描述:「can control a local browser, a Browser Use Cloud browser, or an existing remote browser over CDP」。CDP 这个关键词也出现在仓库 topics 里,说明它不是附带能力,而是底层协议。

云端浏览器的定价 README 写得很直白:$0.02 per browser-hour plus network traffic。这个数字反复出现(官网描述里也是 $0.02/hour),可以放心引用。它附带的能力清单是:stealth、住宅代理、验证码求解、live view URL。live view 这一项对调试很实用——你能实时看到 Agent 在页面上干什么。

当 Claude 需要一个浏览器

README 里有一段容易被略过但信息量很大的内容:Browser Use 为 Claude 提供了官方维护的 toolset 集成。

它的定位很清晰——Claude 是大脑,Browser Use 是手。README 说 Browser Use 实现了全部 31 个 browser actions,通过 Anthropic SDK 暴露给 Claude 调用,另外还带一个 Bash 工具用于处理数据和写文件。架构图上标明了分工:浏览器可以本地也可以远程,但 Bash 跑在 SDK 所在的主机上。

python
import os from anthropic import AsyncAnthropic from browser_use.integrations.toolsets_for_claude import Bash, BrowserUse task = 'Open example.com and report its page title.' driver = BrowserUse() # Or BrowserUse(use_cloud=True) bash = Bash(output_dir='outputs') async with driver, AsyncAnthropic() as client: runner = client.beta.messages.tool_runner( model=os.environ['ANTHROPIC_MODEL'], max_tokens=32_768, max_iterations=100, tools=[driver, bash], messages=[{'role': 'user', 'content': task}], ) result = await runner.until_done()

这段代码值得注意的地方有三个。第一,BrowserUse 和 Bash 都是上下文管理器,async with driver 负责资源的建立与释放——浏览器是有状态的重资源,这个约束是必要的。第二,max_iterations=100 是硬性护栏,防止 Agent 在某个页面上无限打转。第三,Bash 要求 Linux 或 macOS 上有 /bin/bash,Windows 得走 WSL——这是个真实的部署约束,不是可选项。

这个集成的意义在于:它把 browser-use 从一个「自己带 LLM 的框架」变成了「别人的 Agent 可以调用的能力层」。Path 2 的 CLI 是同一个思路的另一种包装——README 让你把一段安装 prompt 直接粘给 Claude Code、Codex、Cursor 之类的工具,让它们自己把 browser-use 装好并连上浏览器。它甚至准备了失败兜底:装不上就去看 browser-harness 的 install.md。

和同主题项目比,它站在哪

把几个同主题项目摆在一起,定位差异比单个项目的功能列表更能说明问题:

项目语言核心抽象解决的核心问题与 browser-use 的差异
browser-usePythonAgent + Browser + LLM 三元组让模型直接操作真实网页唯一以「浏览器」为第一公民,环境问题(stealth/代理/验证码)是产品的一部分
deepseek-harnessTypeScript插件按需组装 Agent 能力通用编排框架,浏览器只是它可能接入的众多工具之一
graphifyPython知识图谱让 Agent 读懂代码库全貌解决的是「上下文从哪来」,browser-use 解决的是「动作往哪去」
TradingAgentsPython多角色 Agent 协作金融决策的辩论式推理垂直领域多 Agent,browser-use 是单 Agent 的通用执行层
reaTypeScript逆向分析 Agent从行为到二进制的安全分析同样是「Agent 操作系统」,但目标是闭源程序而非网页

最能说明问题的是和 deepseek-harness 的对比。后者把工具调用、prompt 编排都拆成插件,本质是一个组装框架——它不关心你的工具是浏览器还是数据库,只关心怎么把它们拼起来。browser-use 反过来:它把浏览器这一件事做到很深,深到连「怎么绕过反爬」「怎么解验证码」都做成了产品的一部分。

这也是为什么它的 topics 里同时有 playwright 和 cdp、stealth-browser、cloud-browser、remote-browser。Playwright 是通用的浏览器自动化库,browser-use 站在它(或类似的 CDP 层)之上,把「写脚本」换成「下指令」。它没有取代 Playwright,而是给 Playwright 加了一个会思考的上层。

它适合谁,不适合谁

从 README 的三条路径反推,适用边界其实很清楚。

适合:任务目标能用一句话描述、但执行路径依赖页面实时状态的场景——订一个驾考时间(README 首页的演示就是「handle the CAPTCHA, and book a driving test」)、在多个站点采集结构化信息、给已有的编码 Agent 补上「打开网页看看」的能力。这类任务的共同点是你写不出稳定的选择器,或者写出来也很快会失效。

不太适合:需要确定性、可重放、零成本的批处理。每跑一次都要过一遍 LLM,成本和延迟都是硬开销;云端浏览器按 $0.02/小时计费,流量另算。如果你的目标页面结构稳定、路径固定,手写脚本仍然更快更便宜。

部署上要注意:Python 版本要求 >= 3.11,README 的示例用 uv 管理并建议 --python 3.12。没有本地 Chrome 的环境(Docker、CI、serverless)必须切到云端浏览器,也就必须有 BROWSER_USE_API_KEY。想用 BU2 模型同样需要这个 key。换句话说,纯本地、纯第三方模型的组合是可行的,但只要想要官方优化的模型或托管浏览器,就得接上它的云服务——这也是这个开源项目与其商业产品之间的接缝所在。

项目坐标

先把硬数据摆出来:

MIT 许可 + 上万 forks + 持续推送,说明它既被大量使用也被大量改造。568 个 open issues 对一个这个量级的项目不算异常,但也提示你:真实网页的边界情况是无穷的,这个领域没有「装好就不用管」的状态。

如果只记一件事:browser-use 的价值不在于「让 LLM 点按钮」这个演示,而在于它把浏览器 Agent 落地时那些不体面的部分——反爬、验证码、代理、无头环境、模型选型——都收进了同一套抽象里。Agent、Browser、ChatOpenAI/ChatBrowserUse 三个名字,就是它给你的全部接口面。剩下的复杂度,它替你扛了,也替它自己定价了。