SSD Nodes Learn Hosting plans →
指南 Matt Connor作者: Matt Connor · 更新于 2026-08-27

VPS 自托管 Firecrawl 替代方案对比

对比 Draco、Hound 与自托管 Firecrawl 的内存占用、无头浏览器需求和 API 兼容性,按固定版本安装低资源方案,并通过 MCP 接入代理。

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

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

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

四个项目,以及它们的实际定位

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

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

Hound 位于 master-fetch repository 中,并以 hound-mcp 的名称发布到 PyPI,采用 MIT 许可证;截至 3 August 2026,版本为 13.0.1。它需要 Python 3.11 或更高版本。它首先是 MCP server,其次才是 fetcher:它会先尝试使用普通 HTTP,只有在普通 fetch 被阻止时才启动 Patchright 浏览器。

Trawl 出现在这里,是因为人们搜索其他项目时也会遇到它,但它执行的是不同的任务。它使用经过指纹修改的 Firefox 解决 JavaScript challenge 和 CAPTCHA,可在 *arr media stack 中替代 FlareSolverr。它不是 markdown extractor。下面的使用规范部分会解释这一差异为何决定它是否适合加入您的 agent stack。

小型 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。这些上限由项目自行选择,是公开的配置数值,不是空闲系统的实测值;此外,Redis、RabbitMQ、PostgreSQL 和 FoundationDB 仍需从 Firecrawl 的内存预算中分配资源。

如果上限高于主机实际拥有的 RAM,就没有任何作用。主机内存耗尽时,内核的内存不足终止程序会结束某个进程,因此容器可能从 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。请在脚本中检查这一点,因为空文件加零退出码会悄悄污染 agent 的上下文:

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: OK。如果出现 FAILED 行,说明当前文件的字节内容与项目发布的内容不一致。请删除文件并重新开始。

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 服务单元和计时器。

现在获取 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 守护进程不暴露在公网

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

代理代码会变化吗?实际 API 兼容性

Draco 响应 Firecrawl v1 路由:/v1/scrape、/v1/map、/v1/crawl、/v1/batch/scrape 和 /v1/search,其 README 说明会接受并忽略未知字段。已经向 /v1/scrape 发送请求的代理只需更换基础 URL,无需进行其他修改。请注意另一端的变化:Firecrawl 自己的自托管页面现在使用 /v2/crawl 进行测试,而当前 SDK 使用 v2,因此将 v2 客户端指向 Draco 时,会请求 Draco 未提供的路由。在修改代理代码前,先使用 curl 测试每个调用,并读取 JSON 正文而不是仅查看状态码,因为不同实现通常会在字段名称上存在差异。

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

Draco 默认读取 robots.txt,而 --ignore-robots 会关闭该功能。Firecrawl 也记录了相同的默认设置。请保留这两个设置。然后设置自己的请求速率:--delay 用于设置请求之间的毫秒间隔,--max-concurrency 用于限制并行任务数,守护进程默认值为 8。在共享 VPS 链路上,将并行数设为 2 到 4 更为合适,而且总体速度通常不会更慢,因为网站开始对您进行速率限制后,耗费的时间往往超过提高并行数所节省的时间。缓存已获取的内容,这样代理再次运行时就不会给源站增加请求成本。这也是控制 AI 代理成本中最便宜的一项。

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

通过 MCP 将其连接到代理

MCP(model context protocol)是 agent 调用工具所使用的接口。哪些工具能够接触模型,以及模型是否可以在不先征得您同意的情况下调用某个工具,都由更上层的 模型运行所在的宿主程序决定,因此让 daemon 开始监听只是完成连接配置的一半。Draco 在同一个二进制文件中通过 stdio 提供 MCP server:

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

随后,这些工具会以 draco_scrape、draco_search 和 draco_interact_* 集合的形式显示给代理。只有当代理进程和二进制文件位于同一台机器上时,stdio 才能工作,因为其传输通道是该进程的标准输入。对于位于其他主机上的代理,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 代理都可以使用同一个共享服务。如果您最不确定的是代理端的实现,先手动编写一个小型代理循环,就能清楚看到抓取工具的接入位置,以及模型如何处理返回的 Markdown。

FAQ

是否需要无头浏览器来为 AI 代理抓取页面?

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

自托管 Firecrawl 在 VPS 上需要多少 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 地址失效。只能通过绕过挑战墙才能运行的服务栈,可能在没有警告的情况下失效。