DEV Community

Cover image for How to Check Indian Railway PNR Status Programmatically (Node.js & Python Guide)
Manjot Singh
Manjot Singh

Posted on Originally published at irctc.dev

How to Check Indian Railway PNR Status Programmatically (Node.js & Python Guide)

Original Guide: This article was originally published on IRCTC Developer Platform.

Checking the status of an Indian Railways Passenger Name Record (PNR) programmatically has historically been frustrating: brittle web scrapers, OCR-based captcha captchas, and random IP bans.

In this guide, we'll cover how to query official CRIS PRS live PNR records in under 100ms using Node.js and Python with zero scraping maintenance.


Anatomy of a 10-Digit PNR

A PNR number consists of:

  • First 3 Digits: PRS Reservation Zone (e.g., 226 for Northern Railway CRIS PRS).
  • Last 7 Digits: Unique transaction serial number.

Method 1: Node.js & TypeScript with irctc-api

The official client SDK handles authentication, keep-alive connections, and TypeScript types out of the box.

Installation

npm install irctc-api
Enter fullscreen mode Exit fullscreen mode

Code

import { IrctcApi } from 'irctc-api';

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

async function verifyBooking(pnrNumber: string) {
  try {
    const pnr = await client.pnr.check(pnrNumber);

    console.log(`🚆 Train: ${pnr.trainNumber} - ${pnr.trainName}`);
    console.log(`🛣️ Route: ${pnr.from} -> ${pnr.to} | Date: ${pnr.doj}`);
    console.log(`📊 Chart Status: ${pnr.chartStatus}`);

    pnr.passengers.forEach((p, idx) => {
      console.log(`  • Passenger ${idx + 1}: ${p.currentStatus} | Coach: ${p.coach || 'N.A'} | Berth: ${p.berthNumber || 'N.A'} [${p.berth || 'N.A'}]`);
    });
  } catch (error: any) {
    console.error('PNR verification error:', error.message);
  }
}

verifyBooking('2265248473');
Enter fullscreen mode Exit fullscreen mode

Method 2: Python with requests

If you are building in Python (Django, Flask, FastAPI, Celery):

Installation

pip install requests
Enter fullscreen mode Exit fullscreen mode

Code

import os
import requests

API_KEY = os.getenv("IRCTC_API_KEY", "irctc_live_9a8f2c7e01d4")
PNR = "2265248473"

url = f"https://api.irctc.dev/api/v1/pnr/{PNR}"
headers = {
    "x-api-key": API_KEY,
    "accept": "application/json",
    "User-Agent": "pnr-client/v1.0"
}

response = requests.get(url, headers=headers, timeout=5.0)

if response.status_code == 200:
    data = response.json().get("data", {})
    print(f"Train: {data.get('trainNumber')} - {data.get('trainName')}")
    print(f"Date: {data.get('doj')} ({data.get('from')} -> {data.get('to')})")
    print(f"Chart: {data.get('chartStatus')}")

    for idx, p in enumerate(data.get("passengers", []), 1):
        print(f"  P{idx}: {p.get('currentStatus')} | Coach: {p.get('coach', 'N.A')} | Seat: {p.get('berthNumber', 'N.A')} [{p.get('berth', 'N.A')}]")
else:
    print(f"Error {response.status_code}: {response.text}")
Enter fullscreen mode Exit fullscreen mode

Understanding Passenger Fields

Field Description Values
currentStatus Current booking status CNF, RAC 12, WL 45
coach Reserved coach B2, S4, M1, N.A
berthNumber Specific berth number 18, 45, N.A
berth Clean normalized berth type LOWER BERTH, MIDDLE BERTH, UPPER BERTH, SIDE LOWER, SIDE UPPER
chartStatus PRS charting status CHART NOT PREPARED, CHART PREPARED

Recommended Polling Schedule (Smart Backoff)

Do NOT poll PNR every few seconds. PNR statuses only update upon ticket cancellation or chart preparation.

  • > 48 hours to departure: Poll once every 24 hours.
  • 12 – 48 hours to departure: Poll every 4 hours.
  • < 4 hours to departure: Poll every 15 minutes to catch chart preparation.

Resources

Top comments (0)