Skip to content

brrock/realtimetrains-api

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

1 Commit
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Realtime Trains API

A powerful Bun API for fetching real-time train information from the UK's Realtime Trains service. Get detailed train schedules, unit numbers, stops, operators, and more. Vibecoded lol.

Features

Core Features

  • 🚂 Get train unit numbers and formations
  • 📍 Fetch detailed stop information with real-time updates
  • 🔍 Search by station code or full station name
  • 📅 Query any date (defaults to today)
  • 🎯 Find services by time and destination
  • ⏱️ View scheduled and real-time arrival/departure times
  • 🚫 Optional non-stop passes display
  • 💾 Built-in caching for better performance
  • ⚡ Lazy-loaded station database (2,600+ stations)

Installation

Prerequisites

  • Bun

Setup

# Clone the repository

# Install dependencies
bun install

# Start the development server
bun run dev
# Deploy to vercel
vc --prod

Server runs on http://localhost:3000

API Endpoints

1. /services - List All Services

Get all trains departing from a station at a given time.

Method: POST

Request Body:

{
  "stationCodeOrName": "KGX",
  "date": "2026-01-01",
  "fromTime": "0900"
}

Parameters:

  • stationCodeOrName (required) - Station code (e.g., KGX) or name (e.g., London Kings Cross)
  • date (optional) - Date in YYYY-MM-DD format. Defaults to today
  • fromTime (optional) - Start time in HHMM format (e.g., 0900)

Response:

{
  "stationCode": "KGX",
  "stationName": "London Kings Cross",
  "date": "2026-01-01",
  "count": 5,
  "services": [
    {
      "time": "1003",
      "destination": "Edinburgh",
      "href": "/service/gb-nr:C41110/2026-01-01#allox_id=0"
    }
  ]
}

2. /find - Find Specific Service

Find a service by time and optionally destination.

Method: POST

Request Body:

{
  "stationCodeOrName": "KGX",
  "time": "1003",
  "destinationCodeOrName": "Edinburgh",
  "date": "2026-01-01"
}

Parameters:

  • stationCodeOrName (required) - Origin station
  • time (required) - Departure time in HHMM format
  • destinationCodeOrName (optional) - Destination station code or name
  • date (optional) - Date in YYYY-MM-DD format

Response (without destination):

{
  "stationCode": "KGX",
  "stationName": "London Kings Cross",
  "date": "2026-01-01",
  "time": "1003",
  "count": 1,
  "services": [
    {
      "destination": "Edinburgh",
      "href": "/service/gb-nr:C41110/2026-01-01#allox_id=0"
    }
  ]
}

Response (with destination):

{
  "stationCode": "KGX",
  "stationName": "London Kings Cross",
  "date": "2026-01-01",
  "time": "1003",
  "destination": "Edinburgh",
  "simpleUrl": "https://www.realtimetrains.co.uk/service/gb-nr:C41110/2026-01-01",
  "detailedUrl": "https://www.realtimetrains.co.uk/service/gb-nr:C41110/2026-01-01/detailed"
}

3. /train - Get Unit Numbers

Get the train unit numbers for a specific service.

Method: POST

Request Body:

{
  "stationCodeOrName": "HGS",
  "time": "1850",
  "destinationCodeOrName": "CHX",
  "date": "2025-12-31"
}

Parameters:

  • stationCodeOrName (required) - Origin station
  • time (required) - Departure time in HHMM format
  • destinationCodeOrName (required) - Destination station
  • date (optional) - Date in YYYY-MM-DD format

Response:

{
  "stationCode": "HGS",
  "stationName": "Hastings",
  "date": "2025-12-31",
  "time": "1850",
  "destination": "London Charing Cross",
  "unitNumbers": ["375708", "375909"],
  "urls": {
    "simple": "https://www.realtimetrains.co.uk/service/gb-nr:J31261/2025-12-31",
    "detailed": "https://www.realtimetrains.co.uk/service/gb-nr:J31261/2025-12-31/detailed"
  }
}

4. /detailed - Get Full Train Details

Get comprehensive train information including all stops.

Method: POST

Request Body:

{
  "stationCodeOrName": "HGS",
  "time": "1850",
  "destinationCodeOrName": "CHX",
  "date": "2025-12-31",
  "includeTimes": true,
  "includeNonStops": true
}

Parameters:

  • stationCodeOrName (required) - Origin station
  • time (required) - Departure time in HHMM format
  • destinationCodeOrName (required) - Destination station
  • date (optional) - Date in YYYY-MM-DD format
  • includeTimes (optional, default: true) - Include arrival/departure times
  • includeNonStops (optional, default: false) - Include pass-through locations

Response:

