ARTICLE DETAIL

建站实战干货

来自一线的建站与推广经验沉淀,每一条都经过真实交付验证。

browser-use实战:让AI Agent真正操控浏览器完成自动化任务

2026/10/2 19:04:44 拓冰建站 浏览量
browser-use实战:让AI Agent真正操控浏览器完成自动化任务 这段时间AI Agent的话题特别热但很多朋友问我Agent到底能帮我们干什么说实话早期接触Agent的时候我也觉得它有点“纸上谈兵”——能写代码、能回答问题但真要让它去完成一个实际操作比如帮我查个资料、填个表单、对比几个网页的价格它就没辙了。原因很简单Agent的“手”没伸出来它只能通过API跟外部世界对话真实世界的浏览器它根本碰不到。browser-use 就是我这段时间实测下来非常好用的一个开源项目。它把大语言模型和浏览器控制彻底打通给Agent一个浏览器让它可以像人一样点击、输入、滚动、翻页、提取内容从“只能说说”变成“真的去做”。如果你正在研究AI Agent怎么落地或者想从0到1搭建属于自己的AI Agent应用这个项目值得认真玩一玩。这篇文章我会从原理拆解、环境搭建、核心实操、服务化改造、常见坑位几个方面把browser-use讲透。不管你是刚接触Agent的新手还是已经在做AI应用落地的开发者这篇都能帮你少走弯路。1. 为什么需要browser-useAI Agent的“最后一公里”1.1 传统Agent做不到的事先聊聊背景。现在各种“AI助手”满天飞但它们能做的事其实非常有限写文案、总结文档、回答百科类问题。这些任务有一个共同点——只发生在“对话”内部不需要操控外部工具。一旦任务变成“帮我去某某网站查一下今天的报价”、“帮我把这个表单填了并提交”、“把这个页面里的数据抓下来整理成表格”传统Agent就露馅了。问题在于它没有“手”。有一些Agent为了弥补这个短板会通过API去调第三方服务比如天气API、新闻API。但这有个很明显的问题API是别人规定好的接口功能写死了。网站没有开放API怎么办网站每天都在改版接口参数变了怎么办数据分散在不同网页结构里API拿不到怎么办这时候就需要Agent能像人一样直接打开浏览器看页面、点按钮、填信息。这不是“调接口”这是“用人操控电脑的方式去完成任务”。1.2 browser-use的定位给Agent装上一双“眼睛”和“手”browser-use的核心思路是把浏览器的能力抽象成一套“动作空间”然后交给大语言模型去决策。具体来说它干了两件事让LLM“看懂”网页。通过视觉截图和DOM结构提取把浏览器里呈现的内容转成LLM能处理的语言信息。让LLM“操作”浏览器。定义了点击、输入、滚动、跳转、提取等原子动作LLM每次输出一个结构化的动作指令由底层代码去执行。这是个“观察-决策-执行-再观察”的循环一直持续到任务完成。我用一个生活化的类比解释browser-use相当于给你请了一个“远程操控手”。你通过对话告诉它“去京东搜一下XX把前五条的价格列出来”它理解需求后自己打开京东在搜索框输入关键词点搜索滚动页面把结果标题和价格读出来整理成表格交给你。对你来说整个过程就是一句话的事。1.3 它和Selenium/Playwright这类自动化工具的区别这一块很多人容易混淆我提前说清楚。Selenium和Playwright也是浏览器自动化工具但它们和browser-use完全不是一个物种。Selenium/Playwright解决的是“自动化执行固定脚本”的问题。你要先写清楚步骤打开网址、等待元素出现、输入用户名、点击登录按钮。每一步都是写死的页面一变脚本就废了。browser-use解决的是“让AI自主完成动态任务”的问题。你不需要把每一步都写下来只需要告诉它“你想干什么”它自己判断每一步怎么走。底层虽然也用到了Playwright来操控浏览器但决策层完全是LLM在驱动。简单说Selenium是“遥控器”browser-use是“驾驶员”。遥控器得由人一步步按按钮驾驶员自己看路、自己打方向盘、自己踩油门。这个差异非常关键它决定了browser-use适合解决“非确定性”任务——那些没有固定步骤、需要临场判断的操作。2. browser-use核心原理拆解它是怎么“看懂”网页并决策的2.1 双通道状态感知视觉与DOM结合要让LLM操作浏览器第一步是让它“理解”当前页面内容。browser-use采用两条通道感知页面状态第一是视觉通道。系统会对当前页面截图把截图作为图像输入发送给多模态大模型。大模型能看到页面的布局、按钮的位置、颜色、图标这相当于“人眼看到的样子”。第二是DOM通道。系统会把关键DOM元素按钮、输入框、链接、文本节点的位置和属性提取出来构建一个可访问性树再转换成文本输入发送给大模型。这相当于“在后台读页面的HTML源码”。为什么要双通道因为视觉信息适合理解大体布局但细节比如一个链接的href、一个输入框的name属性视觉看不清楚DOM信息很精确但纯文本形式很难理解页面布局的层次。两者结合起来LLM对页面的理解才足够完整。这里有个细节值得注意browser-use对DOM的处理不是把整个HTML直接扔给LLM。HTML动辄几百KBToken根本不够用而且噪音很大。它会做智能裁剪只保留与交互相关的可操作元素。这个设计大大降低了Token消耗也提高了决策准确率。2.2 动作空间设计LLM输出就是“操作指令”理解页面之后LLM要输出动作。browser-use定义了一套JSON格式的动作指令集我列举几个常用的[ {action: go_to_url, params: {url: https://example.com}}, {action: click_element, params: {index: 5}}, {action: type_text, params: {index: 3, text: 关键词}}, {action: scroll, params: {direction: down, amount: 500}}, {action: extract_content, params: {description: 提取页面上所有商品的价格}}, {action: switch_tab, params: {page_id: 2}} ]每个动作对应浏览器里的一个真实操作。LLM每次输出一个JSONbrowser-use解析后执行执行完把新的页面状态反馈给LLMLLM再输出下一个动作。如此循环直到LLM判断任务完成输出结束标记。这套设计的妙处在于LLM不需要“写代码”来控制浏览器它只需要“描述动作”。无论底层浏览器有多少按钮、输入框在LLM的视角里所有页面元素都被编号了它只需要说“点击元素3”“在元素5里输入文字”大幅降低了决策难度。2.3 记忆与任务管理多步骤任务是怎么串起来的单一的“观察-决策-执行”循环只能处理简单的单步任务。真实场景下任务往往是多步骤的比如“先搜索再点进第一个结果提取正文返回搜索页搜索另一个关键词对比结果”。为了解决这个问题browser-use引入了类似Agent的记忆机制短期记忆当前页面的状态、最近的几次操作记录放在上下文里保证LLM知道“我现在到哪一步了”。任务规划LLM会先对整体任务做一个拆解形成一个计划列表每完成一步就在计划上打勾更新剩余步骤。错误恢复如果某个动作执行失败比如点击目标不存在LLM会收到错误信息它能自行调整策略换个方式继续。这套机制在代码层面的体现就是Prompt模板中嵌入了“当前任务描述已完成步骤页面状态可用元素列表风险提示”等模块。browser-use对Prompt工程的处理比很多同类项目细致这也是它效果好的原因之一。2.4 同类方案横向对比为什么我最终选了browser-use现在做AI操控浏览器的方案并不只有browser-use一个。OpenAI的Operator、Anthropic的Computer Use、开源的Skyvern等都在做类似的事。我做个简单的横向对比方案开源定位优点局限browser-use是浏览器自动化专用开源免费、动作定义清晰、社区活跃、可深度定制依赖外部LLM APIToken成本需自控OpenAI Operator否通用计算机操作闭源但体验完整区域受限、不可定制、成本高Anthropic Computer Use否通用桌面操作模型能力强API费用高、偏桌面场景Skyvern是自动化流程引擎偏向固定流程执行对LLM自主决策的支持不如browser-use灵活对比一圈下来browser-use最大的优势是“专注”。它把浏览器相关的动作抽象得足够精细又有很好的扩展机制加上开源、社区有大量案例所以最终我选择它作为主力工具。3. 环境准备与快速上手从0到1跑通你的第一个浏览Agent3.1 环境依赖清单动手之前先把环境准备清楚。browser-use基于Python 3.11推荐3.11或3.12依赖Playwright控制浏览器同时需要你有大模型API的访问权限。我实测下来完整的环境准备分三步第一创建独立的Python虚拟环境。AI项目依赖经常有冲突用venv或conda建一个独立环境是基本素质。python -m venv browser-env source browser-env/bin/activate # Windows上执行 browser-env\Scripts\activate第二安装browser-use主包和Playwright内核pip install browser-use playwright playwright install chromium这里有个小坑playwright install chromium在国内网络环境下可能下载很慢偶尔还会失败。如果遇到超时可以设置镜像源重试实在不行就多试几次或者手动下载浏览器包放到缓存目录。第三配置大模型API。browser-use默认支持OpenAI接口也支持Anthropic以及国内很多兼容OpenAI协议的服务。先用环境变量配置最省事export OPENAI_API_KEY你的key如果你用的是国内模型服务在初始化Agent时直接传对应的base_url和模型名即可这一点比很多只绑定OpenAI的框架友好很多。3.2 最小可用示例让它去完成任务装好之后写一个最小的Agent脚本感受一下效果。下面这段代码是我第一次跑通的版本非常简单import asyncio from browser_use import Agent, Browser async def main(): agent Agent( task打开百度首页在搜索框输入AI Agent点击搜索然后把搜索结果第一页的前五个结果标题列出来, browserBrowser() ) result await agent.run(max_steps20) print(result) if __name__ __main__: asyncio.run(main())这段代码的含义很直白task是你要Agent做的事用自然语言描述就行max_steps限制最大操作步数防止它陷入死循环run()会执行整个任务循环返回最终结果很多第一次跑browser-use的朋友看到的效果都会有点震撼浏览器真的自己开了、真的自己往搜索框里敲字、真的自己点了搜索结果、然后规规矩矩地把结果列表提取了出来。整个过程没有写任何选择器、没有写任何XPath、没有写任何“点击某个坐标”之类的指令全都是Agent自己判断的。3.3 核心参数配置模型、步数与成本控制跑通最小示例之后你可能会遇到几个问题Token消耗太快、等待时间太长、经常在某一步卡住。这些问题大多可以通过调参解决。browser-use的核心配置项有几个参数作用我的建议值max_steps最大操作步数简单任务10~20复杂任务30~50max_retries失败动作重试次数2~3model使用的LLM模型预算充足用强模型测试用小模型temperature模型温度0.1左右越低越稳定特别提醒browser-use一次任务会多次调用LLM API每一步决策都是一次调用。所以如果你用的是按Token计费的模型一个复杂任务跑下来Token消耗相当可观。我建议前期测试阶段尽量用便宜的模型跑通流程确认效果后再切到强模型。另外并发这一块要提前规划。browser-use本身是单任务执行的设计一个Agent实例操作一个浏览器页面。如果你要扛并发比如同时跑10个Agent做批量任务需要考虑几个层面浏览器实例隔离用Playwright的BrowserContext隔离多个会话每个Agent用独立的上下文避免互相干扰。任务队列调度并发请求不可能是无限的。用一个消息队列如CeleryRedis把任务排队控制同时运行的Agent数量。API限流控制LLM API有每分钟调用次数限制你需要算自己的并发上限。比如你的模型API每分钟允许60次请求每个任务平均15步一步一次调用那同时跑4个任务就是极限了超过必然报限流错误。4. 核心功能实战让Agent完成真实的业务任务4.1 实战一自动采集商品信息并整理成表格先来看一个贴近生活的例子采集某电商平台的商品信息。假设你要做市场调研需要搜集某个品类下前20个商品的名称、价格、销量和店铺名。手动操作一个人起码要忙半小时。用browser-use一段代码就搞定import asyncio from browser_use import Agent, Browser async def main(): agent Agent( task去某电商平台搜索机械键盘按销量排序 打开前3个商品详情页分别提取商品名称、价格、销量、优惠信息 最后汇总成JSON列表返回, browserBrowser() ) result await agent.run(max_steps30) print(result)这里有个关键点Agent在提取数据时不会像爬虫那样去解析特定的HTML结构。它会调用extract_content动作用自然语言描述“提取什么”browser-use会把页面上相关内容作为上下文发回LLM让LLM整理出结构化的JSON。这种方式的优点是页面改版了爬虫代码就废了但browser-use不会——它每次都是“现看现提取”页面怎么改都不影响它提取“价格”“名称”这类语义信息。4.2 实战二自动填写并提交表单表单填写是另一个高频场景。现实中有大量网站没有开放API用户只能手动填。browser-use在这方面非常好使await agent.run( task在注册页面填写表单姓名填张三邮箱填zhangsanexample.com 手机号填13800138000勾选同意用户协议点击提交按钮 如果出现错误提示把错误信息打印出来, max_steps25 )我用这个场景做过大量测试发现一个规律如果页面表单有明确的label文字比如“姓名”“邮箱”Agent的成功率很高基本90%以上。但如果表单是纯图标式设计只有图标没有文字labelAgent容易判断错误。所以遇到这种页面我会在task描述里写得更具体些比如“在页面上部找到输入框”。另外涉及验证码的场景目前browser-use还没有内置的验证码识别能力。图形验证码需要外接OCR服务滑块验证码就更复杂。这部分大家在实际使用中要有预期别拿它去做对抗验证码的任务。4.3 实战三UI自动化测试的“另类玩法”browser-use在UI测试领域也有一个很有意思的应用方式。传统UI测试是写死脚本后反复执行维护成本高。browser-use可以当作“探索性测试助手”你告诉它“这个页面有个登录表单帮我测试用户名密码错误时会不会出现提示”它会自己尝试输入错误信息、点击登录、观察页面变化、最后告诉你测试结果。这种“AI驱动的测试”目前还不够成熟不能完全替代传统自动化测试但作为冒烟测试和探索性测试的补充效率提升非常明显。特别适合产品快速迭代、没有时间维护繁琐测试脚本的小团队。4.4 实战四把browser-use嵌入更大的Agent框架browser-use还有一个重要的打开方式嵌入更大的Agent框架中。现在很多开发者在用LangChain/LangGraph搭建Agent应用。browser-use可以作为其中的一个“工具节点”负责所有需要浏览器操作的任务。比如数据分析Agent需要抓取实时数据时调用browser-use节点去执行邮件Agent收到用户需求后拆解任务把需要查询网页的部分交给browser-use处理个人AI助手需要帮用户订票、查快递、比价时底层都是browser-use在工作这种“工具化嵌入”的思路让browser-use的价值不止于一个独立脚本而是成为整个自动化系统的“执行器官”。如果你正在规划AI Agent学习路线我建议把browser-use这样的“工具类项目”作为一个重要的实践环节。光会写Prompt、调API不够真正让Agent做实事必须给它接上工具。5. 服务化改造用FastAPI把browser-use变成一个任务接口5.1 为什么需要服务化改造跑通几个Demo之后你会发现一个问题脚本是脚本应用是应用。想让browser-use真正成为产品的一部分不能只是本地跑脚本得把它封装成一个服务对外提供HTTP接口。这样做有几个明显的好处业务方不需要知道browser-use怎么用只需要提交任务描述服务端可以做并发控制和资源管理多个业务方可以共享同一个Agent服务。方案上我用FastAPI做了一层薄封装任务进队列后异步执行前端通过轮询或WebSocket拿结果。代码不复杂但工程上很实用。5.2 一个简单的任务服务Demo下面这个示例是一个最基础的任务接口服务import asyncio from datetime import datetime from fastapi import FastAPI, BackgroundTasks from pydantic import BaseModel from browser_use import Agent, Browser app FastAPI() tasks_db {} class TaskRequest(BaseModel): task: str max_steps: int 20 async def run_task(task_id: str, task_desc: str, max_steps: int): try: agent Agent(tasktask_desc, browserBrowser()) result await agent.run(max_stepsmax_steps) tasks_db[task_id] {status: done, result: str(result)} except Exception as e: tasks_db[task_id] {status: error, error: str(e)} app.post(/agent/task) async def submit_task(req: TaskRequest, background_tasks: BackgroundTasks): task_id datetime.now().strftime(%Y%m%d%H%M%S%f) tasks_db[task_id] {status: running} background_tasks.add_task(run_task, task_id, req.task, req.max_steps) return {task_id: task_id} app.get(/agent/task/{task_id}) async def get_task(task_id: str): return tasks_db.get(task_id, {status: not_found})这个Demo有几点需要注意BackgroundTasks是FastAPI内置的轻量后台任务机制适合开发调试生产环境建议换成Celery任务可靠性和持久化会好很多。每个任务都new一个Browser实例开销很大。更好的做法是用浏览器连接池复用Playwright的BrowserContext。任务并发数要加信号量限制否则几十个任务同时进来服务器内存直接爆掉。5.3 并发调度与资源管理方案关于“AI Agent怎么扛并发”我在这块踩过不少坑总结一下自己的处理方案。第一层是并发上限控制。我在任务入口加了一个asyncio.Semaphore限制同时运行的Agent数量。假设服务器内存是8GB每个浏览器上下文大约占300MB那同时跑4到6个Agent比较安全。第二层是LLM API限流。前面说过LLM API是并发链路中最容易被打爆的一环。我的做法是建立一个请求计数器在把任务交给Agent之前先估算它的步数上限乘以每步的API调用次数判断是否会超过分钟限流。超了就排队等下一轮。第三层是浏览器资源释放。browser-use每个任务开启一个浏览器上下文如果不显式关闭内存占用会持续增长。长时间跑任务的机器我会定期重启任务进程避免内存泄漏导致的崩溃。下面是我常用的一段BrowserContext池化逻辑的参考思路# 思路示例复用BrowserContext而不是每次新建 class BrowserPool: def __init__(self, max_contexts4): self.max_contexts max_contexts self.available [] self.lock asyncio.Lock() async def acquire(self): async with self.lock: if self.available: return self.available.pop() # 如果池中没有空闲等待或者新建受max限制 # 这里省略具体的context创建逻辑 pass async def release(self, context): async with self.lock: self.available.append(context)当然如果你的并发量不是很大直接用最朴素的“每次新建用完释放”也能跑只是要注意监控内存。6. 我踩过的坑与排查指南6.1 坑一Token消耗比想象中大得多第一个让我印象深刻的坑是Token。第一次跑一个10步左右的任务我以为消耗不了多少Token结果账单出来吓了我一跳。问题出在哪前面讲过browser-use每一步决策都要调用LLM而且每次调用要携带页面截图和DOM信息。多模态模型的图像Token比文本Token贵得多一个截图动辄上千Token。10步任务保守估计要消耗几万Token。我的优化经验设置合理的max_steps别让Agent“自由发挥”太多步。对于不依赖视觉信息的页面可以关闭视觉通道只用DOM信息能省不少Token。用价格低的模型跑流程验证最后再切强模型。把常见操作固化成快捷方式减少不必要的决策步数。6.2 坑二并发一高就报限流错误“AI Agent怎么扛并发”这个问题在社区里讨论得很激烈。browser-use的并发瓶颈主要是LLM API限流。我自己测试过4个Agent并发跑每个任务约15步共用同一个API Key不到两分钟就会触发限流。解决方案我用下来比较有效的有三个给每个Agent实例设置请求间隔错峰调用。用多个API Key做负载均衡。接一层缓存对相同或相似的页面状态直接复用之前的决策结果减少LLM调用。如果用的是自建模型服务把并发队列和速率限制配置好别让下游把上游打爆。6.3 坑三页面元素找不到、点击无效另一个高频问题Agent明明“看”到了页面上有个按钮执行点击时却提示元素不存在。排查下来最常见的原因有三个一是页面还在加载中元素是动态渲染出来的Agent截图时看到了但执行点击时DOM还没准备好。解决办法是增加动作间等待时间或者在任务描述里提醒Agent“等待页面加载完成”。二是页面有弹窗或遮罩层点击被遮挡了。browser-use有时识别不出页面上有个弹窗挡住按钮会去点底下的元素。这种情况下我会在任务里明确要求“先检查是否有弹窗有就关闭”。三是元素在iframe里。browser-use对iframe的支持目前不够完善跨iframe的元素定位容易出错。如果你经常需要操作iframe里的内容建议在任务描述里写清楚“这个元素在iframe中”Agent处理起来会更有预期。6.4 坑四网站风控与合规边界做浏览器自动化风控是绕不开的话题。browser-use是真实浏览器行为比requests爬虫隐蔽得多但并不是万无一失。一些风控严格的网站会检测自动化特征异常的鼠标轨迹、极快的操作速度、非人类的行为模式。我遇到过几次被拦截的情况同一个IP短时间内多次运行Agent网站直接弹出滑块验证。我的应对策略很简单控制运行频率别同一时间扎堆跑。设置合理的动作间隔让Agent的操作节奏看起来更像真人。必要时使用合规的代理IP池分散请求。对频繁被风控的站点降低任务强度。这里特别提醒一句做浏览器自动化一定要遵守目标网站的robots协议和用户协议只做合法的数据采集和自动化操作。别拿browser-use去做违规的事情风险很大不值得。6.5 常见问题速查表问题可能原因解决方案任务执行到一半报错退出浏览器崩溃或LLM API超时增加重试次数检查网络换稳定模型Agent一直重复同一个动作页面状态没变化LLM误判增加等待时间修改任务描述增加max_steps提取的数据格式不对LLM没有完全理解需求在task里把期望的JSON结构写清楚中文页面支持不好模型对中文DOM理解弱换支持中文更好的模型或提示词中强调用中文浏览器窗口一闪而过Playwright内核未正确安装重新执行playwright install chromium本地运行出现SSL证书报错部分网站证书链不完整在Playwright配置里设置ignore_https_errors7. 几点实操体会文章写到这里最后分享几个我个人用得比较多的技巧和心得。第一任务描述一定要具体。browser-use对模糊指令的理解不如对明确指令好。“去搜索一个东西”这种描述Agent会懵。但“打开某网站在搜索框输入某关键词点击第一个结果提取页面上的价格”这种具体描述它的表现会好很多。本质上LLM擅长的是执行不是猜你的意图。第二browser-use的Prompt模板是可以自定义的。如果你希望Agent在某些特殊场景下有不同的行为习惯比如更谨慎的点击、更详细的日志输出可以去改它的系统提示词模板。这个项目比较开放很多行为逻辑都能调整。第三如果要上生产环境建议把browser-use封装成任务管理服务放到消息队列后面通过API对外提供服务。这样每个业务方只需要提交任务描述服务端负责调度、并发、结果汇总整个系统的稳定性和可维护性会高很多。第四注意浏览器资源的释放。browser-use每个任务开启一个浏览器上下文如果不显式关闭内存占用会持续增长。长时间跑任务的机器我会定期重启任务进程避免内存泄漏导致的崩溃。根据我的经验browser-use这类“让LLM操控真实工具”的思路后续还有很大的扩展空间。比如跟本地文件系统打通、跟命令行打通、跟更多专业软件打通。AI Agent的“手脚”会越来越齐全未来一定会有更多“把AI撒出去干活”的落地场景。如果你正在做AI Agent相关的项目browser-use值得认真研究一下。它可能不是你想象中的那种“全自动万能机器人”但它确实能把AI从“聊天框”里放出来让它真正碰一碰真实世界里的网页。