mitsuhiko

oebb-scotty

@mitsuhiko/oebb-scotty
mitsuhiko
619
37 forks
Updated 1/18/2026
View on GitHub

Austrian rail travel planner (ÖBB Scotty). Use when planning train journeys in Austria, checking departures/arrivals at stations, or looking for service disruptions. Covers ÖBB trains, S-Bahn, regional trains, and connections to neighboring countries.

Installation

$skills install @mitsuhiko/oebb-scotty
Claude Code
Cursor
Copilot
Codex
Antigravity

Details

Pathskills/oebb-scotty/SKILL.md
Branchmain
Scoped Name@mitsuhiko/oebb-scotty

Usage

After installing, this skill will be available to your AI coding assistant.

Verify installation:

skills list

Skill Instructions


name: oebb-scotty description: Austrian rail travel planner (ÖBB Scotty). Use when planning train journeys in Austria, checking departures/arrivals at stations, or looking for service disruptions. Covers ÖBB trains, S-Bahn, regional trains, and connections to neighboring countries.

ÖBB Scotty API

Query Austria's public transport for trip planning, station departures, and service alerts via the HAFAS mgate API.

Quick Reference

MethodPurpose
LocMatchSearch for stations/stops by name
TripSearchPlan a journey between two locations
StationBoardGet departures/arrivals at a station
HimSearchGet service alerts and disruptions

Base URL: https://fahrplan.oebb.at/bin/mgate.exe


Authentication

All requests require these headers in the JSON body:

{
  "id": "1",
  "ver": "1.67",
  "lang": "deu",
  "auth": {"type": "AID", "aid": "OWDL4fE4ixNiPBBm"},
  "client": {"id": "OEBB", "type": "WEB", "name": "webapp", "l": "vs_webapp"},
  "formatted": false,
  "svcReqL": [...]
}

1. Location Search (LocMatch)

Search for stations, stops, addresses, or POIs by name.

Request

curl -s -X POST "https://fahrplan.oebb.at/bin/mgate.exe" \
  -H "Content-Type: application/json" \
  -d '{
    "id":"1","ver":"1.67","lang":"deu",
    "auth":{"type":"AID","aid":"OWDL4fE4ixNiPBBm"},
    "client":{"id":"OEBB","type":"WEB","name":"webapp","l":"vs_webapp"},
    "formatted":false,
    "svcReqL":[{
      "req":{"input":{"field":"S","loc":{"name":"Wien Hbf","type":"ALL"},"maxLoc":10}},
      "meth":"LocMatch"
    }]
  }'

Response Structure

{
  "svcResL": [{
    "res": {
      "match": {
        "locL": [{
          "lid": "A=1@O=Wien Hbf (U)@X=16377950@Y=48184986@U=181@L=1290401@",
          "type": "S",
          "name": "Wien Hbf (U)",
          "extId": "1290401",
          "crd": { "x": 16377950, "y": 48184986 },
          "pCls": 6015
        }]
      }
    }
  }]
}

Location Types

TypeDescription
SStation/Stop
AAddress
PPOI (Point of Interest)

Key Fields

FieldDescription
lidLocation ID string (use in TripSearch)
extIdExternal station ID
nameStation name
crd.x/yCoordinates (x=lon, y=lat, scaled by 10^6)
pClsProduct class bitmask

2. Trip Search (TripSearch)

Plan a journey between two locations.

Request

curl -s -X POST "https://fahrplan.oebb.at/bin/mgate.exe" \
  -H "Content-Type: application/json" \
  -d '{
    "id":"1","ver":"1.67","lang":"deu",
    "auth":{"type":"AID","aid":"OWDL4fE4ixNiPBBm"},
    "client":{"id":"OEBB","type":"WEB","name":"webapp","l":"vs_webapp"},
    "formatted":false,
    "svcReqL":[{
      "req":{
        "depLocL":[{"lid":"A=1@O=Wien Hbf@L=8103000@","type":"S"}],
        "arrLocL":[{"lid":"A=1@O=Salzburg Hbf@L=8100002@","type":"S"}],
        "jnyFltrL":[{"type":"PROD","mode":"INC","value":"1023"}],
        "getPolyline":false,
        "getPasslist":true,
        "outDate":"20260109",
        "outTime":"080000",
        "outFrwd":true,
        "numF":5
      },
      "meth":"TripSearch"
    }]
  }'

Parameters

ParamDescription
depLocLDeparture location(s) - use lid from LocMatch
arrLocLArrival location(s)
outDateDeparture date (YYYYMMDD)
outTimeDeparture time (HHMMSS)
outFrwdtrue = search forward, false = search backward
numFNumber of connections to return
jnyFltrLProduct filter (see below)
getPasslistInclude intermediate stops

Product Filter Values

BitValueProduct
01ICE/RJX (High-speed)
12IC/EC (InterCity)
24NJ (Night trains)
38D/EN (Express)
416REX/R (Regional Express)
532S-Bahn
664Bus
7128Ferry
8256U-Bahn
9512Tram

Use 1023 for all products, or sum specific bits.

Response Structure

{
  "svcResL": [{
    "res": {
      "outConL": [{
        "date": "20260109",
        "dur": "025200",
        "chg": 0,
        "dep": {
          "dTimeS": "075700",
          "dPltfS": {"txt": "8A-B"}
        },
        "arr": {
          "aTimeS": "104900",
          "aPltfS": {"txt": "7"}
        },
        "secL": [{
          "type": "JNY",
          "jny": {
            "prodX": 0,
            "dirTxt": "Salzburg Hbf",
            "stopL": [...]
          }
        }]
      }],
      "common": {
        "locL": [...],
        "prodL": [...]
      }
    }
  }]
}

