Como hospedar um bot de WhatsApp 24/7

Para manter um bot de WhatsApp online 24 horas, rode o processo num servidor que não desliga e guarde a pasta de autenticação em disco persistente. Assim ele reconecta sozinho sem pedir novo pareamento.

Atualizado em 7 min de leitura

Objetivos de aprendizado

Depois de ler este artigo, você vai conseguir:

  • Escolher entre uma biblioteca não oficial e a Cloud API oficial da Meta
  • Rodar um bot com Baileys que guarda a sessão e reconecta sozinho
  • Verificar que o bot está online e corrigir os erros mais comuns
Nesta página

Um bot de WhatsApp é um programa que recebe mensagens do seu número, decide o que responder e envia a resposta. Para funcionar o dia todo, ele precisa de um processo vivo e de uma sessão autenticada que sobreviva a reinícios. Esses são os dois pontos em que a maioria dos bots quebra.

Este guia mostra os dois caminhos: Baileys, uma biblioteca não oficial que conecta como o WhatsApp Web, e a Cloud API, a interface oficial da Meta. Os exemplos usam a versão LTS ativa do Node.js e a API do Baileys 7. Se o npm install trouxer outra versão maior, leia as notas de versão do projeto antes de seguir.

Usuário!pingpongWhatsAppCelularpareia uma vezWebSocketsempre ligadoProcesso do botBaileysgravalêauth_info/sessão em discoreiniciasem parearde novo
O processo grava a sessão na pasta de autenticação em disco; no reinício ele a lê e reconecta sem parear de novo.

Biblioteca não oficial ou Cloud API?#

Baileys (não oficial) Cloud API (oficial)
Como conecta WebSocket, como dispositivo vinculado ao número Webhook HTTPS + chamadas à Graph API
Sessão Pasta de autenticação em disco Token de acesso, sem sessão
Servidor Processo sempre ligado Servidor HTTPS público com certificado válido
Mensagem fora de conversa Livre, mas com risco de banimento Só modelos (templates) aprovados
Risco Ban por violar os Termos de Serviço Sem esse risco, mas exige conta comercial

A Cloud API entrega as mensagens recebidas por webhook. Quando o usuário escreve, abre-se uma janela de atendimento de 24 horas, que renova a cada nova mensagem dele. Dentro dela você responde com texto livre. Fora dela, só com modelos pré-aprovados. A Meta cobra por mensagem de modelo entregue, e mensagens de texto livre dentro da janela não são cobradas. Os valores e as regras de cobrança atuais estão na página de preços da Meta.

Para comparar as bibliotecas a fundo, veja Baileys, whatsapp-web.js ou Cloud API. Para criar a lógica do bot, veja como fazer um bot de WhatsApp.

O que significa manter um bot de WhatsApp 24/7?#

Significa ter o processo rodando sem parar, numa máquina que não desliga, e a sessão salva de forma que um reinício não exija novo pareamento. No Baileys, a sessão são as chaves e credenciais gravadas na pasta de autenticação. Se essa pasta some, o bot vira um dispositivo novo e precisa ser pareado outra vez.

Por isso, rodar no notebook serve para testar, mas não para produção. Pelo mesmo motivo, o disco importa tanto quanto o processo: em ambientes cujo disco é apagado a cada deploy, o bot perde a sessão a cada atualização.

Como rodar um bot com Baileys?#

Crie o projeto e instale as dependências:

bash
npm init -y
npm pkg set type=module
npm install baileys

O Baileys 7 é um módulo ES, por isso o type=module. Defina duas variáveis de ambiente: WA_PHONE, o número do bot só com dígitos e código do país (por exemplo 5562999999999), e, opcionalmente, AUTH_DIR, a pasta da sessão. Não deixe o número nem credenciais no código.

Crie o index.js:

js
import makeWASocket, {
  DisconnectReason,
  useMultiFileAuthState,
} from "baileys";

const AUTH_DIR = process.env.AUTH_DIR ?? "auth_info";
const PHONE = process.env.WA_PHONE;

async function start() {
  const { state, saveCreds } = await useMultiFileAuthState(AUTH_DIR);
  const sock = makeWASocket({ auth: state });

  sock.ev.on("creds.update", saveCreds);

  sock.ev.on("connection.update", async ({ connection, lastDisconnect, qr }) => {
    // Primeira execução: sem sessão salva, gera um código de pareamento.
    if (qr && !sock.authState.creds.registered) {
      if (!PHONE) return console.error("Defina WA_PHONE para parear.");
      console.log("Código de pareamento:", await sock.requestPairingCode(PHONE));
    }

    if (connection === "open") console.log("Conectado ao WhatsApp.");

    if (connection === "close") {
      const code = lastDisconnect?.error?.output?.statusCode;
      if (code === DisconnectReason.loggedOut) {
        console.error("Sessão encerrada pelo celular. Apague a pasta e pareie de novo.");
        process.exit(1);
      }
      if (code === DisconnectReason.connectionReplaced) {
        console.error("Outra instância assumiu a sessão. Encerrando.");
        process.exit(1);
      }
      start(); // queda de rede ou reinício pedido pelo WhatsApp: reconecta
    }
  });

  sock.ev.on("messages.upsert", async ({ messages, type }) => {
    if (type !== "notify") return;
    for (const msg of messages) {
      if (msg.key.fromMe || !msg.message) continue;
      const text =
        msg.message.conversation ?? msg.message.extendedTextMessage?.text;
      if (text?.trim().toLowerCase() === "!ping") {
        await sock.sendMessage(msg.key.remoteJid, { text: "pong" });
      }
    }
  });
}

