SSD Nodes Learn 🎉 VPS $5.50/月起
指南 Matt Connor作者: Matt Connor

VPS 自托管 Firecrawl 替代方案对比

对比 Draco、Hound 和自托管 Firecrawl 的内存占用、无头浏览器需求及 API 兼容性,提供固定版本安装步骤和 MCP 接入方法。

自托管 Firecrawl 替代方案必须具备的功能

自托管 Firecrawl 替代方案只有一个任务:接收 URL,并返回代理可以读取的干净 Markdown。托管 API 按页面收费,因此代理抓取的页面越多,费用越高;而您已经付费使用的 VPS 也可以完成相同的工作。这些项目的差异取决于一个问题:您的服务器是否必须启动无头浏览器(在没有窗口的情况下运行的真实浏览器引擎)?

这个问题决定内存占用、抓取每个页面的成本,以及哪些页面会返回空内容。本指南比较 Draco、Hound 和自托管 Firecrawl 版本,以固定版本安装其中最轻量的方案,并通过 MCP(模型上下文协议)将其连接到代理。

这 4 个项目分别是什么,以及它们实际做什么

Draco 是一个使用 Rust 编写的单一二进制程序,采用 MIT 或 Apache-2.0 许可证。版本 v0.20.5 于 16 July 2026 发布。draco scrape <url> 将 markdown 输出到 stdout。draco serve 运行一个守护进程,并在 127.0.0.1:3002 上响应;这是 Firecrawl 使用的端口。它不提供容器镜像,也不会启动浏览器。

Firecrawl self-hosted 是托管产品背后的引擎,采用 AGPL-3.0 许可证。其 docker-compose.yaml 定义了 7 个服务:playwright-service、api、redis、rabbitmq、nuq-postgres、foundationdb 和 foundationdb-init。您可以获得实际的抓取队列,但需要运行一个小型分布式系统。

Hound 位于 master-fetch 仓库中,并以 hound-mcp 的名称发布到 PyPI;截至 3 August 2026,版本为 13.0.1,采用 MIT 许可证。它需要 Python 3.11 或更高版本。它首先是 MCP 服务器,其次才是抓取器:它会先尝试普通 HTTP 请求,只有在普通抓取返回 blocked 时才启动 Patchright 浏览器。

Trawl 出现在这里,是因为人们搜索其他项目时经常会遇到它,但它执行的是不同的任务。它使用经过指纹补丁处理的 Firefox 来解决 JavaScript challenge 和 CAPTCHA,可在 *arr 媒体栈中替代 FlareSolverr。它不是 markdown 提取器。下面关于使用规范的章节会说明这一差异为何决定它是否适合加入您的 agent 栈。

为什么浏览器池会耗尽小型 VPS

每个打开的浏览器标签页都是一个独立的渲染器进程,并持有自己的 DOM(文档对象模型)和 JavaScript 堆。因此,内存消耗取决于同时打开的页面数,而不是每天抓取的页面数。这两个项目都在各自的 compose 文件中写明了这项开销。

ChartMemory ceilings each project sets in its own compose file (GB)
The data behind this chart
[
  {
    "label": "Firecrawl api",
    "memory_limit_gb": 8
  },
  {
    "label": "Firecrawl playwright",
    "memory_limit_gb": 4
  },
  {
    "label": "Hound (browser included)",
    "memory_limit_gb": 3
  }
]

Firecrawl 的 compose 文件将其 api 容器的内存上限设为 8 GB,将其 Playwright 容器的内存上限设为 4 GB,并设置了相应的 swap 上限。Hound 的 compose 文件为一个内置 Chromium 的容器设置了 3 GB。这些是项目选择并公布的上限,不是空闲系统的实测值。在 Firecrawl 的内存需求之外,Redis、RabbitMQ、PostgreSQL 和 FoundationDB 仍需要占用内存。

内存上限高于实际拥有的 RAM 没有作用。当服务器内存耗尽时,内核的 out-of-memory killer 会终止进程,因此容器可能从 docker compose ps 中消失,而应用日志中不会记录错误。每次遇到无法解释的重启后,都应读取 dmesg -T | tail。应为完整的 Firecrawl 栈预留 8 GB,并将 4 GB 视为测试服务器的最低配置。按服务设置这些数值的方法参见 Docker Compose 中的内存限制

还有一个浏览器细节也可能让人排查数小时。Docker 会在 /dev/shm 为容器提供 64 MB 共享内存,Chromium 会将渲染器缓冲区放在那里,因此处理大型页面时可能崩溃。两个浏览器栈都会增大该值:Hound 的 compose 文件包含 shm_size: "1gb"。构建基于 Playwright 的镜像时,也应复制这一行。

JavaScript 密集型页面的提取质量

对于静态 HTML、服务端渲染的博客、文档页面和新闻文章,这些工具返回的 Markdown 几乎相同,因此速度最快的工具胜出。差异出现在客户端渲染的页面上:服务器返回的 HTML 只是空壳,页面加载后文本才由 JavaScript 获取。

