Alerts & AutomationIntermediate
10 min read

Automated 14-Day Seat Availability Tracker in Python

Monitor Indian Railways seat availability across classes and quotas with a recurring Python daemon and instant Telegram/Discord alerts.

IRCTC Developer Relations
IRCTC Developer Relations
Platform Engineering
Updated 2026-10-25
Prerequisites
  • •Python 3.9+ with requests and schedule installed (pip install requests schedule)
  • •Free API key from https://irctc.dev/dashboard
  • •Telegram bot token and chat ID for notifications
Architecture Flow

Background Python daemon schedules periodic requests to https://api.irctc.dev/api/v1/trains/:trainNo/availability with date in DD-MM-YYYY format ➔ Parses 14-day availability array and tracks status changes in memory ➔ Fires Telegram webhook whenever status transitions from WL/RAC to AVAILABLE.

Implementation Steps

(4 Steps)
1

Install Dependencies & Setup Environment

Create a virtual environment and install requests for API communication and schedule for recurring execution.

bash
mkdir irctc-tracker && cd irctc-tracker
python3 -m venv venv
source venv/bin/activate # On Windows: .\venv\Scripts\activate
pip install requests schedule
# Set environment variables
export IRCTC_API_KEY="irctc_live_9a8f2c7e01d4"
export TELEGRAM_BOT_TOKEN="123456789:ABCdefGhIJKlmNoPQRsTUVwxyZ"
export TELEGRAM_CHAT_ID="987654321"
Tip:Never hardcode production API credentials in source control. Always load from environment variables.
2

Query 14-Day Live Availability with Date Parsing

Construct an authenticated HTTP GET request to the Seat Availability endpoint. Note that the date parameter must follow the DD-MM-YYYY format.

python
import os
import requests
from datetime import datetime
API_BASE = "https://api.irctc.dev"
API_KEY = os.environ.get("IRCTC_API_KEY")
def check_availability(train_no: str, src: str, dest: str, date_str: str, cls: str = "3A", quota: str = "GN"):
"""
Query Indian Railways PRS 14-day seat availability calendar.
date_str must be in DD-MM-YYYY format.
"""
url = f"{API_BASE}/api/v1/trains/{train_no}/availability"
headers = {
"x-api-key": API_KEY,
"accept": "application/json"
}
params = {
"from": src,
"to": dest,
"date": date_str,
"class": cls,
"quota": quota
}
resp = requests.get(url, headers=headers, params=params, timeout=10)
resp.raise_for_status()
data = resp.json()
if not data.get("success"):
raise ValueError(data.get("error", "Unknown API error"))
return data.get("availability", [])
Tip:Remember the Date Format Rule: Seat Availability uses DD-MM-YYYY, whereas Route Search uses YYYY-MM-DD.
3

State Machine & Change Detection

Keep an in-memory dictionary of last known statuses to prevent duplicate alert notifications. Trigger an alert only when a seat status flips to AVAILABLE.

python
# Track previous statuses to avoid duplicate alerts
last_status_cache = {}
def evaluate_status_change(train_no: str, day_record: dict) -> bool:
date_key = f"{train_no}_{day_record.get('date')}_{day_record.get('class')}"
current_status = day_record.get("status", "").upper()
previous_status = last_status_cache.get(date_key)
# Update cache
last_status_cache[date_key] = current_status
# Check if seats became AVAILABLE from a previously unavailable state
is_available = "AVAILABLE" in current_status or "CURR_AVBL" in current_status
was_unavailable = previous_status is not None and not ("AVAILABLE" in previous_status or "CURR_AVBL" in previous_status)
# Trigger alert if freshly available
return is_available and was_unavailable
Tip:You can also customize the filter to alert if Waitlist drops below a threshold (e.g. WL < 5).
4

Dispatch Telegram Alert & Run Recurring Daemon

Send markdown formatted notifications via Telegram Bot API and schedule the checker to run every 10 minutes.

python
import time
import schedule
BOT_TOKEN = os.environ.get("TELEGRAM_BOT_TOKEN")
CHAT_ID = os.environ.get("TELEGRAM_CHAT_ID")
def send_telegram_alert(message: str):
url = f"https://api.telegram.org/bot{BOT_TOKEN}/sendMessage"
payload = {
"chat_id": CHAT_ID,
"text": message,
"parse_mode": "Markdown"
}
try:
requests.post(url, json=payload, timeout=5)
except Exception as e:
print(f"Telegram notification error: {e}")
def job():
print(f"[{datetime.now().strftime('%H:%M:%S')}] Checking seat availability...")
try:
records = check_availability(
train_no="12557",
src="NKE",
dest="ANVT",
date_str="17-11-2026",
cls="3A",
quota="GN"
)
for record in records:
if evaluate_status_change("12557", record):
alert_text = (
f"🚨 *Train Ticket Alert!*
"
f"🚆 *Train:* 12557 (Sapt Kranti Express)
"
f"📅 *Date:* {record.get('date')}
"
f"💺 *Status:* {record.get('status')}
"
f"⚡ *Class:* 3A | *Quota:* GN
"
f"👉 Book immediately on IRCTC!"
)
send_telegram_alert(alert_text)
print("Alert dispatched!")
except Exception as err:
print(f"Error checking availability: {err}")
# Schedule job every 10 minutes
schedule.every(10).minutes.do(job)
# Run initial check immediately
job()
print("🚂 IRCTC Seat Availability Tracker running. Press Ctrl+C to stop.")
while True:
schedule.run_pending()
time.sleep(1)
Tip:For zero-downtime background execution on a server, run with systemd, Docker, or PM2.
Production Endpoint

IRCTC Seat Availability API

Test live queries and inspect sub-100ms response payloads directly in the browser sandbox.

Frequently Asked Questions

Related Tutorials

View All Guides →