SSD Nodes Learn 🎉 VPS desde $5.50/mês
Guias Matt ConnorPor Matt Connor

Alternativas self-hosted ao Firecrawl para um VPS

Compare Draco, Hound e Firecrawl self-hosted por RAM, browser headless e compatibilidade de API. Instale o Draco v0.20.5 e ligue-o a um agente via MCP.

O que uma alternativa self-hosted ao Firecrawl tem de fazer

Uma alternativa self-hosted ao Firecrawl tem uma função: receber um URL e devolver o conteúdo da página em markdown limpo, que um agente consiga ler. As APIs alojadas cobram por página. Por isso, a fatura aumenta à medida que o agente consulta mais páginas. Um VPS que já paga pode fazer o mesmo trabalho. Os projetos diferem numa questão: é necessário iniciar um browser headless (um motor de browser real executado sem janela) no seu servidor?

A resposta determina o consumo de memória, o custo de cada página e quais páginas são devolvidas vazias. Este guia compara Draco, Hound e a versão self-hosted do Firecrawl, instala a opção mais leve numa versão fixa e liga-a a um agente através de MCP (model context protocol).

Os quatro projetos e o que cada um realmente é

Draco é um único binário, escrito em Rust, com licença MIT ou Apache-2.0. A versão v0.20.5 foi publicada em 16 de julho de 2026. draco scrape <url> imprime markdown na saída padrão. draco serve executa um daemon que responde em 127.0.0.1:3002, a porta usada pelo Firecrawl. Não fornece uma imagem de contentor nem inicia um navegador.

Firecrawl self-hosted é o motor por trás do produto alojado, sob a licença AGPL-3.0. O seu docker-compose.yaml define sete serviços: playwright-service, api, redis, rabbitmq, nuq-postgres, foundationdb e foundationdb-init. Terá a fila de crawling real, mas terá de executar um pequeno sistema distribuído.

Hound está no repositório master-fetch e é distribuído no PyPI como hound-mcp, com licença MIT e versão 13.0.1 em 3 de agosto de 2026. Requer Python 3.11 ou posterior. É primeiro um servidor MCP e só depois um fetcher: tenta usar HTTP simples e inicia um navegador Patchright apenas quando a obtenção simples é bloqueada.

Trawl aparece aqui porque as pessoas encontram-no enquanto procuram os outros projetos, mas desempenha uma função diferente. Resolve desafios JavaScript e CAPTCHAs com um Firefox cujo fingerprint foi alterado, como substituto do FlareSolverr numa stack multimédia *arr. Não é um extrator de markdown. A secção sobre boas práticas abaixo explica por que motivo essa distinção determina se ele pertence ou não à sua stack de agentes.

Por que o pool de navegadores é onde VPS pequenos falham

Cada separador de navegador aberto é um processo de renderização separado, com o seu próprio DOM (document object model) e a sua própria heap JavaScript. Por isso, a memória aumenta com o número de páginas abertas ao mesmo tempo, e não com o número de páginas obtidas por dia. Dois destes projetos registam esse custo nos próprios ficheiros 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
  }
]

O ficheiro compose do Firecrawl limita o seu contentor api a 8 GB e o seu contentor Playwright a 4 GB, com limites de swap correspondentes. O compose do Hound define 3 GB para um contentor que inclui um Chromium integrado. Estes são limites máximos escolhidos pelos projetos e valores publicados, não medições de um sistema sem carga. Além disso, Redis, RabbitMQ, PostgreSQL e FoundationDB continuam a precisar da sua parte, para além dos valores do Firecrawl.

Um limite máximo superior à RAM disponível não resolve nada. Quando o servidor fica sem memória, o kernel termina um processo através do out-of-memory killer. Assim, um contentor desaparece de docker compose ps sem que seja escrito um erro no log da aplicação. Consulte dmesg -T | tail depois de qualquer reinício cuja causa não consiga explicar. Reserve 8 GB para a stack completa do Firecrawl e trate 4 GB como o mínimo para um servidor de testes. A configuração dos valores por serviço é explicada em limites de memória no Docker Compose.

Há outro detalhe dos navegadores que pode consumir uma noite de diagnóstico. O Docker atribui 64 MB de memória partilhada a um contentor em /dev/shm, e o Chromium coloca aí os buffers de renderização. Por isso, pode falhar ao processar páginas pesadas. Ambas as stacks de navegador aumentam esse valor: o compose do Hound inclui shm_size: "1gb". Copie essa linha para qualquer imagem que crie em torno do Playwright.

Qualidade da extração em páginas com muito JavaScript

Em HTML estático, num blogue renderizado no servidor, numa página de documentação ou num artigo de notícias, todos estes casos devolvem markdown quase idêntico, e vence a opção mais rápida. A diferença surge em páginas renderizadas no cliente, nas quais o HTML recebido é apenas uma estrutura vazia e o texto chega através de JavaScript depois do carregamento.