{
  "stationCode": "HGS",
  "stationName": "Hastings",
  "date": "2025-12-31",
  "time": "1850",
  "destination": "London Charing Cross",
  "unitNumbers": ["375708", "375909"],
  "operator": "Southeastern",
  "carriages": 8,
  "stops": [
    {
      "code": "HGS",
      "name": "Hastings",
      "platform": "3",
      "scheduledDeparture": "1850",
      "realtimeDeparture": "1850",
      "isStop": true
    },
    {
      "code": "SLQ",
      "name": "St Leonards Warrior Square",
      "platform": "1",
      "scheduledArrival": "1853",
      "scheduledDeparture": "1853",
      "realtimeArrival": "1852¼",
      "realtimeDeparture": "1853",
      "isStop": true
    },
    {
      "name": "Mountfield Tunnel",
      "scheduledDeparture": "1911",
      "realtimeDeparture": "1913¾",
      "isStop": false
    }
  ],
  "urls": {
    "simple": "https://www.realtimetrains.co.uk/service/gb-nr:J31261/2025-12-31",
    "detailed": "https://www.realtimetrains.co.uk/service/gb-nr:J31261/2025-12-31/detailed"
  }
}

5. /health - Health Check

Check API status.

Method: GET

Response:

{
  "status": "ok"
}

Usage Examples

Using Codes (Fastest)

# Get unit numbers using station codes
curl -X POST http://localhost:3000/train \
  -H "Content-Type: application/json" \
  -d '{
    "stationCodeOrName": "HGS",
    "time": "1850",
    "destinationCodeOrName": "CHX"
  }'

Using Station Names

# Works with full station names too
curl -X POST http://localhost:3000/train \
  -H "Content-Type: application/json" \
  -d '{
    "stationCodeOrName": "Hastings",
    "time": "1850",
    "destinationCodeOrName": "London Charing Cross"
  }'

List All Services from a Station

curl -X POST http://localhost:3000/services \
  -H "Content-Type: application/json" \
  -d '{
    "stationCodeOrName": "KGX",
    "fromTime": "0900"
  }'

Get Detailed Info with Stops

curl -X POST http://localhost:3000/detailed \
  -H "Content-Type: application/json" \
  -d '{
    "stationCodeOrName": "KGX",
    "time": "1003",
    "destinationCodeOrName": "EDB",
    "includeTimes": true,
    "includeNonStops": true
  }'

Query a Specific Date

curl -X POST http://localhost:3000/train \
  -H "Content-Type: application/json" \
  -d '{
    "stationCodeOrName": "KGX",
    "date": "2025-12-31",
    "time": "2030",
    "destinationCodeOrName": "Edinburgh"
  }'

Performance

Caching Strategy

  • Station Data: Loaded once on first request (2,600+ stations)
  • Services: Cached for 5 minutes per date/time combo
  • Deduplication: Multiple concurrent requests for same service reuse single fetch

Response Times

  • Cold Start (first request): ~500ms-2s
  • Warm Cache (subsequent requests): ~100-500ms
  • Detailed Info: ~2-5s (multiple page fetches)

Error Handling

All endpoints return appropriate HTTP status codes:

  • 200 - Success
  • 400 - Bad request (validation error)
  • 500 - Server error

Error Response:

{
  "error": "Unknown station: \"XYZ\""
}

Architecture

API Request
    ↓
Hono Router + Zod Validators
    ↓
Station Code Resolver (lazy-loaded from API)
    ↓
Realtime Trains Scraper
    ↓
Cheerio HTML Parser
    ↓
JSON Response
    ↓
Client

Data Flow

  1. Input Validation - Zod validates request schema
  2. Station Resolution - Convert code/name to station code
  3. Service Lookup - Fetch services from Realtime Trains
  4. Service Matching - Find specific service by time/destination
  5. Detail Extraction - Scrape detailed train info if needed
  6. Response Formatting - Return structured JSON

Limitations

  • ⚠️ Scrapes website (not official API) - subject to HTML changes
  • 🔄 No real-time push updates (polling only)
  • 📊 Historical data not available
  • 🔐 No authentication required or provided
  • 🌍 UK trains only (National Rail network)

Future Improvements

  • WebSocket for live updates
  • Request deduplication across concurrent calls
  • Historical data storage
  • Train tracking by unit number
  • Batch endpoints
  • Analytics dashboard

Contributing

Contributions welcome! Please:

  1. Test your changes
  2. Update README if needed
  3. Follow existing code style
  4. Submit PR with description

Troubleshooting

"Unknown station" Error

  • Verify station code (e.g., KGX not KG)
  • Try full name (e.g., London Kings Cross)

"Failed to fetch" 400 Bad Request

  • Check date format (YYYY-MM-DD)
  • Check time format (HHMM, 24-hour)
  • Verify service exists at that time

Slow First Request

  • Normal - station data loads on first use
  • Subsequent requests are cached

Empty Services List

  • No trains at that time/date combination
  • Try removing fromTime to see all services

License

MIT License - feel free to use for personal/commercial projects

Disclaimer

This API is unofficial and not affiliated with National Rail or Realtime Trains. Use at your own risk. Web scraping may violate terms of service.


About

API for realtimetrains

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors