انتقل إلى المحتوى
هذه الصفحة غير متوفرة بعد باللغة Arabic. نعرض النسخة الإنجليزية.

WhatsApp Automation with Node.js

آخر تحديث:

Which Node.js approach to use

The npm registry holds many WhatsApp packages. They fall into three groups with very different risk.

Node.js approaches to WhatsApp automation compared
ApproachOfficialGood forRisk
Cloud API with fetch or axiosOfficialYesGood forProduction bots, notifications, CRM syncRiskYou build and host the webhook
Provider SDK (for example Twilio's Node.js library)OfficialYes, through a Business Solution ProviderGood forTeams that prefer provider-managed infrastructureRiskProvider fees and its own API shape
Packages that drive WhatsApp Web or reverse engineer itOfficialNoGood forPersonal experiments onlyRiskNumber can be restricted or banned; breaks when WhatsApp changes

What you need first

The setup matches the Python guide. The code reads these from environment variables.

  • A Meta developer account and an app with the WhatsApp product.
  • A phone number ID for the number you send from. A test number is available during development.
  • An access token, ideally from a system user, since temporary tokens expire quickly.
  • Your app secret, to verify webhook signatures.
  • A public HTTPS URL for the webhook, and Node.js 18 or later for the built-in fetch.

Send a message

Sending is one authenticated POST. Free-form text works only inside the 24-hour customer service window. Outside it, send an approved template.

send-message.mjsjavascript
const API_VERSION = process.env.WA_API_VERSION ?? "v21.0"; // use a version Meta currently supports
const PHONE_NUMBER_ID = process.env.WA_PHONE_NUMBER_ID;
const TOKEN = process.env.WA_ACCESS_TOKEN;
const URL = `https://graph.facebook.com/${API_VERSION}/${PHONE_NUMBER_ID}/messages`;

async function post(payload) {
  const response = await fetch(URL, {
    method: "POST",
    headers: { Authorization: `Bearer ${TOKEN}`, "Content-Type": "application/json" },
    body: JSON.stringify(payload),
    signal: AbortSignal.timeout(10_000),
  });
  if (!response.ok) throw new Error(`WhatsApp API ${response.status}: ${await response.text()}`);
  return response.json();
}

/** Free-form text. Only valid inside the 24-hour customer service window. */
export function sendText(to, body) {
  return post({ messaging_product: "whatsapp", to, type: "text", text: { body } });
}

/** Approved template. Required to start a conversation or after the 24-hour window. */
export function sendTemplate(to, name, language = "en") {
  return post({
    messaging_product: "whatsapp",
    to,
    type: "template",
    template: { name, language: { code: language } },
  });
}

Receive messages with an Express webhook

A GET request verifies the endpoint once; POST requests deliver messages. Capture the raw body so the X-Hub-Signature-256 header can be checked against exactly what Meta sent.

server.mjsjavascript
import crypto from "node:crypto";
import express from "express";
import { sendText } from "./send-message.mjs";

const VERIFY_TOKEN = process.env.WA_VERIFY_TOKEN;
const APP_SECRET = process.env.WA_APP_SECRET;
const seen = new Set(); // use Redis or a database in production

const app = express();
app.use(express.json({ verify: (req, _res, buf) => { req.rawBody = buf; } }));

app.get("/webhook", (req, res) => {
  if (req.query["hub.mode"] === "subscribe" && req.query["hub.verify_token"] === VERIFY_TOKEN) {
    return res.status(200).send(req.query["hub.challenge"]);
  }
  res.sendStatus(403);
});

function validSignature(req) {
  const header = req.get("X-Hub-Signature-256") ?? "";
  if (!header.startsWith("sha256=") || !req.rawBody) return false;
  const expected = crypto.createHmac("sha256", APP_SECRET).update(req.rawBody).digest("hex");
  const received = header.slice("sha256=".length);
  return received.length === expected.length &&
    crypto.timingSafeEqual(Buffer.from(received), Buffer.from(expected));
}

app.post("/webhook", (req, res) => {
  if (!validSignature(req)) return res.sendStatus(403);
  res.sendStatus(200); // acknowledge fast; do slow work in a queue

  for (const entry of req.body.entry ?? []) {
    for (const change of entry.changes ?? []) {
      for (const message of change.value?.messages ?? []) {
        if (seen.has(message.id)) continue; // Meta may deliver the same message more than once
        seen.add(message.id);
        handleMessage(message).catch(console.error);
      }
    }
  }
});

async function handleMessage(message) {
  const text = (message.text?.body ?? "").trim().toLowerCase();
  if (text === "price" || text === "pricing") {
    await sendText(message.from, "Our pricing depends on your volume. Reply HUMAN to talk to a person.");
  } else if (text === "human") {
    await sendText(message.from, "Thanks, a team member will reply shortly.");
    // notify your team here
  } else {
    await sendText(message.from, "Hi! Reply PRICE for pricing or HUMAN to talk to a person.");
  }
}

app.listen(8000);

Judging an npm package before you depend on it

Searches for "whatsapp automation npm" and "whatsapp automation library" return packages of very different quality. Check these before installing:

  • Does the README say it uses Meta's Cloud API or a provider API, or does it drive WhatsApp Web with a browser or reverse-engineered protocol?
  • Does the project itself warn about number bans or say it is not endorsed by WhatsApp?
  • When was the last release, and are security issues handled?
  • Does it verify webhook signatures, or leave that to you?
  • Is it a thin typed wrapper over the official API? Those are the lowest-risk to adopt, and you can also call the API directly as shown above.

Common errors and what they usually mean

The same causes appear in every language.

  • Text messages rejected after a quiet day: the 24-hour window closed, so use an approved template.
  • Signature check fails: the body was parsed before hashing, or the app secret is wrong.
  • Webhook verifies but gets no messages: the app is not subscribed to the messages field.
  • Duplicate replies: Meta retried because the response was slow, so respond with 200 first and deduplicate by message ID.

ابدأ تجربتك لمدة 7 أيام

اكتشف كيف تساعد أتمتة واتساب نشاطك التجاري على جذب العملاء المحتملين وأتمتة المحادثات والمتابعة بشكل أسرع.

تُرسل بياناتك فقط ضمن رسالة واتساب التي ترسلها. هذا الموقع لا يخزّنها.

الأسئلة الشائعة

How do I send a WhatsApp message with Node.js?

Send an authenticated POST request to the Cloud API messages endpoint with fetch. The request carries your access token and a JSON body containing the recipient number and the message.

Is whatsapp-web.js safe for business use?

It is an unofficial client that drives WhatsApp Web. That is not part of the official platform and carries a risk of the number being restricted, so it is not recommended for customer-facing business messaging.

Is there an official WhatsApp npm package?

The official route is Meta's Cloud API over HTTP, which needs no special package. Some providers publish their own SDKs. Verify any package's approach before using it.

Should I use Node.js or Python?

Both use the same API, so choose the language your team can maintain. The Python guide covers the same flow.

المصادر

About this page

Published by WhatsAppAutomation.si.

Pages here are written and reviewed in-house, cite Meta's documentation for platform rules, and carry a last-updated date. WhatsApp's pricing and policies change, so confirm anything that affects a decision against Meta's current documentation.

Found an error or something out of date?Tell us on WhatsApp

Want to automate this for your business?

Tell us what you are trying to automate and we will reply on WhatsApp.