O Draco escala por níveis. Os níveis 0 e 1 analisam o HTML sem executar JavaScript. O nível 2 executa o JavaScript da página dentro de um isolate V8 no mesmo processo. Trata-se do motor JavaScript sem um browser à sua volta, e o README indica que o código da página não recebe bindings para capacidades do host nesse ambiente. Isto cobre muitas aplicações single-page com uma fração da memória de um browser. Quando o Draco encontra um obstáculo que não consegue ultrapassar, draco scrape termina com o código 3, needs_browser. Verifique este comportamento nos scripts, porque um ficheiro vazio com código de saída 0 é uma falha que contamina silenciosamente o contexto de um agente:

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

O playwright-service do Firecrawl controla um Chromium real, pelo que renderiza o que um browser renderiza. A versão self-hosted continua a não ser o produto alojado: a documentação indica que as instâncias self-hosted não têm acesso ao Fire Engine. Por isso, faltam o mecanismo anti-bloqueio e a rotação de IP do serviço cloud, e os endpoints /agent e /browser não são suportados. O Hound fica deliberadamente entre estas opções. Obtém o conteúdo por HTTP e escala por pedido. O seu browser mantido em memória termina depois de um timeout de inatividade, pelo que um servidor sem carga permanece próximo do consumo normal.

Instalar o Draco com uma versão fixada

O README documenta um instalador de uma linha. Leia o que ele faz antes de o encaminhar para uma shell: instala em $HOME/.draco/bin/draco, usa sempre a release latest e não verifica nenhuma assinatura nem hash. Num servidor, fixe a versão e verifique o download.

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

Isto imprime draco-linux-x86-64.tar.gz: OK. Uma linha FAILED significa que os bytes que tem não correspondem aos bytes publicados pelo projeto. Apague-os e recomece.

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

O último comando imprime a página de exemplo em markdown em bem menos de um segundo. O find não é decorativo: a disposição do arquivo não faz parte do contrato público do projeto, e o instalador oficial localiza o binário da mesma forma.

Execute o daemon com a sua própria conta, em vez de usar o utilizador com que iniciou sessão. Escreva /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

/health responde assim que o daemon está a escutar. Connection refused significa que não está, por isso consulte journalctl -u draco -n 50. A causa habitual é outro processo já estar a utilizar a porta 3002, porque essa também é a porta predefinida do Firecrawl, e --port altera uma delas. Consulte mais detalhes sobre ficheiros de unidade em: unidades e temporizadores de serviço do systemd.

Agora faça a obtenção da forma que o seu agente irá usar:

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

Mantenha o daemon de fetch fora da Internet pública

Uma API de fetch sem autenticação é um proxy aberto. Qualquer pessoa que consiga alcançar a porta pode fazer o seu servidor solicitar qualquer URL através do seu endereço IP. A denúncia de abuso será enviada ao seu fornecedor, e não à pessoa que fez o pedido. As flags documentadas de Draco, serve, não incluem uma chave de API. Por isso, a proteção tem de ser feita pela rede. Mantenha o bind predefinido, 127.0.0.1, quando o agent é executado no mesmo host. Quando o agent estiver noutro host, coloque as duas extremidades num túnel privado. Uma VPN WireGuard alojada por si é normalmente a opção adequada. Faça o bind ao endereço do túnel, e não a 0.0.0.0. Depois, confirme a partir de outra máquina que o IP público não responde a nada. Os fundamentos da firewall ufw e as contas de utilizador com privilégios mínimos abrangem as duas partes desta configuração.

O código do seu agente vai mudar? Compatibilidade da API na prática

Draco responde às rotas do Firecrawl v1: /v1/scrape, /v1/map, /v1/crawl, /v1/batch/scrape e /v1/search, e o README informa que os campos desconhecidos são aceites e ignorados. Um agente que já envia pedidos para /v1/scrape precisa de um novo URL base e de mais nada. Verifique o que mudou do outro lado: a própria página de self-hosting do Firecrawl agora testa com /v2/crawl, e os SDKs atuais usam v2. Por isso, um cliente v2 apontado para o Draco solicita uma rota que o Draco não publica. Teste cada chamada com curl antes de editar o código do agente e leia o corpo JSON em vez do código de estado, porque é nos nomes dos campos que estas implementações divergem.

Robots.txt, limites de pedidos e o limite a respeitar

O Draco lê robots.txt por predefinição, e --ignore-robots desativa esse comportamento. A documentação do Firecrawl indica a mesma predefinição. Mantenha ambas inalteradas. Em seguida, defina o seu próprio ritmo: --delay insere milissegundos entre pedidos e --max-concurrency limita os trabalhos em paralelo, com 8 como predefinição do daemon. Um valor entre 2 e 4 exerce menos pressão sobre a ligação de um VPS partilhado e raramente é mais lento no total, porque um site que começa a aplicar limites de pedidos faz perder mais minutos do que os poupados com a concorrência. Coloque em cache o que obtiver, para que uma segunda execução do agente não gere pedidos adicionais à fonte. Essa também é a opção mais barata em controlar o custo de um agente de IA.

