How to Build a Real-Time WhatsApp Train Tracking & PNR Bot in Node.js (2026 Tutorial)

How to Build a Real-Time WhatsApp Train Tracking & PNR Bot in Node.js (2026 Tutorial)

# node# typescript# webdev# tutorial
How to Build a Real-Time WhatsApp Train Tracking & PNR Bot in Node.js (2026 Tutorial)Manjot Singh

Original Resource: This guide is officially published on the IRCTC Developer Platform. Have you ever...

Original Resource: This guide is officially published on the IRCTC Developer Platform.

Have you ever been stuck at a railway platform frantically refreshing slow apps to find out where your train is or whether your RAC/WL ticket confirmed?

In this tutorial, we will build a production-ready WhatsApp bot in Node.js & TypeScript that lets you check live train running status, delay minutes, and 10-digit PNR status directly in WhatsApp with zero Twilio or Meta WhatsApp Business API costs.


Architecture Overview

User sends WhatsApp message (!live 12557)
    │
    ▼
[@whiskeysockets/baileys Multi-Device Socket]
    │
    ▼
Command Parser (!live <train> | !pnr <pnr>)
    │
    ▼
[IRCTC API Gateway: https://api.irctc.dev]
    │
    ▼
Formatted WhatsApp Response (Delays, Halts, Coach & Berths)
Enter fullscreen mode Exit fullscreen mode

Prerequisites

  1. Node.js 18+ LTS installed on your system.
  2. A mobile phone with WhatsApp installed to scan the QR code.
  3. A free IRCTC API Key from irctc.dev/dashboard (every developer receives 10,000 free requests upon 1-click Google signup with zero credit card required).

Step 1: Initialize Project & Install Dependencies

Create a new directory and install @whiskeysockets/baileys (for WhatsApp Web multi-device connection), qrcode-terminal, irctc-api, and dotenv:

mkdir irctc-whatsapp-bot && cd irctc-whatsapp-bot
npm init -y
npm install @whiskeysockets/baileys qrcode-terminal irctc-api dotenv
npm install -D typescript @types/node ts-node
npx tsc --init
Enter fullscreen mode Exit fullscreen mode

Step 2: Configure Environment Variables

Create a .env file in your root folder:

IRCTC_API_KEY=your_irctc_api_key_here
BOT_PREFIX=!
NODE_ENV=production
Enter fullscreen mode Exit fullscreen mode

Step 3: Implement WhatsApp Socket & Railway Commands

Create src/index.ts and set up the Baileys socket with persistent multi-file authentication so you only have to scan the QR code once:

import makeWASocket, {
  DisconnectReason,
  useMultiFileAuthState
} from '@whiskeysockets/baileys';
import { Boom } from '@hapi/boom';
import qrcode from 'qrcode-terminal';
import { IrctcApi } from 'irctc-api';
import dotenv from 'dotenv';

dotenv.config();

const irctc = new IrctcApi({
  apiKey: process.env.IRCTC_API_KEY || ''
});

async function startBot() {
  const { state, saveCreds } = await useMultiFileAuthState('auth_info_baileys');

  const sock = makeWASocket({
    auth: state,
    printQRInTerminal: false
  });

  sock.ev.on('connection.update', (update) => {
    const { connection, lastDisconnect, qr } = update;
    if (qr) {
      console.log('⚡ Scan this QR code with WhatsApp on your phone:');
      qrcode.generate(qr, { small: true });
    }
    if (connection === 'close') {
      const shouldReconnect =
        (lastDisconnect?.error as Boom)?.output?.statusCode !== DisconnectReason.loggedOut;
      if (shouldReconnect) startBot();
    } else if (connection === 'open') {
      console.log('✅ IRCTC WhatsApp Bot is online!');
    }
  });

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

  // Incoming Message Handler
  sock.ev.on('messages.upsert', async ({ messages, type }) => {
    if (type !== 'notify') return;
    const msg = messages[0];
    if (!msg.message || msg.key.fromMe) return;

    const sender = msg.key.remoteJid!;
    const text =
      msg.message.conversation ||
      msg.message.extendedTextMessage?.text ||
      '';

    const trimmed = text.trim();

    // 1. Live Running Status Command (!live 12557)
    if (trimmed.startsWith('!live ')) {
      const trainNo = trimmed.replace('!live ', '').trim();
      try {
        await sock.sendMessage(sender, { text: `🔍 Checking live status for ${trainNo}...` });
        const live = await irctc.live.getStatus(trainNo);

        const reply = `🚆 *Train ${live.trainNumber} — ${live.trainName}*
📍 *Current Location:* ${live.currentLocation} (${live.locationStatus})
⏱️ *Status:* ${live.currentDelayMin > 0 ? `Delayed by ${live.currentDelayMin} mins 🔴` : 'Running On Time 🟢'}
🎯 *Next Station:* ${live.stops?.find((s: any) => s.status === 'upcoming')?.stationName || 'In Transit'}

⚡ _Powered by irctc.dev_`;

        await sock.sendMessage(sender, { text: reply });
      } catch (err: any) {
        await sock.sendMessage(sender, { text: `❌ ${err.message}` });
      }
    }

    // 2. Real-Time PNR Status Command (!pnr 2265248473)
    if (trimmed.startsWith('!pnr ')) {
      const pnr = trimmed.replace('!pnr ', '').trim();
      try {
        await sock.sendMessage(sender, { text: `🔍 Verifying PNR ${pnr}...` });
        const data = await irctc.pnr.check(pnr);

        const passengerList = (data.passengers || [])
          .map((p: any, i: number) => `  • P${i + 1}: *${p.currentStatus}* (Coach ${p.coach || 'N.A'}, Seat ${p.berthNumber || 'N.A'} [${p.berth || 'N.A'}])`)
          .join('\n');

        const reply = `🎫 *IRCTC PNR Status: ${pnr}*
🚆 *Train:* ${data.trainNumber} - ${data.trainName}
🗓️ *Date:* ${data.journeyDate} (${data.from?.code} ➔ ${data.to?.code})
📊 *Charting:* ${data.chartStatus}

👥 *Passenger Manifest:*
${passengerList}

⚡ _Powered by irctc.dev_`;

        await sock.sendMessage(sender, { text: reply });
      } catch (err: any) {
        await sock.sendMessage(sender, { text: `❌ ${err.message}` });
      }
    }
  });

  return sock;
}

startBot();
Enter fullscreen mode Exit fullscreen mode

Step 4: Run the Bot

Start your bot in development:

npx ts-node src/index.ts
Enter fullscreen mode Exit fullscreen mode
  1. Scan the terminal QR code using WhatsApp on your phone (Linked Devices ➔ Link a Device).
  2. Once connected, open any WhatsApp chat and send:
    • !live 12557 (Fetches live GPS status, platform, and delay in under 400ms).
    • !pnr 2265248473 (Fetches passenger coach and berth allocations).

Test it right now in your terminal (No code required)

If you want to test the underlying Indian Railways API directly without setting up WhatsApp, run:

npx irctc-api live 12557
npx irctc-api pnr 2265248473
Enter fullscreen mode Exit fullscreen mode

You can claim 10,000 free requests directly at irctc.dev/dashboard.