Key Connection Fields

FieldDescription
durDuration (HHMMSS)
chgNumber of changes
dTimeSScheduled departure
dTimeRReal-time departure (if available)
aTimeSScheduled arrival
aTimeRReal-time arrival (if available)
dPltfS.txtDeparture platform
aPltfS.txtArrival platform
secLJourney sections (legs)
secL[].jny.prodXIndex into common.prodL[] for train name

Understanding prodX (Product Index)

Important: The prodX field in journey sections is an index into the common.prodL[] array, NOT the train name itself. To get the actual train name (e.g., "S7", "RJX 662"), you must look up common.prodL[prodX].name.

Extracting Trip Summaries with jq

The raw TripSearch response is very verbose. Use this jq filter to extract a concise summary with resolved train names:

curl -s -X POST "https://fahrplan.oebb.at/bin/mgate.exe" \
  -H "Content-Type: application/json" \
  -d '{ ... }' | jq '
    .svcResL[0].res as $r |
    $r.common.prodL as $prods |
    [$r.outConL[] | {
      dep: .dep.dTimeS,
      arr: .arr.aTimeS,
      depPlatform: .dep.dPltfS.txt,
      arrPlatform: .arr.aPltfS.txt,
      dur: .dur,
      chg: .chg,
      legs: [.secL[] | select(.type == "JNY") | {
        train: $prods[.jny.prodX].name,
        dir: .jny.dirTxt,
        dep: .dep.dTimeS,
        arr: .arr.aTimeS,
        depPlatform: .dep.dPltfS.txt,
        arrPlatform: .arr.aPltfS.txt
      }]
    }]'

Example output:

[
  {
    "dep": "213900",
    "arr": "221100",
    "depPlatform": "1",
    "arrPlatform": "3A-B",
    "dur": "003200",
    "chg": 0,
    "legs": [{"train": "S 7", "dir": "Flughafen Wien Bahnhof", "dep": "213900", "arr": "221100", ...}]
  }
]

3. Station Board (StationBoard)

Get departures or arrivals at a station.

Request

curl -s -X POST "https://fahrplan.oebb.at/bin/mgate.exe" \
  -H "Content-Type: application/json" \
  -d '{
    "id":"1","ver":"1.67","lang":"deu",
    "auth":{"type":"AID","aid":"OWDL4fE4ixNiPBBm"},
    "client":{"id":"OEBB","type":"WEB","name":"webapp","l":"vs_webapp"},
    "formatted":false,
    "svcReqL":[{
      "req":{
        "stbLoc":{"lid":"A=1@O=Wien Hbf@L=8103000@","type":"S"},
        "date":"20260109",
        "time":"080000",
        "type":"DEP",
        "maxJny":20
      },
      "meth":"StationBoard"
    }]
  }'

Parameters

ParamDescription
stbLocStation location
dateDate (YYYYMMDD)
timeTime (HHMMSS)
typeDEP (departures) or ARR (arrivals)
maxJnyMaximum number of journeys

Response Structure

{
  "svcResL": [{
    "res": {
      "jnyL": [{
        "prodX": 0,
        "dirTxt": "Salzburg Hbf",
        "stbStop": {
          "dTimeS": "080000",
          "dPltfS": {"txt": "8A-B"}
        }
      }],
      "common": {
        "prodL": [{
          "name": "RJX 662",
          "cls": 1,
          "prodCtx": {"catOutL": "Railjet Xpress"}
        }]
      }
    }
  }]
}

4. Service Alerts (HimSearch)

Get current disruptions and service information.

Request

curl -s -X POST "https://fahrplan.oebb.at/bin/mgate.exe" \
  -H "Content-Type: application/json" \
  -d '{
    "id":"1","ver":"1.67","lang":"deu",
    "auth":{"type":"AID","aid":"OWDL4fE4ixNiPBBm"},
    "client":{"id":"OEBB","type":"WEB","name":"webapp","l":"vs_webapp"},
    "formatted":false,
    "svcReqL":[{
      "req":{
        "himFltrL":[{"type":"PROD","mode":"INC","value":"255"}],
        "maxNum":20
      },
      "meth":"HimSearch"
    }]
  }'

Response Structure

{
  "svcResL": [{
    "res": {
      "msgL": [{
        "hid": "HIM_FREETEXT_843858",
        "head": "Verringertes Sitzplatzangebot",
        "text": "Wegen einer technischen Störung...",
        "prio": 0,
        "sDate": "20260108",
        "eDate": "20260108"
      }]
    }
  }]
}

Common Station IDs

StationextId
Wien Hbf8103000
Wien Meidling8100514
Wien Westbahnhof8101003
Salzburg Hbf8100002
Linz Hbf8100013
Graz Hbf8100173
Innsbruck Hbf8100108
Klagenfurt Hbf8100085
St. Pölten Hbf8100008
Wr. Neustadt Hbf8100516

Time Format

  • Dates: YYYYMMDD (e.g., 20260109)
  • Times: HHMMSS (e.g., 080000 = 08:00:00)
  • Duration: HHMMSS (e.g., 025200 = 2h 52m)

Error Handling

Check err field in response:

{
  "err": "OK",           // Success
  "err": "PARSE",        // Invalid request format
  "err": "NO_MATCH",     // No results found
  "errTxt": "..."        // Error details
}

Product Classes (cls values)

clsProduct
1ICE/RJX
2IC/EC
4Night trains
8NJ/EN
16REX/Regional
32S-Bahn
64Bus
128Ferry
256U-Bahn
512Tram
1024On-demand
2048Other