
Como Substituir o Baileys pelo whatsmeow-node
Se você usa o Baileys e está enfrentando problemas de manutenção, instabilidade de forks ou quer um upstream mais confiável, o whatsmeow-node é uma alternativa direta com uma superfície de API similar. Este guia mapeia os conceitos-chave e mostra como migrar.
Por Que Migrar?
- Upstream estável — o whatsmeow é mantido pelo time Mautrix e usado em produção por milhares de bridges Matrix 24/7. Quando o WhatsApp muda o protocolo, as correções chegam rápido.
- Sem roleta de forks — o Baileys já passou por múltiplos forks (adiwajshing, WhiskeySockets, outros). O whatsmeow-node encapsula uma única biblioteca Go estável.
- Menos memória — ~10-20 MB vs ~50 MB típicos do Baileys.
- API tipada — mais de 100 métodos async tipados com design TypeScript-first.
Veja a Comparação com Alternativas para mais detalhes.
Passo 1: Instalar
# Remove Baileys
npm uninstall @whiskeysockets/baileys
# Install whatsmeow-node
npm install @whatsmeow-node/whatsmeow-node
Passo 2: Atualizar a Inicialização do Client
Baileys
import makeWASocket, { useMultiFileAuthState } from "@whiskeysockets/baileys";
const { state, saveCreds } = await useMultiFileAuthState("auth_info");
const sock = makeWASocket({ auth: state });
sock.ev.on("creds.update", saveCreds);
whatsmeow-node
import { createClient } from "@whatsmeow-node/whatsmeow-node";
const client = createClient({ store: "session.db" });
const { jid } = await client.init();
await client.connect();
A persistência da sessão é automática — não precisa de callback saveCreds. A opção store aceita um caminho de arquivo (SQLite) ou uma string de conexão PostgreSQL.
Você precisará parear novamente (escanear QR code) após a troca. O estado de autenticação do Baileys não é compatível com sessões do whatsmeow.
Passo 3: Atualizar os Listeners de Eventos
Mensagens
Baileys:
sock.ev.on("messages.upsert", ({ messages }) => {
for (const msg of messages) {
if (msg.key.fromMe) continue;
const text = msg.message?.conversation
?? msg.message?.extendedTextMessage?.text;
console.log(`${msg.pushName}: ${text}`);
}
});
whatsmeow-node:
client.on("message", ({ info, message }) => {
if (info.isFromMe) return;
const text =
(message.conversation as string) ??
(message.extendedTextMessage as { text?: string } | undefined)?.text;
console.log(`${info.pushName}: ${text}`);
});
Diferenças principais:
- Uma mensagem por evento (sem batch)
- Metadados da mensagem ficam em
info, conteúdo protobuf fica emmessage info.isFromMesubstituimsg.key.fromMeinfo.chatsubstituimsg.key.remoteJidinfo.sendersubstituimsg.key.participant(em grupos)
Conexão
Baileys:
sock.ev.on("connection.update", ({ connection, lastDisconnect }) => {
if (connection === "open") console.log("Connected!");
if (connection === "close") { /* handle reconnection */ }
});
whatsmeow-node:
client.on("connected", ({ jid }) => console.log(`Connected as ${jid}`));
client.on("disconnected", () => console.log("Disconnected"));
client.on("logged_out", ({ reason }) => console.error(`Logged out: ${reason}`));
Você não precisa de lógica manual de reconexão — o whatsmeow faz isso automaticamente.
Passo 4: Atualizar o Envio de Mensagens
Mensagem de texto
Baileys:
await sock.sendMessage(jid, { text: "Hello!" });
whatsmeow-node:
await client.sendMessage(jid, { conversation: "Hello!" });
Resposta com citação
Baileys:
await sock.sendMessage(jid, { text: "Reply!" }, { quoted: msg });
whatsmeow-node:
await client.sendRawMessage(jid, {
extendedTextMessage: {
text: "Reply!",
contextInfo: {
stanzaId: info.id,
participant: info.sender,
quotedMessage: { conversation: originalText },
},
},
});
Mídia
Baileys:
await sock.sendMessage(jid, {
image: { url: "/path/to/photo.jpg" },
caption: "Check this out",
});
whatsmeow-node:
const media = await client.uploadMedia("/path/to/photo.jpg", "image");
await client.sendRawMessage(jid, {
imageMessage: {
URL: media.URL,
directPath: media.directPath,
mediaKey: media.mediaKey,
fileEncSHA256: media.fileEncSHA256,
fileSHA256: media.fileSHA256,
fileLength: String(media.fileLength),
mimetype: "image/jpeg",
caption: "Check this out",
},
});
O upload e o envio de mídia são etapas separadas no whatsmeow-node. Isso dá mais controle (ex.: fazer upload uma vez, enviar para vários chats).
Reações
Baileys:
await sock.sendMessage(jid, { react: { text: "👍", key: msg.key } });
whatsmeow-node:
await client.sendReaction(jid, senderJid, messageId, "👍");
Passo 5: Atualizar Operações de Grupo
| Baileys | whatsmeow-node |
|---|---|
sock.groupCreate(name, members) | client.createGroup(name, members) |
sock.groupMetadata(jid) | client.getGroupInfo(jid) |
sock.groupFetchAllParticipating() | client.getJoinedGroups() |
sock.groupUpdateSubject(jid, name) | client.setGroupName(jid, name) |
sock.groupUpdateDescription(jid, desc) | client.setGroupDescription(jid, desc) |
sock.groupSettingUpdate(jid, "announcement") | client.setGroupAnnounce(jid, true) |
sock.groupParticipantsUpdate(jid, [jid], "add") | client.updateGroupParticipants(jid, [jid], "add") |
sock.groupInviteCode(jid) | client.getGroupInviteLink(jid) |
sock.groupLeave(jid) | client.leaveGroup(jid) |
Referência Rápida de API
| Baileys | whatsmeow-node |
|---|---|
makeWASocket() | createClient() |
sock.sendMessage(jid, content) | client.sendMessage(jid, content) |
sock.readMessages([key]) | client.markRead([id], chat, sender) |
sock.sendPresenceUpdate("available") | client.sendPresence("available") |
sock.presenceSubscribe(jid) | client.subscribePresence(jid) |
sock.profilePictureUrl(jid) | client.getProfilePicture(jid) |
sock.updateBlockStatus(jid, "block") | client.updateBlocklist(jid, "block") |
sock.logout() | client.logout() |
Checklist de Migração
- Instalar
@whatsmeow-node/whatsmeow-node, remover@whiskeysockets/baileys - Substituir
makeWASocketporcreateClient - Remover
useMultiFileAuthState— a sessão é tratada automaticamente - Atualizar listeners de eventos (
ev.onporclient.on, nomes de eventos diferentes) - Atualizar chamadas de
sendMessage(textporconversation) - Atualizar envio de mídia (etapas separadas de upload + envio)
- Atualizar operações de grupo (nomes dos métodos diferem levemente)
- Remover lógica manual de reconexão — o whatsmeow reconecta automaticamente
- Parear novamente via QR code (nova sessão necessária)
- Testar todos os tipos de mensagem de ponta a ponta
Erros Comuns
O estado de autenticação do Baileys não pode ser migrado. Você precisa parear uma nova sessão escaneando o QR code. Seu histórico de conversas e contatos do WhatsApp não são afetados — apenas o vínculo do dispositivo é novo.
text vs conversationO Baileys usa { text: "..." } para mensagens. O whatsmeow-node usa { conversation: "..." } — seguindo o nome do campo protobuf do WhatsApp.
Os campos da resposta do upload usam o casing exato do protobuf: URL, fileSHA256, fileEncSHA256 — não camelCase. Usar o casing errado falha silenciosamente.