start();

Rode com WA_PHONE=5562999999999 node index.js. No WhatsApp do celular, abra Dispositivos conectados, escolha vincular com número de telefone e digite o código que apareceu no log. Depois de conectado, mande !ping de outro número: o bot responde pong.

Nas versões anteriores, a opção printQRInTerminal imprimia o QR code sozinha. No Baileys 7 ela foi descontinuada e não imprime mais nada: o QR chega no campo qr do evento connection.update, para você desenhar como quiser. O código de pareamento dispensa o QR e é mais fácil de ler num log de servidor.

Como a sessão sobrevive a reinícios?#

O useMultiFileAuthState grava credenciais e chaves na pasta de autenticação, e o evento creds.update chama o saveCreds sempre que algo muda. Na próxima execução, o Baileys lê a pasta e conecta sem QR nem código. A documentação do projeto alerta que as chaves precisam ser salvas sempre que mudam, senão as mensagens deixam de chegar ao destinatário.

Três cuidados:

  • Não apague nem sobrescreva a pasta num deploy. Mantenha-a fora do ZIP e do repositório.
  • Trate a pasta como senha. Quem a copia controla a sessão.
  • Só uma instância por sessão. Duas cópias do bot com as mesmas credenciais derrubam uma à outra.

O próprio useMultiFileAuthState é só um exemplo: o código-fonte do Baileys não o recomenda para produção, com a ressalva de que talvez sirva para um bot. Num projeto maior, guarde o estado num banco de dados.

Como usar a Cloud API oficial?#

Na Cloud API não há sessão nem pareamento. Você precisa de uma conta comercial na Meta, um número de telefone comercial e um servidor com HTTPS válido (certificado autoassinado não funciona). Veja como funciona o Let's Encrypt se precisar de um certificado.

A Meta confirma o endpoint com uma requisição GET: se hub.verify_token bater com o seu valor, você responde 200 com o hub.challenge. As mensagens chegam por POST e vêm assinadas no cabeçalho X-Hub-Signature-256. Um servidor mínimo, só com a biblioteca padrão do Node.js:

js
import { createServer } from "node:http";
import { createHmac, timingSafeEqual } from "node:crypto";

const {
  VERIFY_TOKEN,
  APP_SECRET,
  WA_TOKEN,
  PHONE_NUMBER_ID,
  GRAPH_API_VERSION,
  PORT = "8080",
} = process.env;
if (!GRAPH_API_VERSION) throw new Error("Defina GRAPH_API_VERSION (formato vXX.0) com uma versão do changelog da Graph API");

async function reply(to, body) {
  await fetch(`https://graph.facebook.com/${GRAPH_API_VERSION}/${PHONE_NUMBER_ID}/messages`, {
    method: "POST",
    headers: {
      "Content-Type": "application/json",
      Authorization: `Bearer ${WA_TOKEN}`,
    },
    body: JSON.stringify({
      messaging_product: "whatsapp",
      to,
      type: "text",
      text: { body },
    }),
  });
}

createServer(async (req, res) => {
  const url = new URL(req.url, "http://localhost");
  if (url.pathname !== "/webhook") return res.writeHead(404).end();

  if (req.method === "GET") {
    const ok =
      url.searchParams.get("hub.mode") === "subscribe" &&
      url.searchParams.get("hub.verify_token") === VERIFY_TOKEN;
    return res
      .writeHead(ok ? 200 : 403)
      .end(ok ? url.searchParams.get("hub.challenge") : "");
  }

  const chunks = [];
  for await (const chunk of req) chunks.push(chunk);
  const raw = Buffer.concat(chunks);

  const expected = Buffer.from(
    "sha256=" + createHmac("sha256", APP_SECRET).update(raw).digest("hex"),
  );
  const got = Buffer.from(req.headers["x-hub-signature-256"] ?? "");
  if (got.length !== expected.length || !timingSafeEqual(got, expected)) {
    return res.writeHead(401).end();
  }
  res.writeHead(200).end(); // responda rápido; a Meta repete entregas que falham

  for (const entry of JSON.parse(raw).entry ?? [])
    for (const change of entry.changes ?? [])
      for (const m of change.value?.messages ?? [])
        if (m.type === "text") await reply(m.from, `Você disse: ${m.text.body}`).catch(console.error);
}).listen(Number(PORT));

A Meta reenvia entregas que falham por até 7 dias, então o mesmo evento pode chegar duas vezes. Em produção, guarde o id de cada mensagem e ignore repetidas. Variáveis como WA_TOKEN e APP_SECRET entram por ambiente: veja o que são variáveis de ambiente. A versão da Graph API também, porque cada versão deixa de funcionar cerca de dois anos depois do lançamento: coloque em GRAPH_API_VERSION a mais recente do changelog da Graph API, no formato vXX.0, e quando ela envelhecer basta trocar o valor e reiniciar.

Como saber se o bot está online?#

  • Mande uma mensagem de teste (!ping) e confira a resposta.
  • No Baileys, procure Conectado ao WhatsApp. no log e observe se aparecem quedas em sequência.
  • Na Cloud API, use o teste de webhook do painel da Meta e confira se o servidor responde 200.
  • Confirme que o processo reinicia sozinho se parar. Em um VPS, essa é a função de systemd ou pm2.

Quais são os erros comuns?#

  • O bot pede código a cada reinício: a pasta de autenticação foi apagada ou o disco não é persistente. Salve a pasta em local que sobrevive ao deploy.
  • Sessão encerrada (loggedOut): o aparelho foi removido em Dispositivos conectados, ou o WhatsApp invalidou a sessão. Apague a pasta e pareie de novo.
  • Dois bots derrubando um ao outro (connectionReplaced): há outra instância com as mesmas credenciais, inclusive no seu PC. Mantenha uma só. Veja também por que o bot do WhatsApp desconecta.
  • Webhook da Cloud API não valida: hub.verify_token diferente do configurado, URL sem HTTPS válido ou rota errada.
  • Mensagem rejeitada fora da janela de 24 horas: só modelos aprovados podem iniciar a conversa depois que a janela fecha.
  • Cannot use import statement outside a module: falta "type": "module" no package.json.

Como fazer isso na Square Cloud#

A Square Cloud é hospedagem self-service: você envia o projeto, define a memória e controla tudo no painel. Ela funciona com Baileys, WPPConnect, whatsapp-web.js e a Cloud API oficial. A pasta de autenticação fica no disco da aplicação, então a sessão continua conectada depois de um restart.

Os containers ficam sempre ligados, sem modo de suspensão, com reinício automático (ligado por padrão no deploy pelo painel) quando o processo encerra com erro. WA_PHONE, WA_TOKEN, GRAPH_API_VERSION e as demais variáveis são definidas por aplicação no painel, e os logs em tempo real mostram o código de pareamento e os eventos de conexão. Você faz o deploy por ZIP, CLI, GitHub ou extensão do VS Code, e o squarecloud.app é opcional: o painel gera o arquivo com runtime, memória e arquivo principal, ou você o escreve na raiz do projeto.

Todos os planos são pagos e cobrados em reais. O Hobby custa R$ 12,49 por mês, com 1 GB de RAM compartilhado entre as suas aplicações, e o mínimo por aplicação de fundo, como um bot, é de 256 MB. Aplicações web, como o webhook da Cloud API, partem de 512 MB e ganham um subdomínio squareweb.app com HTTPS. Veja a página de hospedagem de bots de WhatsApp.

Hospedagem de bots

Seu bot online 24/7, com reinício automático

Saiba mais

Perguntas frequentes

O bot de WhatsApp precisa ficar com o computador ligado?

Precisa de um processo rodando em algum lugar. Se for o seu PC, o bot cai quando ele desliga ou perde a internet. Num servidor sempre ligado, ele continua respondendo sem depender da sua máquina.

Preciso parear o bot toda vez que ele reinicia?

Não, desde que a pasta de autenticação esteja salva em disco e não seja apagada. O Baileys lê as credenciais dessa pasta e reconecta sem novo pareamento. Só é preciso parear de novo se a sessão for encerrada pelo celular.

Preciso de domínio para hospedar um bot de WhatsApp?

Com o Baileys, não: o bot abre a conexão por conta própria. Com a Cloud API oficial, sim: a Meta entrega as mensagens por webhook, que exige uma URL pública com HTTPS e certificado válido.

Usar Baileys pode banir meu número?

Pode. Bibliotecas não oficiais não são autorizadas pelo WhatsApp, e os mantenedores do Baileys dizem não apoiar usos que violem os Termos de Serviço do WhatsApp, deixando a responsabilidade com quem usa. Para uso comercial, a Cloud API oficial evita esse risco.

Próximo artigoO que é um bot do Discord e como ele funcionaUm bot do Discord é um programa que usa uma conta de bot para receber eventos e agir nos servidores. Veja como Gateway, API, intents e comandos se encaixam.