Indian Railways Scraper - Schedules, Fares & Live Status
Indian Railways Trains, Schedules & Live Status Scraper
Scrape Indian Railways train data without IRCTC logins or paid APIs. Returns schedules between stations, full train routes with per-stop timings, fares by class, and live running status — pulled from public sources at erail.in and runningstatus.in.
Indian Railways Scraper Features
- Searches all trains running between any two Indian Railways stations
- Looks up a train by number and returns its full route, fares, and seat availability
- Tracks live train running status — current position, delay, and next scheduled stop
- Returns fares per class in INR (1A / 2A / 3A / SL / CC / EC / 2S / 3E / FC) where the source publishes them
- Decodes the IR weekly bitmask into a clean array of three-letter day labels
- Pure HTTP — no browser, no captcha solver, no proxy required
- Handles all train types: Rajdhani, Shatabdi, Vande Bharat, Duronto, Garib Rath, Superfast, Mail/Express, Passenger
- Coverage spans 13,000+ trains and 7,300+ stations across the Indian Railways network
Who Uses Indian Railways Train Data?
- Travel apps — Power booking flows that need IR schedules without paying RailAPI rates per query.
- Aggregators — Combine train, bus, and flight inventory into a single multi-modal route engine.
- Fintech and SaaS — Embed train running status into expense apps, employee travel tools, or logistics dashboards.
- Researchers and analysts — Build mobility datasets, study delay patterns, or model passenger flows on the world's busiest rail network.
- Indian developers building side projects — Skip the IRCTC API approval queue and just get the data.
How the Indian Railways Scraper Works
- Pick a mode —
train_search,train_number, orlive_status. - Provide the inputs that mode needs (station codes, or a list of train numbers).
- The scraper hits erail.in for schedules and fares, and runningstatus.in for live status.
- Each train comes back as one record in the dataset, with consistent field names across modes.
Input
{
"mode": "train_search",
"originStation": "NDLS",
"destinationStation": "BCT",
"maxItems": 50,
"sp_intended_usage": "test",
"sp_improvement_suggestions": "test"
}
| Field | Type | Default | Description |
|---|---|---|---|
mode |
string | "train_search" |
One of train_search, train_number, live_status, pnr_status. |
originStation |
string | "NDLS" |
Indian Railways station code for the boarding station (e.g. NDLS, BCT, MAS, HWH). Used by train_search. |
destinationStation |
string | "BCT" |
Station code for the alighting station. Used by train_search. |
trainNumbers |
array of strings | [] |
Train numbers to look up (e.g. ["12951", "22439"]). Used by train_number and live_status. |
date |
string | "" (today) |
Optional YYYY-MM-DD date for live_status. Other modes ignore this. |
maxItems |
integer | 50 |
Maximum number of records returned. |
proxyConfiguration |
object | {useApifyProxy:false} |
Leave default. erail.in and runningstatus.in are public and don't need proxies. |
Train number lookup
{
"mode": "train_number",
"trainNumbers": ["12951", "12302"],
"maxItems": 5
}
Live train status
{
"mode": "live_status",
"trainNumbers": ["12951"],
"maxItems": 1
}
pnr_status mode is reserved in the schema for a future release. The IRCTC PNR flow needs a CAPTCHA solver and an India residential proxy, and v1 chooses to be honest about that rather than ship something flaky. The actor returns a clear error if you select it.
Indian Railways Scraper Output Fields
Every record uses the same schema regardless of mode. Fields that don't apply to the chosen mode are returned as empty arrays, empty objects, or empty strings.
train_search example
{
"train_number": "12951",
"train_name": "Mumbai Central New Delhi MUMBAI RAJDHANI",
"train_type": "RAJDHANI",
"origin_station": "Mumbai Central",
"origin_code": "MMCT",
"destination_station": "New Delhi",
"destination_code": "NDLS",
"from_station": "Mumbai Central",
"from_code": "MMCT",
"to_station": "New Delhi",
"to_code": "NDLS",
"departure_time": "17:00",
"arrival_time": "08:32",
"duration_minutes": 932,
"distance_km": 1384,
"runs_on": ["Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"],
"classes_available": ["1A", "2A", "3A"],
"route_stations": [],
"fare_by_class": {"1A": 5335, "2A": 3235, "3A": 2405},
"seat_availability": [
"1A: avail 10",
"2A: avail 87 / WL 60 / RAC 20",
"3A: avail 266 / WL 160 / RAC 55"
],
"live_status": {},
"source_url": "https://erail.in/rail/getTrains.aspx?Station_From=BCT&Station_To=NDLS",
"scraped_at": "2026-04-25T13:57:07.231Z"
}
train_number example
Same schema as above, plus a populated route_stations array — one pre-formatted string per stop.
{
"route_stations": [
"01. MMCT Mumbai Central | arr First dep 17:00 | day 1 | no halt | 0 km",
"02. BVI Borivali | arr 17:20 dep 17:22 | day 1 | halt 2 min | 30 km",
"03. ST Surat | arr 19:32 dep 19:35 | day 1 | halt 3 min | 263 km",
"04. BRC Vadodara Jn | arr 21:11 dep 21:16 | day 1 | halt 5 min | 392 km",
"05. KOTA Kota Jn | arr 03:35 dep 03:40 | day 2 | halt 5 min | 925 km",
"06. NDLS New Delhi | arr 08:32 dep Last | day 2 | no halt | 1384 km"
]
}
live_status example
{
"train_number": "12951",
"train_name": "Ndls Tejas Raj",
"live_status": {
"current_station": "GHOLVAD",
"last_event": "Approaching",
"delay_minutes": 8,
"next_station": "Surat",
"source_station": "MUMBAI CENTRAL",
"destination_station": "NEW DELHI",
"journey_date": "25-Apr-2026",
"summary": "Departed from Gholvad at 25-Apr-2026 18:45. Upcoming station is Bordi Road (non-stopping). Next stoppage station is Surat.",
"updated_at": "2026-04-25T13:57:07.232Z"
},
"source_url": "https://www.runningstatus.in/status/12951-today",
"scraped_at": "2026-04-25T13:57:07.232Z"
}
Output field reference
| Field | Type | Description |
|---|---|---|
train_number |
string | IR train number (e.g. 12951). |
train_name |
string | Full train name. |
train_type |
string | Service category: RAJDHANI, SHATABDI, VANDE_BHARAT, DURONTO, GARIB_RATH, SUPERFAST, MAIL_EXPRESS, PASSENGER, etc. |
origin_station / origin_code |
string | Station name and code where the train begins its run. |
destination_station / destination_code |
string | Station name and code where the train ends its run. |
from_station / from_code |
string | User-effective boarding station for train_search. Equals origin for train_number mode. |
to_station / to_code |
string | User-effective alighting station. Equals destination for train_number mode. |
departure_time |
string | Scheduled departure from the boarding station, HH:MM 24h. |
arrival_time |
string | Scheduled arrival at the alighting station. |
duration_minutes |
integer | Total journey duration in minutes. |
distance_km |
number | Distance between boarding and alighting stations in kilometres. |
runs_on |
array of strings | Days the train runs (e.g. ["Mon","Wed","Fri"]). |
classes_available |
array of strings | Seat classes the train carries (1A, 2A, 3A, SL, CC, EC, 2S, FC, GN, GC). |
route_stations |
array of strings | Per-stop schedule lines (train_number mode only). |
fare_by_class |
object | INR fares keyed by class. Empty for trains where erail.in doesn't publish fares. |
seat_availability |
array of strings | Per-class snapshot of available, waitlist, RAC, and tatkal counts (where the source publishes them). |
live_status |
object | Real-time position object (live_status mode only). |
source_url |
string | URL the record was scraped from. |
scraped_at |
string | ISO 8601 timestamp when the record was captured. |
FAQ
How do I scrape Indian Railways data?
The Indian Railways Scraper covers three modes. Pick train_search to list every train between two stations. Pick train_number to get a single train's full route and fares. Pick live_status to track a running train in real time. Inputs and outputs are all in the tables above.
How much does the Indian Railways Scraper cost to run?
The Indian Railways Scraper bills $0.10 per actor start plus $0.001 per record returned — the standard Apify pay-per-event pricing. A typical train_search between two metros returns 30-50 trains for about $0.13. A train_number lookup returns one record for $0.101.
What stations are supported by the Indian Railways Scraper?
The Indian Railways Scraper accepts any of the ~7,300 IR station codes — NDLS (New Delhi), BCT (Mumbai Central), MAS (Chennai Central), HWH (Howrah), SBC (Bengaluru), and the rest of the network. Use the official IR station code (3-5 letters), not the city name.
Does the Indian Railways Scraper need a proxy or India IP?
The Indian Railways Scraper does not need a proxy. The two source sites (erail.in and runningstatus.in) serve traffic globally and don't geofence. The default proxy configuration is useApifyProxy: false, which keeps the run free of proxy bandwidth charges.
Why is pnr_status mode marked "coming soon"?
PNR lookups need to go through IRCTC or indianrail.gov.in, both of which sit behind CAPTCHAs, F5 bot protection, and (in IRCTC's case) a login. v1 of the Indian Railways Scraper handles the 90% of use cases that don't need PNR. v2 will add it once the captcha-solving plumbing is reliable enough to ship.
Can I get fares for every train?
The Indian Railways Scraper returns whatever fares erail.in publishes. Most major Mail/Express, Superfast, Rajdhani, Shatabdi, and Vande Bharat trains have fare data. Suburban locals and unreserved passengers usually don't — the source just doesn't carry it. Empty fare_by_class is honest about that.
Need More Features?
Need PNR status, station departures, or coverage of another rail network? File an issue or get in touch.
Why Use the Indian Railways Scraper?
- Affordable — $0.001 per record, undercutting paid alternatives like RailAPI by an order of magnitude.
- Honest about limits — v1 ships the modes that work reliably and labels the one that doesn't, instead of pretending IRCTC's captcha layer is a solved problem.
- Clean output — flat records with consistent field names across all three modes. Empty fields stay empty; you don't get strings where numbers belong.