As páginas de desafio são um assunto separado, e o Trawl foi concebido precisamente para lidar com Cloudflare Turnstile, reCAPTCHA, hCaptcha e GeeTest. Uma página de desafio é uma recusa explícita do site ao tráfego automatizado. Contornar essa proteção entra em conflito com os termos de utilização do site e, em alguns locais, com a lei. Por isso, este guia limita-se à infraestrutura de obtenção de dados. As mesmas técnicas que ultrapassam uma página de desafio são as que os proprietários dos sites monitorizam e bloqueiam. Assim, qualquer pipeline baseado nelas fica frágil e também desrespeita as regras do site. Quando uma fonte é assim tão importante, procure o respetivo feed RSS, a API pública ou uma exportação em massa. Cada opção é mais barata de executar, e nenhuma deixa de funcionar na semana em que a proteção é alterada.

Conecte-o a um agente através de MCP

MCP (model context protocol) é a interface que um agente usa para chamar uma ferramenta. Draco inclui um servidor MCP no mesmo binário, através de stdio:

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

As ferramentas aparecem então no agente como draco_scrape, draco_search e o conjunto draco_interact_*. O stdio só funciona quando o processo do agente e o binário estão na mesma máquina, porque o transporte usa a entrada padrão desse processo. Para um agente noutro host, Hound disponibiliza MCP através de HTTP: hound --http --host 127.0.0.1 --port 8765 publica um endpoint em http://127.0.0.1:8765/mcp, ao qual acede através do túnel. As opções de transporte e os elementos a expor estão descritos em executar servidores MCP numa VPS.

Obtenha pares através da pesquisa. Um agente que só consegue fazer fetch fica à espera que lhe forneça URLs. Adicione uma instância SearXNG de pesquisa self-hosted para que possa encontrá-los sozinho, seguindo o mesmo modelo da skill de pesquisa no browser baseada em SearXNG. Depois de o daemon arrancar, passa a ser um serviço partilhado pelos agentes de IA self-hosted que executar.

FAQ

Preciso de um navegador headless para obter páginas para um agente de IA?

Não para a maioria das páginas. Documentação, blogs e artigos de notícias renderizados no servidor são devolvidos completos com uma simples obtenção HTTP seguida de uma conversão de HTML para Markdown. É isso que o Draco faz nos níveis inferiores, com cerca de 300 ms por página sem navegador, segundo os valores do próprio projeto. Um navegador é necessário em aplicações renderizadas no cliente, nas quais o HTML recebido é apenas uma estrutura vazia. O isolamento V8 do Draco cobre grande parte desses casos sem iniciar um processo de navegador. Quando não consegue fazê-lo, termina com o código 3, needs_browser.

De quanta RAM precisa o Firecrawl autoalojado numa VPS?

O ficheiro compose define um limite de 8 GB para o contentor api e de 4 GB para o contentor Playwright. A mesma stack também inicia Redis, RabbitMQ, PostgreSQL e FoundationDB. Planeie 8 GB. Numa máquina com 2 GB, o kernel out-of-memory killer remove contentores sob carga. O primeiro sinal é um contentor reiniciado em docker compose ps, sem informação útil no log da aplicação. Confirme a causa com dmesg -T | tail.

O Draco é um substituto direto da API do Firecrawl?

Para os endpoints v1, está próximo. Disponibiliza /v1/scrape, /v1/map, /v1/crawl, /v1/batch/scrape e /v1/search. Também ignora os campos de pedido que não conhece. Por isso, um cliente desenvolvido para o Firecrawl v1 normalmente precisa apenas de um novo URL base. Não é o produto alojado. Não existe um pool de proxies gerido por trás dele, e as rotas v2 mais recentes do Firecrawl não fazem parte da interface disponível. Verifique primeiro cada chamada feita pelo seu agente com curl.

O autoalojamento de um scraper significa que posso ignorar o robots.txt?

Não. O local onde o código é executado não altera o que um site publicou nem o que os seus termos permitem. Tanto o Draco como o Firecrawl respeitam robots.txt por predefinição. A opção de substituição existe para sites que lhe pertencem ou para os quais tem autorização escrita para fazer crawling. Os limites de pedidos continuam a ser aplicados pelo serviço remoto. Por isso, um --delay educado, com baixa concorrência, mantém o seu endereço IP operacional. Uma stack que só funciona ao contornar uma challenge wall é uma stack que pode deixar de funcionar sem aviso.

#scraping#firecrawl#ai-agents#self-hosting#markdown