Draco 会分层升级。第 0 层和第 1 层完全不运行 JavaScript,只解析 HTML。第 2 层会在进程内 V8 隔离环境中运行页面自身的 JavaScript。V8 是不带浏览器环境的 JavaScript 引擎,README 说明页面代码在其中无法获得宿主能力绑定。这种方式只需浏览器一小部分内存,就能处理许多单页应用。当 Draco 遇到无法处理的页面时,draco scrape 会以退出码 3 退出,needs_browser。请在脚本中检查这一点,因为退出码为 0 但文件为空,是一种会悄悄污染代理上下文的失败:

draco scrape https://example.com > page.md
echo "exit=$?"

Firecrawl 的 playwright-service 驱动真实的 Chromium,因此会渲染浏览器实际渲染的内容。但自托管版本仍不同于托管产品:文档说明,自托管实例无法访问 Fire Engine,因此云服务提供的反拦截和 IP 轮换功能不可用,/agent/browser 端点也不受支持。Hound 则有意处于两者之间。它通过 HTTP 获取内容,并按请求逐级升级;其预热浏览器会在空闲超时后关闭,因此空闲服务器的资源占用仍接近基线。

安装固定版本的 Draco

README 提供了单行安装程序。将其通过管道传给 shell 前,先查看它的行为:它会安装到 $HOME/.draco/bin/draco,始终获取 latest 版本,并且不会检查签名或哈希值。在服务器上,应固定版本并验证下载内容。

cd /tmp
curl -fsSLO https://github.com/0xchasercat/draco/releases/download/v0.20.5/draco-linux-x86-64.tar.gz
curl -fsSLO https://github.com/0xchasercat/draco/releases/download/v0.20.5/SHA256SUMS
sha256sum --ignore-missing -c SHA256SUMS

该命令会输出 draco-linux-x86-64.tar.gz: OKFAILED 行表示你保存的字节内容与项目发布的内容不一致,因此请删除文件并重新开始。

mkdir -p draco-v0.20.5
tar -xzf draco-linux-x86-64.tar.gz -C draco-v0.20.5
sudo install -m 755 "$(find draco-v0.20.5 -type f -name draco | head -n1)" /usr/local/bin/draco
draco scrape https://example.com

最后一条命令会以 markdown 格式输出示例页面,耗时远低于 1 秒。find 不是装饰信息:归档文件的目录结构不属于项目的公开契约,官方安装程序也会以相同方式定位二进制文件。

请使用专用账户运行 daemon,不要使用登录账户。写入 /etc/systemd/system/draco.service

[Unit]
Description=Draco fetch daemon
After=network-online.target
Wants=network-online.target

[Service]
User=draco
ExecStart=/usr/local/bin/draco serve --host 127.0.0.1 --port 3002 --max-concurrency 4
Restart=on-failure
NoNewPrivileges=true
ProtectSystem=strict
ProtectHome=true
PrivateTmp=true

[Install]
WantedBy=multi-user.target
sudo useradd --system --no-create-home --shell /usr/sbin/nologin draco
sudo systemctl daemon-reload
sudo systemctl enable --now draco
curl -s http://127.0.0.1:3002/health

daemon 开始监听后,/health 会立即返回。Connection refused 表示 daemon 未监听,因此请读取 journalctl -u draco -n 50。通常的原因是其他进程已经占用 3002,因为这也是 Firecrawl 的默认端口;--port 可更改任一方的端口。有关 unit 文件的详细说明,请参阅:systemd service unit 和 timer

现在按 agent 的实际调用方式获取内容:

curl -X POST http://127.0.0.1:3002/v1/scrape \
  -H 'content-type: application/json' \
  -d '{"url": "https://example.com", "formats": ["markdown"]}'

不要让 fetch daemon 暴露在公网

没有身份验证的 fetch API 就是开放代理。任何能够访问该端口的人,都可以让您的服务器通过您的 IP 地址请求任意 URL。滥用报告会发送给您的服务提供商,而不是发送给攻击者。Draco 的文档中,serve 标志不包含 API key,因此必须通过网络控制访问权限。agent 与 fetch daemon 运行在同一台主机上时,保持默认的 127.0.0.1 绑定地址。agent 位于其他主机时,将两端都放在私有隧道中。通常使用 自行托管的 WireGuard VPN,并绑定到隧道地址,而不是 0.0.0.0。然后从另一台机器检查,确认公网 IP 不响应任何请求。ufw 防火墙基础知识最小权限用户账户 分别介绍这两部分的配置。

您的 agent 代码会改变吗?实际 API 兼容性

Draco 响应 Firecrawl v1 路由:/v1/scrape/v1/map/v1/crawl/v1/batch/scrape/v1/search,其 README 说明会接受并忽略未知字段。已经向 /v1/scrape 发送请求的 agent 只需更换基础 URL,无需其他修改。请注意另一端发生了什么变化:Firecrawl 自托管页面现在使用 /v2/crawl 进行测试,而当前 SDK 使用 v2,因此将 v2 客户端指向 Draco 时,会请求 Draco 未发布的路由。修改 agent 代码前,先使用 curl 测试每个调用,并读取 JSON 响应体而不是只查看状态码,因为这些实现之间最容易出现差异的是字段名。

