Node.js tutorial

Send a WhatsApp Message with Node.js

Send WhatsApp messages from Node.js with built-in fetch: text, images and documents, error handling and delivery status. No packages needed.

Updated 6 October 2026 ยท by BriskBrain Technologies

Here's how to send a WhatsApp message from Node.js using the fetch function that's built into Node.js 18 and newer — no npm packages to install. You'll end up with a small module you can use from an Express or Next.js app, a background worker or a one-off script, to send text, images and documents and track delivery.

Check your version with node --version; you need 18 or newer.

Before you start

You need three things from your InstaMessage dashboard. It takes about five minutes:

  1. A free account. Sign up here — no card needed.
  2. A connected instance. Create an instance and scan its QR code with WhatsApp on your phone (Settings → Linked devices → Link a device), until its status shows Connected.
  3. Your instance_id and access_token. On the instance's page, generate an API credential. The token is shown only once, so copy it somewhere safe straight away.

Keep both out of your code: store them as environment variables, so they never end up in Git. On macOS or Linux:

Terminal (macOS / Linux)
export INSTAMESSAGE_INSTANCE_ID="your-instance-id"
export INSTAMESSAGE_TOKEN="your-access-token"

On Windows (PowerShell):

PowerShell (Windows)
$env:INSTAMESSAGE_INSTANCE_ID = "your-instance-id"
$env:INSTAMESSAGE_TOKEN = "your-access-token"
Phone number format: country code first, digits only — no +, spaces or leading 0. For example +91 98765 43210 becomes 919876543210.

Step 1: Write a small module

Save this as instamessage.mjs. It adds your token to every request and throws an error with the API's own message when something goes wrong:

instamessage.mjs
const API_URL = "https://instamessage.in/api/v1";
const INSTANCE_ID = process.env.INSTAMESSAGE_INSTANCE_ID;
const TOKEN = process.env.INSTAMESSAGE_TOKEN;

async function request(method, path, body) {
  const response = await fetch(API_URL + path, {
    method,
    headers: {
      Authorization: "Bearer " + TOKEN,
      "Content-Type": "application/json",
      Accept: "application/json",
    },
    body: body ? JSON.stringify(body) : undefined,
    // Media files are downloaded before sending, so allow up to 60 seconds.
    signal: AbortSignal.timeout(60_000),
  });

  const data = await response.json().catch(() => ({}));

  if (!response.ok || !data.success) {
    throw new Error(data.error ?? "Request failed with HTTP " + response.status);
  }

  return data;
}

// Send a WhatsApp message. Extra fields (type, media_url, file_name) are passed through.
export function sendMessage(to, message, extra = {}) {
  return request("POST", "/messages/send", { instance_id: INSTANCE_ID, to, message, ...extra });
}

// Look up a sent message, including its delivery status.
export async function getMessage(messageId) {
  const data = await request("GET", "/messages/" + encodeURIComponent(messageId));
  return data.message;
}

The .mjs ending lets you use import / export without changing your package.json.

Step 2: Send your first text message

Create send.mjs with your own WhatsApp number to test it:

send.mjs
import { sendMessage } from "./instamessage.mjs";

const result = await sendMessage("919876543210", "Hello from Node.js! ๐Ÿ‘‹");
console.log("Sent! Message ID:", result.message_id);
Terminal
node send.mjs

Within a second or two the message lands on the phone. result holds the API's reply, for example { success: true, message_id: "3EB0A1B2C3D4E5F6", sent_via: "device", fallback_status: null }.

Step 3: Handle errors

Use try / catch — the error message is the API's explanation, or the network problem:

JavaScript
import { sendMessage } from "./instamessage.mjs";

try {
  await sendMessage("919876543210", "Your OTP is 482913. It expires in 10 minutes.");
} catch (error) {
  console.error("WhatsApp message failed:", error.message);
}

What usually causes an error:

  • HTTP 401 — the access token is missing, wrong or revoked.
  • "Instance is not connected" — reconnect the instance from your dashboard.
  • "instance_id does not match this token" — the token is for a different instance.
  • "You've reached your plan's monthly message limit" — upgrade, or wait for the new month.
  • HTTP 429 — more than 30 send requests in a minute; wait and try again.

Step 4: Send an image or a document

Pass a type and a public media_url as extra fields. The text becomes an optional caption:

JavaScript
import { sendMessage } from "./instamessage.mjs";

// An image with a caption (JPG, PNG or WebP, up to 5 MB)
await sendMessage("919876543210", "Just in: our new collection", {
  type: "image",
  media_url: "https://example.com/images/new-arrival.jpg",
});

// A PDF, with the file name the recipient will see
await sendMessage("919876543210", "Here is your invoice.", {
  type: "document",
  media_url: "https://example.com/invoices/42.pdf",
  file_name: "Invoice-42.pdf",
});

Videos, audio and voice notes work the same way — the media rules list every type and size limit.

Step 5: Check if it was delivered and read

JavaScript
import { getMessage, sendMessage } from "./instamessage.mjs";

const result = await sendMessage("919876543210", "Did you get this?");

const message = await getMessage(result.message_id);
console.log(message.status); // pending, sent, delivered, read or failed

read only appears when the recipient has read receipts turned on. To get delivery and read updates pushed to your server as they happen, set a webhook on your instance.

Protect your WhatsApp number

WhatsApp can restrict or ban a number that looks like it's sending spam. Only message people who expect to hear from you, keep your volume steady, and avoid sending the same text to large lists. Read the full do's and don'ts before you go live.

Next steps

More guides