一个读取网页的智能体,可用程度取决于它的工具交回的最差答案。只回来一半内容的页面、把原因归错的错误、一个从没人抓取过的引用链接,都算在内。从 9 月 29 日到 10 月 22 日,我们发布了 CrawlForge MCP 的 24 个版本,从 v6.12.1 到 v6.24.0,其中几乎没有一个新增了值得放上落地页的功能。它们只为一件事:让 CrawlForge 成为一个可靠的网页抓取 MCP 服务器,它的输出能让智能体直接据以行动,而无需人工核查。
大部分修复来自两轮针对真实站点、覆盖全部 31 个工具的线上实测。第一轮在 v6.21.1 上进行了约 470 次调用,每个缺陷在修复之前都由第二名测试者复现过。第二轮覆盖 v6.22.3,每个工具至少测试三个线上站点。这篇文章记录了改动内容,并按它们给你带来的变化分组。
目录
- 本次发布了什么,逐版本列出
- 失败调用一律不计费
- 面向重复读取的页面缓存
- 两轮线上实测,打造可靠的网页抓取 MCP 服务器
- 可以核查的智能体答案
- 从更多框架读取内嵌状态
- 会等页面就绪的浏览器自动化
- 安全:每一跳都经过防护
- 搜索迁移到 Brave Search API
- 升级前需要检查的破坏性变更
- 如何升级
本次发布了什么,逐版本列出
| 版本 | 日期 | 一句话概括 |
|---|---|---|
| v6.12.1 | 2026-09-29 | scrape_with_actions 默认关闭重试;截图字节不再进入内联结果 |
| v6.13.0 | 2026-09-29 | 快照会等待页面渲染完成;超出浏览器上限的调用改为排队,而不是失败 |
| v6.14.0 | 2026-09-29 | 快照能看到 shadow root 和 iframe 内部;consent: "reject" 自动应答 Cookie 弹窗 |
| v6.15.0 | 2026-09-29 | extract_embedded_state 新增 escalate、keys_only、window_state 和结果句柄 |
| v6.16.0 | 2026-10-03 | Nuxt 3、SvelteKit、YouTube、Remix、Inertia 和 Shopify 状态;find;重定向的每一跳都经过闸门检查 |
| v6.17.0–6.17.1 | 2026-10-03 | 动作链中的每次导航都检查机器人墙;可识别 AWS WAF;代理凭据脱敏 |
| v6.18.0–6.18.1 | 2026-10-03 | extract_text 和 extract_links 用上升级阶梯;静默失败改为报错 |
| v6.19.0–6.19.2 | 2026-10-04 | 文本类工具的输出质量;按原因给出错误提示;serp_rank 深度 30 |
| v6.20.0–6.20.1 | 2026-10-06 至 10-11 | 本地文件路径不再进入用量报告;点击操作遵守 Crawl-delay;npm audit 无告警 |
| v6.21.0–6.21.1 | 2026-10-19 | 网页搜索改用 Brave Search API;serp_rank 标记诱饵结果;修复 .mcpb 包中的 PDF 处理 |
| v6.22.0–6.22.3 | 2026-10-19 | 第一轮 31 工具实测:所有失败调用免费;agent 引用的 URL 必须有出处 |
| v6.23.0–6.23.2 | 2026-10-21 | 第二轮实测与安全复审:浏览器流量经过防护代理;MCP SDK 2.3.1 |
| v6.24.0 | 2026-10-22 | 会话页面缓存、maxAge,以及更有针对性的 extract_embedded_state 路径未命中提示 |
没有新增或重命名任何工具,也没有任何标价变化。上面每一行都取自服务器的 changelog,网站的 changelog 也载有相同的条目。
失败调用一律不计费
大多数抓取 API 回答「失败的请求收费吗?」时,给出的是一张状态码列表。CrawlForge 自 v6.22.0 起的回答更短:失败的调用花费 0 credits,MCP server 和 REST API 都是如此。
在 v6.22.0 之前,MCP server 在出错时收取一半价格。还有三个工具存在一个更隐蔽的问题:extract_structured、extract_with_llm 和 summarize_content 返回 success: false,却没有把结果标记为错误,所以这些调用被全额计费,并被记录为成功。现在,失败是以下三种情况中的任何一种,且都不计费:
- 设置了
isError的结果 - 抛出的错误
- 顶层为
success: false的响应体
拒绝本来就免费,现在依然如此。robots.txt 禁止、主机在黑名单中、SSRF 拒绝,或者一道挡住升级阶梯每一级的机器人墙,都不花任何费用。自 v6.16.0 起,这也覆盖了被我们自己的合规闸门中途叫停的 scrape_with_actions 和 browser_session 动作链。报告调用计费金额的 _cost 块,现在对声明了输出 schema 的工具也会出现在 structuredContent 中,而不只在文本结果里,因此智能体无需解析文字就能读到自己的花费。
面向重复读取的页面缓存
智能体会重复读取页面。模型先抓取一个页面拿 markdown,然后觉得还需要元数据,再从内嵌 JSON 里要一个值,这就是对同一个 URL 的三次抓取。v6.24.0 新增了会话页面缓存,让第二次和第三次读取更便宜,也不再打扰站点。
10 分钟内对同一页面的重复请求会复用已经抓取的副本,花费 1 credit,无论这次要的是什么:其他格式、另一个 JSON 路径、其他选择器。对同一页面的并行调用共享一次请求。它覆盖九个工具:fetch_url、scrape、extract_metadata、extract_text、extract_links、scrape_structured、extract_embedded_state、extract_structured 和 extract_with_llm。
什么永远不会被缓存,与什么会被缓存同样重要:
- 非 2xx 响应、机器人墙和挑战页
- 标记了
Cache-Control: no-store的响应 - 携带
Authorization或Cookie请求头的请求
缓存命中仍会运行黑名单和 robots.txt 检查,所以缓存的页面永远不会成为绕过站点规则的途径。缓存有大小上限(CRAWLFORGE_PAGE_CACHE_MB,默认 64,0 表示关闭)。它只在本地 MCP 安装中运行:在 --http 下以及通过 REST API 的请求中都是关闭的。
需要实时页面时,用 maxAge(毫秒)说明。maxAge: 0 强制重新抓取:
{
"name": "scrape",
"arguments": {
"url": "https://example.com/pricing",
"formats": ["markdown"],
"maxAge": 0
}
}这九个工具返回的每个结果都带有 cache: { state, fetchedAt, ageMs, note },所以智能体能分辨自己看到的是 3 秒前的副本,还是新抓取的页面。
两轮线上实测,打造可靠的网页抓取 MCP 服务器
下面的 scrape 和 crawl_
读起来像页面本身的文本
- 列表页保留了文本。 Readability 把列表项的作者当成了文章署名,于是 quotes.toscrape.com 丢掉了「by Albert Einstein」。主内容提取保留的可见文本不足 60% 的列表页,现在会回退到整个页面。这一修复覆盖
scrape、extract_content、batch_scrape、crawl_deep和scrape_with_actions。 - 块与块不再粘连。 一个共享的文本扁平化器取代了原先的多个,所以「July 2023If you…」会读作两行,紧挨着写的链接也各占一行。
- 代码块以带语言标注的围栏形式输出。 docs.python.org 上的 Sphinx 代码此前会以转义后的普通文字返回。
- Wikipedia 保留章节标题,并去掉「[edit]」链接。
能跑完、计数诚实的爬取
crawl_deep基于实际落地的页面解析链接。 docs.python.org/3/tutorial 会重定向到 /3/tutorial/,此前每个章节链接都被解析到高了一级的目录,返回 404。- 链接分析不再拖住服务器。 在一个包含 16,766 个链接的 7.3 MB 页面上,它曾耗时 50 秒,让其他所有调用都得不到资源。现在只需 0.5 秒。
crawl_deep在max_pages处停止。 它过去会先把队列中的所有链接处理完:在一个站点上为 3 个页面花了 232 秒。map_site包含起始 URL,所以单页站点返回 1 个 URL,而不是 0 个。
会说明找不到什么的提取
extract_structured返回你要求的每个字段。 找不到的值为null,并列在新的missing_fields数组中,而不是让该字段悄无声息地消失。analyze_content不再用英语公式给其他语言打分。 一段明显是投诉的西班牙语文本此前得分 −0.08。情感分析现在对英语使用带否定处理的 AFINN-165 词典,对其他语言返回not_applicable,与可读性评分的做法一致。summarize_content默认尝试生成式摘要,在 LLM 可用时采用中等长度,并在摘要之前去掉 Cookie 提示行和导航菜单。
指明原因的错误
DNS 解析失败过去只显示为一句光秃秃的 fetch failed,下一步提示还建议使用 stealth_mode,把智能体送进 stealth 浏览器去抓取一个拼错的地址。现在错误会带上原因(ENOTFOUND、ECONNREFUSED),提示会让你检查 URL。没有匹配到任何元素的选择器会被报告为选择器未命中,并指出是哪个选择器,而不是被当成站点响应慢。提示本身现在按错误类别(robots、黑名单、SSRF、404、超时、校验)给出,而不是每个工具一条通用提示。
可以核查的智能体答案
agent 工具从开放网络回答问题。它在这一周期的修复都关乎出处,因为只有能看到答案从哪里来,答案才有用。
- 引用的 URL 必须来自信息源。 自 v6.22.1 起,答案中的每个 URL 都必须是智能体抓取过的页面、这类页面上的链接,或写在其来源文本中。不满足条件的 URL 会触发一次纠正性重写。重写后仍然保留的 URL 会在
provenance.unverified_urls以及答案内的一条警告中被点名。此前,一个 Hacker News 标题正确、却链接到 2021 年一篇报道的答案,会被当作已验证通过。 - 智能体可以链接到具体条目。 每个信息源现在会把最多八个自身链接带入综合环节,所以「今天的头条」会附上那条报道的 URL。
- 平局时官方来源胜出。 域名投票打平时,过去会推举排名第一的站点,常常是 Wikipedia。
- 「最后更新」不是发布日期。 把页面的更新日期当作发布日期给出的答案会被纠正或标记,记录在
provenance.update_dates中。 - 它遵守 120 秒的上限。 某次实测运行曾耗时 183 秒。达到上限的运行现在会返回
degraded: true以及已经收集到的证据。
价格不变:8 credits,每次拿到页面的 stealth 重试加 5,最多 18。
从更多框架读取内嵌状态
许多站点把数据以 JSON 形式放在 HTML 里,供前端框架进行水合(hydration)。extract_
- Nuxt 3 的
__NUXT_DATA__,解码为对象,以nuxt_data返回(过去返回的是索引数组) - SvelteKit 数据以
sveltekit_data返回,Inertia 的data-page以inertia_page返回 - YouTube 的
ytInitialData和ytInitialPlayerResponse,所以观看页通过普通抓取就能返回videoDetails - Remix、Shopify 商品 JSON 与分析类 meta,以及被赋值为 JavaScript 字面量而非 JSON 的全局变量,由静态求值器读取,不运行任何页面代码
三个参数让大型载荷变得可用。find 返回所有具有给定键名的属性,每个都附带可以直接回传的路径。keys_only 返回两层键及其类型,而不是数据本身。超过 max_inline_chars 时,结果是一份预览加一个句柄,用 read_
{
"name": "extract_embedded_state",
"arguments": {
"url": "https://shop.example.com/products/widget",
"find": "price"
}
}被墙挡住的页面可以用 escalate: true 在 stealth 浏览器中重读,预估 7 credits,普通抓取已拿到页面时只收 2。自 v6.24.0 起,无法解析的 path 会返回它停下位置往下两层的键,并据此给出下一步建议。此前,它会让智能体重读整个载荷。
会等页面就绪的浏览器自动化
scrape_
- 快照会等待页面稳定:先等
load(最多 5 秒),再等一段安静期,即 300 ms 内无 DOM 变化、500 ms 内无进行中的请求(最多 3 秒)。Amazon 首页的快照从 0 个节点变成了 236 个,搜索框也在其中。 - 快照能看到 shadow root 和 iframe 内部,包括跨域 iframe,靠的是 Playwright 原生的无障碍快照。
- 被替换的元素会被重新找到。 当页面在快照之后替换了某个元素(Wikipedia 的搜索框就是如此),会按角色和名称再查找一次该 ref,而不是以元素已脱离(detached)失败。
- Cookie 弹窗替你应答。
browserOptions.consent: "reject"会在每次导航后运行 DuckDuckGo 的 autoconsent 拒绝流程。The Guardian 的 Sourcepoint 对话框大约用了一秒。 - 突发的一批调用改为排队,而不是失败。 「Maximum concurrent sessions (3) reached」不再出现。调用最多等待 60 秒获取浏览器槽位,并报告
queued_ms。 - 失败耗时更短。
maxRetries现在默认为 0,所以在 4 秒超时下点击一个不存在的选择器,大约 4 秒就会失败,而不是 20.8 秒。Camoufox 上的 stealth 点击从 12.5–20 秒降到了 1.4 秒。
动作链中的每一次导航现在都会检查机器人墙,而不只是最后一页。结果会在 navigations 下逐一列出,AWS WAF 和 F5 与 Cloudflare、DataDome 等一起被识别出来。至于撞墙之后会发生什么,v6.
安全:每一跳都经过防护
抓取服务器获取的是模型选定的 URL,而模型可能是从一个恶意页面上读到它们的。SSRF 防护自 v5 起就已就位。这一周期封堵了绕过它的路径:
- 浏览器流量经过防护代理。 自 v6.23.0 起,每个浏览器上下文都通过一个本地正向代理连接,它检查每一个连接(重定向跳转、iframe、子资源、fetch、XHR 和 WebSocket),并连接到它检查过的那个地址,所以 DNS 重绑定再也无法穿过浏览器路径。此前,一个重定向到 127.0.0.1 的页面,会在拦截被报告之前就已经访问到该地址。
[::]被拦截。 这个未指定的 IPv6 地址会访问到本机,和0.0.0.0一样。- 重定向的每一跳都像首次请求一样经过闸门。 自 v6.16.0 起,每一跳之前都会重新检查黑名单和 robots.txt,并且每一跳都会等待该主机的
Crawl-delay。重定向指向被禁止的路径时,该路径永远不会被请求。 - 本地文件读取受到限制。 带本地路径的
process_document现在只接受文档类文件,并拒绝~/.ssh这类点目录。设置CRAWLFORGE_ALLOWED_DIRS可把读取限制在你列出的目录中。 - 你的路径和凭据留在你的机器上。 本地文件路径不再进入用量报告。代理凭据会从结果、错误信息和用量报告中脱敏,URL 中的凭据也会从合规审计日志中脱敏。
- MCP SDK 2.3.1,应对 SDK 的 HTTP 传输层和认证处理中的三项安全公告。
搜索迁移到 Brave Search API
10 月 19 日,CrawlForge API 把 search_provider.backend 会报告这次调用由哪个后端提供。total_results 为 null,因为 Brave 不报告总数,而 0 会被读成「没有结果」。分页是精确的:不是页大小整数倍的偏移量,现在也会返回你所要求的那个窗口。
serp_suspect: true,并说明有多少条提到了。MCP server 和 REST API 上的默认深度现在都是 30,仍是 5 credits。
升级前需要检查的破坏性变更
这 24 个版本中的大多数不会改变你的任何调用。以下这些会:
| 变更 | 起始版本 | 你需要做什么 |
|---|---|---|
read_result 的 json_path 从完整的存储结果开始 | v6.23.0 | 给 fetch_url 路径加上 body. 前缀(body.items[0]) |
extract_links 记录去掉了 is_external | v6.18.0 | 读取 type:internal、external 或 other |
scrape 只接受一个 highlights 和一个 question 格式 | v6.20.0 | 第二个查询另发一次调用 |
scrape_with_actions 的 maxRetries 默认为 0 | v6.12.1 | 如需重放,请显式设置 |
stealth_mode 移除了 enable/disable;waited_for_render_ms 被替换 | v6.19.0, v6.23.0 | 每次调用传入设置;读取 waited_ms 和 render_grace_ms |
scrape_structured 的 @href/@src 值为绝对 URL | v6.23.0 | 去掉你自己的 URL 解析 |
serp_rank 默认扫描 30 条结果 | v6.19.2 | 目标更靠后时传入 depth(最多 200) |
2026-07-28 版协议下的 HTTP 请求需要 MCP-Protocol-Version | v6.23.1 | 官方 SDK 客户端已经会发送它 |
如何升级
npm install -g crawlforge-mcp-server@latest
crawlforge --version # 6.24.0
# Optional: size the session page cache in MB (default 64), or 0 to turn it off
export CRAWLFORGE_PAGE_CACHE_MB=64用 npx 启动服务器的 MCP 客户端会在下次重启时用上 v6.24.0。如果你安装了 Agent Skills,请用 crawlforge install-skills --target claude-code --force 刷新它们,让其中的工具说明与服务器保持一致。
想看看你的智能体读取的页面有什么不同?免费开始,赠送 1,000 credits,让智能体去访问那些曾给它带来麻烦的站点,并在每次调用的 _cost 块里查看花费。失败的调用会显示 0。每个工具的价格都在定价页面上。