Robots.txt、速率限制以及应当遵守的边界

Draco 默认读取 robots.txt,而 --ignore-robots 会关闭该功能。Firecrawl 记录的默认设置也相同。保留这两个设置不变。然后设置请求速率:--delay 会在请求之间加入毫秒级间隔,--max-concurrency 会限制并行任务数;守护进程的默认值为 8。在共享 VPS 链路上,2 到 4 个并行任务更合适,而且整体速度通常不会更慢,因为网站开始限制你的请求后,消耗的时间往往多于并发数带来的节省。缓存已获取的内容,这样第二次运行 agent 时就不会给源站增加请求成本。这也是控制 AI agent 成本中最便宜的一项。

挑战页面是另一个问题,而 Trawl 正是为此构建的:Cloudflare Turnstile、reCAPTCHA、hCaptcha 和 GeeTest。挑战页面直白地表示网站拒绝自动化流量。绕过挑战页面可能违反网站的使用条款,在某些地区还可能违法,因此本指南只介绍内容获取基础设施,不涉及绕过措施。能够通过挑战页面的技术,也是网站所有者重点监控和拦截的技术,因此基于这些技术构建的流水线既不稳定,也不尊重网站规则。当某个来源重要到这种程度时,应查找其 RSS feed、公开 API 或批量导出功能。每种方式的运行成本都更低,而且不会因挑战页面在某周发生变化而中断。

将其通过 MCP 接入代理

MCP(模型上下文协议)是代理调用工具所使用的接口。Draco 在同一个二进制文件中通过标准输入输出提供 MCP 服务器:

{ "mcpServers": { "draco": { "command": "draco", "args": ["mcp"] } } }

这些工具随后会以 draco_scrapedraco_searchdraco_interact_* 集合的形式显示给代理。标准输入输出仅适用于代理进程和该二进制文件位于同一台机器的情况,因为传输使用的是该进程的标准输入。对于位于其他主机上的代理,Hound 改为通过 HTTP 提供 MCP:hound --http --host 127.0.0.1 --port 8765 会在 http://127.0.0.1:8765/mcp 发布一个端点,您可以通过隧道访问它。传输方式和需要公开的内容请参阅在 VPS 上运行 MCP 服务器

搜索可与抓取配合使用。只能抓取内容的代理会等待您提供 URL。添加自托管的 SearXNG 搜索实例后,它就能自行查找这些 URL,使用方式与基于 SearXNG 构建的浏览器搜索技能相同。守护进程启动后,它就是您运行的任意自托管 AI 代理都可以共用的服务。

FAQ

我需要使用无头浏览器为 AI 代理抓取页面吗?

大多数页面不需要。服务器端渲染的文档、博客和新闻文章,通过普通 HTTP 抓取再执行 HTML 转 Markdown 即可获得完整内容;根据 Draco 项目自身的数据,其较低级别的服务无需浏览器,每页处理时间约为 300 ms。对于客户端渲染的应用,浏览器才值得占用内存,因为此类应用返回的 HTML 只是空壳。Draco 的 V8 isolate 无需启动浏览器进程即可处理其中许多场景;无法处理时会以退出码 3、needs_browser 退出。

在 VPS 上自行托管 Firecrawl 需要多少 RAM?

其 compose 文件为 api 容器设置了 8 GB 的内存上限,为 Playwright 容器设置了 4 GB 的内存上限;同一套服务还会启动 Redis、RabbitMQ、PostgreSQL 和 FoundationDB。请按 8 GB 规划。在 2 GB 的主机上,内核的 out-of-memory killer 会在负载较高时终止容器,最初的迹象是 docker compose ps 中出现重启的容器,而应用日志中没有有用信息,因此请使用 dmesg -T | tail 确认。

Draco 是 Firecrawl API 的直接替代品吗?

对于 v1 端点,二者基本兼容。它提供 /v1/scrape/v1/map/v1/crawl/v1/batch/scrape/v1/search,并会忽略不认识的请求字段,因此针对 Firecrawl v1 编写的客户端通常只需更换 base URL。它不是托管产品:其后没有托管的代理池,Firecrawl 更新的 v2 路由也不在支持范围内。请先使用 curl 验证代理发出的每个调用。

自行托管抓取器后,就可以忽略 robots.txt 吗?

不可以。代码在哪里运行,不会改变网站发布的内容,也不会改变网站条款允许的操作。Draco 和 Firecrawl 默认都会遵守 robots.txt;对于您拥有或已获得书面抓取许可的网站,可以使用覆盖标志。无论如何,速率限制都会在对端执行,因此使用低并发的礼貌式 --delay 有助于保持 IP 地址可用。只能通过绕过挑战页面才能运行的服务,在没有任何预警的情况下就可能失效。

#scraping#firecrawl#ai-agents#自托管#markdown