给 Agent 配联网能力,最重的一步往往是浏览器——Puppeteer、Chromium 一挂,几百 MB 内存起步,服务器上跑一晚上就知道了。其实大多数场景要的只是「搜一下、把正文拿回来」,不值得为一件事养一个浏览器。Brave Search 就是冲着这个痛点来的:两个 Node 脚本,一个负责搜,一个负责抓正文,全程无头。
它是 Brave Search 驱动的无头搜索与内容提取 CLI,当前版本 v1.0.1,排专业技能榜第 22 名,安装量 150.8k,拿到 CLS 安全性认证(2026-05-06),整包只有 10.7 kB。维护者 steipete 是 PSPDFKit 创始人,package.json 的作者字段署名 Mario Zechner(libGDX 创始人),两位都是写了很多年开源的老手。依赖也干净:@mozilla/readability、jsdom、turndown,四个成熟库,没有花活。
百度网盘下载:https://pan.baidu.com/s/1ta5mnIYHHxKo0N09XqcJjg?pwd=lcw1(提取码:lcw1)
通过网盘分享的文件:steipete-brave-search-1.0.1.zip
链接: https://pan.baidu.com/s/1ta5mnIYHHxKo0N09XqcJjg?pwd=lcw1 提取码: lcw1 复制这段内容后打开百度网盘手机App,操作更方便哦
一、基本信息
先看全貌。这张表里的每一项都对着源码核过,后面章节不再重复。
| 项目 | 内容 |
|---|---|
| 技能名称 | Brave Search(brave-search) |
| 维护方 | steipete(PSPDFKit 创始人),作者字段署名 Mario Zechner(libGDX 创始人) |
| 定位 | Brave Search 驱动的无头网页搜索与内容提取 CLI |
| 版本 | v1.0.1 |
| 社区数据 | 专业技能榜 #22 · 安装 150.8k · 版本下载 52.9k |
| 安全认证 | CLS 安全性认证(2026-05-06) |
| 运行环境 | Node.js(ESM 模块),4 个 npm 依赖,按文档需配置 BRAVE_API_KEY |
| 启动命令 | ./search.js "关键词" -n 10 --content、./content.js https://… |
| 包体大小 | 整包 10.7 kB(search.js 5.2 kB + content.js 2.5 kB) |
| 下载安装 | steipete-brave-search-1.0.1.zip(网盘,提取码 lcw1) |
| 标签 | web-search、content-extraction、api-client、headless、markdown、cli-tool |
二、它解决什么问题
Agent 需要联网的原因很朴素:模型的知识停在训练截止日,查文档、查版本号、查一件事有没有变,都得往外走。现在主流的两条路各有各的难受。一条是挂浏览器——能力最全,但资源开销大、启动慢、还容易因为一个弹窗把流程卡死;另一条是接搜索 API——要注册账号、管 Key、盯配额,免费档的额度永远不够跑批量任务。
还有第三个常被忽略的问题:拿回来的内容是给谁看的?如果是给 LLM 看,原始 HTML 就是灾难——导航栏、脚本、样式全混在一起,两三千 token 花在噪音上。搜索工具的输出质量,直接决定下游模型的推理成本。
Brave Search 把这三件事压缩到最小:不挂浏览器,不解析整套协议,输出直接是「标题 + 链接 + 摘要 + 可选 Markdown 正文」的结构化文本。整个实现就两个脚本、两百多行代码,你可以在十分钟内读完它到底干了什么。
一句话概括它的取舍:放弃浏览器的全能,换取「装完即用、零常驻开销」的轻——搜索是手段,把干净的 Markdown 喂给模型才是目的。
三、核心功能
3.1 search.js:搜索与结果控制
先看为什么这章值得看——所有日常用法都浓缩在这一个脚本里,参数只有两个,但每个都影响 token 成本。命令形态就四种:./search.js "rust async await" 基础搜索默认 5 条;加 -n 10 控制条数;加 --content 附带每条结果的正文;两者可组合,比如 -n 3 --content。
实现层面有个值得说透的细节:它带着完整的浏览器请求头(Chrome 142 的 UA、sec-ch-ua 全家桶)去请求 search.brave.com 的搜索页,然后用 jsdom 解析返回的 HTML,从 div.snippet[data-type="web"] 节点里抠出标题、链接和摘要,顺手去掉结果里的日期前缀,还要过滤掉 brave.com 自己的链接。这更像「无头网页解析」而不是传统 API 调用——SKILL.md 里写着需要 BRAVE_API_KEY,但把 search.js 和 content.js 翻遍,没有任何一行读这个环境变量。这个落差后面会展开,这里先记住:不配 Key 它也能跑。
| 参数 | 默认值 | 作用 |
|---|---|---|
| -n <num> | 5 | 控制返回结果条数,直接决定输出 token 量 |
| –content | 关闭 | 逐条抓取结果页正文,转成 Markdown 附在输出里 |
3.2 content.js:正文提取与 Markdown 转换
这是第二个独立入口:给它一个 URL,它把可读正文提取出来转成 Markdown,15 秒超时。管线是标准的「三件套」——jsdom 把 HTML 变成 DOM,@mozilla/readability 按可读性算法剔除噪音只留正文,turndown(带 GFM 插件)把剩下的 HTML 转成带表格和代码块的 Markdown。转换后还有一轮清理:删空链接、压缩连续空格、去掉空行。
提取失败时有兜底:删掉 script、style、nav、header、footer、aside 这些节点,然后从 main、article、[role='main']、.content、#content 里挑一个当主内容区,纯文本超过 100 字符就输出。这个兜底让它在很多「非标准页面」上也不至于空手而归。
3.3 输出格式与成本控制
search.js 加 --content 时走同一条提取管线,但有两处收紧:超时从 15 秒降到 10 秒,每条正文截断到 5000 字符。这不是偷懒,是成本设计——默认 5 条结果,每条最多 5000 字符,最坏情况单次调用的输出也是有上限的,不会因为一条超长页面把 Agent 的上下文窗口撑爆。
输出格式是固定的四段式:
- Result N:每条结果一个分隔块;
- Title / Link / Snippet:标题、链接、摘要三要素;
- Content:仅在使用
--content时出现,Markdown 正文; - 查不到结果时输出
No results found.并正常退出,不报错。
四、真正有价值的地方
零浏览器依赖,这是它最大的差异化。同类「搜索+提取」技能里,相当一部分把 Puppeteer 或 Playwright 当地基,装完占几百 MB、运行时再吃一大块内存。这个技能只用 fetch 和 jsdom,Node 装完 npm ci 就能跑,容器、CI、低配 VPS 都不挑。对一个常驻 Agent 工具链的东西来说,这个差别的日常体感很大。
全链路 Markdown 输出。从 Readability 提取到 turndown 转换,中间没有一步留给「原始 HTML」。GFM 插件保证了表格和代码块不丢格式——搜技术文档时这点很关键,代码示例原样保留,模型不用从转义字符里猜。
代码量克制,审计成本近乎为零。两个脚本加起来两百多行,逻辑线性:请求、解析、转换、输出,没有状态、没有后台线程、没有隐藏副作用。想确认它没干别的事,读一遍 search.js 就够了——这种透明度在第三方技能里是稀缺品。
双脚本职责分离。搜索和抓取拆成两个入口,Agent 可以只用来搜,也可以只用来抓已知 URL。搜到之后要不要深入读,由 Agent 按需决定,不会被绑死在「一搜就读全文」的高成本路径上。
作者背景加分。steipete 长期维护 PSPDFKit 和一堆 macOS/iOS 工具链项目,Mario Zechner 是 libGDX 的作者,两人都靠开源声誉吃饭。这类作者的代码风格通常偏保守,不留暗门。
五、绕不开的问题
低危 SSRF 与 URL 白名单缺失。content.js 和 --content 会访问任何传进来的 URL,没有协议过滤、没有私有 IP 拦截。一条恶意指令足以诱导 Agent 去抓 127.0.0.1 或内网地址——虽然返回的是页面内容而非直接泄露,但内容本身可能被模型复述出来。官方安全报告把它标为低危,前提是你的 Agent 指令来源可信;如果 Agent 会处理不可信文本,这就是一个真实的口子。
网页结构依赖,改版即失效。解析靠的是 Brave 搜索页当前的 DOM 结构,代码里那个 a.svelte-14r20fy 选择器就是典型痕迹——Svelte 编译产物,Brave 前端一发版它就可能变。这不是假设性风险,而是这类「页面解析」方案的结构性宿命,用之前要有心理预期。
API Key 声明与实现脱节。SKILL.md 说需要 BRAVE_API_KEY,代码从不读取它。对使用者的影响是双向的:好消息是不用注册 API 账号也能跑;坏消息是文档不可信,你没法确定「Key 到底在哪个路径下被用到」。以实测为准,别按文档想当然。
提取质量波动。纯静态页面效果很好,但重 JS 渲染的 SPA、需要登录的页面、强反爬的站点,拿回来的要么是空壳要么直接报错。Readability 的兜底逻辑能救一部分,救不了全部。批量抓取前先手动试两个样本页。
无缓存、批量请求不友好。同样的查询跑两遍就是两次真实请求,--content 一开就是「1 条搜索 + N 条页面抓取」的请求风暴。对目标站点不礼貌,也容易触发 Brave 的频率限制。高频场景自己在外面套一层缓存。
来源可信度评级不高。安全报告给的是 T3——个人开发者维护,无组织背书。作者个人声誉好,但出问题时没有 SLA,issue 响应全看缘分。用在关键链路前,做好「哪天失效了自己修」的准备。
六、官方风险表与解读
| 风险项 | 级别 | 说明 |
|---|---|---|
| SSRF(服务端请求伪造) | 低 | 可访问用户指定的任意 URL,未过滤私有 IP 或危险协议 |
| 输入验证薄弱 | 提示 | 缺乏 URL 白名单和严格校验机制 |
| 网络行为不可控 | 警告 | 访问外部 URL 的声誉与加密级别不可控 |
| 批处理请求 | 低 | --content 批量抓取时可能对目标站点产生大量请求 |
| 依赖更新 | 提示 | 需关注 @mozilla/readability 与 jsdom 的安全更新 |
五项风险没有一个标到「中」,整体在第三方技能里算干净的——它不写文件、不执行系统命令、不读你的密钥,唯一的攻击面就是「它去访问了什么 URL」。而这一面恰好全在 Agent 的输入侧:只要指令来源可控,风险就可控。
两点补充。一是 SSRF 虽然标低危,但它是唯一一个「需要你主动设防」的项:官方建议的做法是加域名白名单,限制只抓可信站点。二是包体里 20 kB 的 package-lock.json 把依赖锁得死死的,装出来的就是审计过的版本——别手贱去 npm update。
一条实用纪律:让 Agent 搜可以放开,让它抓正文前先看一眼 URL——域名不认识就别让它进门。一行白名单检查,堵掉 SSRF 风险里最不好防的那一半。
七、适合谁,不适合谁
| 类型 | 是否适合 | 理由 |
|---|---|---|
| Agent 开发者 | 适合 | 查文档、查事实、查版本号的高频场景,轻量且输出对模型友好 |
| 服务器/容器环境 | 适合 | 无浏览器依赖,内存占用极低,低配 VPS 也能常驻 |
| 不想管搜索配额的团队 | 适合 | 不走官方 API 计费路径,无配额焦虑(代价见下一行) |
| 重视供应链安全的人 | 适合 | 代码两百多行可全量审计,依赖四个成熟库且版本锁定 |
| 要求长期稳定的生产链路 | 不适合 | 解析依赖 Brave 页面结构,改版即失效,没有 SLA |
| 需要抓登录后/重 JS 页面 | 不适合 | 无浏览器渲染能力,SPA 和鉴权页面拿不到正文 |
| 合规敏感环境 | 不适合 | 访问任意 URL 且无白名单,需自行加固才能过审 |
八、落地路径
比较稳的推进顺序是这样:
- 装好依赖。解压后进目录跑
npm ci,按 lock 文件装,别升级。Node 版本要支持AbortSignal.timeout(18 以上),这是脚本里唯一的新 API。 - 先手动验一轮。直接
./search.js "任意关键词"跑一次,确认能拿到 5 条结果——这一步同时在验证 Brave 当前页面结构和解析逻辑是否还对得上。 - 测提取质量。挑三五个你业务里真实会遇到的页面,用
./content.js各抓一次,看正文完整度。质量不合格的站点别让 Agent 去碰。 - 加白名单再接入。在 Agent 侧对 content.js 的入参做域名过滤,把「能抓哪里」限定在你信任的清单内。这是对官方风险表里 SSRF 项的直接回应。
- 控制输出规模。日常搜索用默认 5 条不带
--content,深度阅读时才对选中结果单独抓,避免一次调用把上下文窗口填满。 - 设一个失效巡检。每周拿固定关键词跑一遍,结果条数骤降就说明 Brave 改版了——这时候要么自己修选择器,要么换方案,别等到业务报错才发现。
九、文件构成与安装
整包 10.7 kB,五个文件各司其职,没有一个多余的:
| 文件/目录 | 大小 | 作用 |
|---|---|---|
| search.js | 5.2 kB | 搜索入口:请求 Brave 搜索页、解析结果、可选抓取正文 |
| content.js | 2.5 kB | 提取入口:抓取单个 URL,转 Markdown 输出 |
| SKILL.md | 1.2 kB | 技能描述与用法示例(含 BRAVE_API_KEY 声明) |
| package.json | 0.3 kB | 元信息:MIT 协议、ESM 模块、4 个依赖 |
| package-lock.json | 20.0 kB | 锁定依赖精确版本,保证审计过的版本可复现 |
安装就两步:解压到技能目录,npm ci 装依赖。没有任何构建步骤、没有配置文件、没有要写入系统的地方——这也是它 10.7 kB 能搞定全部功能的原因。注意 SKILL.md 里的 BRAVE_API_KEY 环境变量按文档配上即可(或干脆不配),当前代码不依赖它。
十、常见问题
需要注册 Brave API 账号吗?
按文档说要配 BRAVE_API_KEY,但当前 1.0.1 的代码没有任何一处读这个变量——它实际是带着浏览器头解析搜索页。所以不注册也能跑。但要把这个当成本版的实现细节而非长期承诺:官方一旦给页面加验证码或风控,挂 Key 走 API 的版本大概率会来。
中文搜索效果怎么样?
解析逻辑对语言不敏感,中文关键词能返回结果,摘要也能正常带上。要注意的是 Accept-Language 请求头写死了 en-US,Brave 可能因此偏向英文来源。查中文资料时建议关键词里带上明确的中文实体名,必要时 Agent 侧再补一次站内搜索。
和浏览器类搜索技能比,输在哪?
输在「深」:没有 JS 渲染,SPA 页面拿不到正文;没有会话,登录页面进不去;没有交互,翻页、点按钮、处理弹窗都做不到。但换来的优势同样明确——体积差两个数量级,内存占用差一个数量级,故障模式从「浏览器各种玄学崩溃」变成「解析失败直接报错」。轻场景换重能力,这笔账多数情况下是划算的。
--content 抓不全怎么办?
先确认是不是截断:正文统一截到 5000 字符,长文看到一半断掉是正常行为,不是 bug。再确认是不是渲染问题:动态加载的内容(滚动才出现、接口异步填充)在原始 HTML 里就不存在,任何解析器都救不了。前者可以把单次抓取拆成多次定向请求,后者只能换带浏览器的方案。
会被 Brave 封吗?
低频使用(每分钟几次查询)目前没问题;把它当批量爬虫、一秒几次地打,被封只是时间问题。请求头模拟得再像,行为模式骗不过风控。批量任务加延迟和缓存,把它当「偶尔查一下」的工具用,就安全。
想审计安全,从哪看起?
两个文件,二十分钟能读完。重点确认三件事:所有网络请求只有两处(搜索页和结果页抓取),没有写盘操作,没有子进程调用。依赖侧看 package-lock.json 里 jsdom 和 turndown 的版本,对照 CVE 数据库过一遍即可。
技能失效了自己能修吗?
能,这就是两百行代码的好处。失效点通常只有一处——搜索结果的选择器。用浏览器打开 Brave 搜索页,按 F12 看新结构的 class 名,替换 search.js 里对应的 querySelector,一般十几行改动。这也是选「页面解析」类工具时该有的自觉:你要么接受维护成本,要么选官方 API 的稳定但收费路径。
结语
Brave Search 是那种「把一件事做小」的技能:不追求浏览器方案的全能,把搜索和提取压缩到 10.7 kB、两百行代码,换来的是装完即用、零常驻开销、十分钟可审计。150.8k 的安装量说明这个取舍击中了大多数人——毕竟需要真的「逛网页」的场景,远比需要「查一下」的场景少。
用它的正确姿势是:把搜索当高频动作,把抓正文当受控动作——前者随便跑,后者套白名单。同时接受它的结构性风险:页面改版会失效,文档里的 Key 和实现对不上。当你只需要「搜一下、拿回干净的 Markdown」,它比任何浏览器方案都省心;当你的 Agent 要逛的是登录墙和 SPA,它就不是对的选择了。
通过网盘分享的文件:steipete-brave-search-1.0.1.zip
链接: https://pan.baidu.com/s/1ta5mnIYHHxKo0N09XqcJjg?pwd=lcw1 提取码: lcw1 复制这段内容后打开百度网盘手机App,操作更方便哦
Brave Search无头搜索内容提取网页抓取Node.js技能包
百度网盘下载:https://pan.baidu.com/s/1ta5mnIYHHxKo0N09XqcJjg?pwd=lcw1(提取码:lcw1)














暂无评论内容