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 文件中明确配置了这项开销。
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.targetsudo 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/healthdaemon 开始监听后,/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 地址失效。只能通过绕过挑战墙才能运行的服务栈,可能在没有警告的情况下失效。