OrbTop

Deutsche Bahn Timetable Scraper - Schedules & Real-Time Delays

TRAVELBUSINESSDEVELOPER TOOLS

Deutsche Bahn Timetable Scraper

Scrape journey plans from Deutsche Bahn (bahn.de), the largest rail operator in Europe. Returns ICE, IC/EC, IR, RE, RB, and S-Bahn schedules with platforms, transfers, real-time delays, occupancy forecasts, and segment-level routing across Germany plus international DB routes (AT, CH, FR, NL, BE, PL, DK).


Deutsche Bahn Timetable Scraper Features

  • Pulls journey plans from the bahn.de Reiseauskunft (HAFAS) JSON API.
  • Returns ~5 connections per request and paginates by advancing the search time forward, so you get a continuous list of departures rather than five and a polite shrug.
  • Resolves station names automatically — pass "Berlin Hbf" or an EVA/IBNR code, the scraper handles the lookup.
  • Surfaces real-time delay (departure_time_realtime) when bahn.de has it, alongside the scheduled time.
  • Captures train type (ICE, IC, EC, IR, RE, RB, S, U, Bus), train number, operating carrier (DB Fernverkehr, Flixtrain, ODEG, etc.), and per-segment platforms.
  • Exposes occupancy forecasts for both 1st and 2nd class (0-4 scale) and a flat list of risNotizen advisories like construction work or board-only stops.
  • Supports both 1st and 2nd class fare classes, plus a long-distance-only filter that strips S-Bahn and regional trains.
  • Pure JSON API — no browser, no captcha solving, no fragile selectors.

Who Uses Deutsche Bahn Timetable Data?

  • Travel aggregators — Feed schedules into trip planners or fare comparison front-ends without paying for a commercial HAFAS licence.
  • Mobility researchers — Build datasets of train frequencies, transfer patterns, and on-time performance across the German rail network.
  • Logistics planners — Track route options for time-sensitive freight or business travel, including platform-level detail.
  • Fare comparison tools — Cross-reference DB schedules against Flixtrain, ÖBB, SNCF, and other operators.
  • Travel-tech startups — Prototype itinerary products against a stable API surface before committing to a paid integration.

How Deutsche Bahn Timetable Scraper Works

  1. Provide an origin and destination — station names like "Berlin Hbf" or numeric EVA/IBNR codes both work.
  2. The scraper resolves each station against bahn.de's autocomplete endpoint, then queries the journey API for the requested date and time.
  3. Each batch returns about five connections; the scraper advances the search time and queries again until it hits maxItems or runs out of departures within a 24-hour window.
  4. Records save as flat JSON with all the fields you'd expect, plus a deeplink back to bahn.de for each journey.

Input

{
  "origin": "Berlin Hbf",
  "destination": "München Hbf",
  "date": "",
  "time": "",
  "fareClass": "2",
  "includeLocalTrains": true,
  "maxItems": 50,
  "proxyConfiguration": {
    "useApifyProxy": true,
    "apifyProxyGroups": ["RESIDENTIAL"]
  }
}
Field Type Default Description
origin string "Berlin Hbf" Departure station name (e.g. "Berlin Hbf", "München Hbf") or EVA/IBNR code.
destination string "München Hbf" Arrival station name or EVA/IBNR code.
date string tomorrow Travel date in YYYY-MM-DD format. Empty defaults to tomorrow.
time string "08:00" Departure time in HH:MM (24h). Empty defaults to 08:00.
fareClass string "2" "1" for 1st class, "2" for 2nd class.
includeLocalTrains boolean true Include S-Bahn, RE, RB, U-Bahn, Tram, Bus. Set to false to restrict to ICE/IC/EC/IR.
maxItems integer 50 Maximum journey records to return.
proxyConfiguration object Apify Residential Standard Apify proxy config. Residential is recommended for production runs.

Long-distance only example

{
  "origin": "Hamburg Hbf",
  "destination": "Frankfurt(Main)Hbf",
  "includeLocalTrains": false,
  "fareClass": "1",
  "maxItems": 30
}

EVA code example

{
  "origin": "8011160",
  "destination": "8000261",
  "date": "2026-05-15",
  "time": "07:00",
  "maxItems": 100
}

Deutsche Bahn Timetable Scraper Output Fields

{
  "journey_id": "21d88e04_3",
  "origin_station": "Berlin Hbf",
  "origin_id": "8011160",
  "destination_station": "München Hbf",
  "destination_id": "8000261",
  "departure_time": "2026-04-26T08:36:00",
  "departure_time_realtime": "",
  "arrival_time": "2026-04-26T12:46:00",
  "arrival_time_realtime": "",
  "duration_minutes": 250,
  "transfers": 0,
  "train_segments": [
    "ICE 1005 | Berlin Hbf -> München Hbf | 08:36 -> 12:46 | platforms 4/22 | DB Fernverkehr AG"
  ],
  "platform_departure": "4",
  "platform_arrival": "22",
  "train_type": "ICE",
  "train_number": "1005",
  "train_name": "ICE 1005",
  "carrier": "DB Fernverkehr AG",
  "delay_minutes": null,
  "cancelled": false,
  "occupancy_class_1": 1,
  "occupancy_class_2": 2,
  "ris_notizen": ["Hält nur zum Einsteigen"],
  "bahn_de_url": "https://www.bahn.de/buchung/fahrplan/suche#sts=true&so=Berlin%20Hbf&zo=M%C3%BCnchen%20Hbf&..."
}
Field Type Description
journey_id string Stable trip identifier from bahn.de (tripId).
origin_station string Departure station name.
origin_id string EVA/IBNR code for the origin.
destination_station string Arrival station name.
destination_id string EVA/IBNR code for the destination.
departure_time string Scheduled departure (ISO 8601 local time).
departure_time_realtime string Real-time-adjusted departure when bahn.de has it. Empty otherwise.
arrival_time string Scheduled arrival.
arrival_time_realtime string Real-time-adjusted arrival when available.
duration_minutes number Total scheduled duration in minutes.
transfers number Number of train changes.
train_segments array of string Per-leg formatted lines: train, route, times, platforms, carrier.
platform_departure string Departure platform at the origin.
platform_arrival string Arrival platform at the destination.
train_type string Primary train type — ICE, IC, EC, IR, RE, RB, S, U, Bus.
train_number string Primary train number (e.g. "1005").
train_name string Friendly name (e.g. "ICE 1005").
carrier string Operating carrier — DB Fernverkehr AG, Flixtrain, ODEG, and so on.
delay_minutes number|null Real-time delay in minutes at origin. null when no real-time data is available.
cancelled boolean True if any segment is cancelled.
occupancy_class_1 number 1st-class occupancy forecast (0=unknown, 1=low, 2=medium, 3=high, 4=very high).
occupancy_class_2 number 2nd-class occupancy forecast on the same 0-4 scale.
ris_notizen array of string Real-time advisories (cancellations, platform changes, board-only stops).
bahn_de_url string Direct deeplink into bahn.de for this trip.

FAQ

How do I scrape Deutsche Bahn schedules?

Deutsche Bahn Timetable Scraper hits the bahn.de Reiseauskunft JSON backend directly. You pass an origin, destination, and date — the scraper resolves stations, queries the journey API, and returns clean records. No browser, no captcha solving.

How much does Deutsche Bahn Timetable Scraper cost to run?

The scraper runs on pay-per-event pricing: $0.10 per actor start plus $0.001 per record. A 50-record run lands at about $0.15. Bulk operators can negotiate a custom rate.

What data can I get from bahn.de?

Deutsche Bahn Timetable Scraper returns 24 fields per journey, including station names and EVA codes, scheduled and real-time departure/arrival times, transfers, per-segment train info (type, number, platforms, carrier), occupancy forecasts for both classes, and any active real-time advisories.

Does Deutsche Bahn Timetable Scraper need proxies?

Deutsche Bahn Timetable Scraper works without proxies for small runs but ships with Apify Residential enabled by default. bahn.de sits behind Akamai, which gets uncomfortable around ~5 req/s per IP — proxies prevent that conversation.

Can I get fare data?

Deutsche Bahn Timetable Scraper does not return ticket prices. The bahn.de fare endpoint moved behind authentication in 2026 and is no longer reachable from the public web SPA. The scraper covers schedules, routing, platforms, and real-time data — everything except the price tag.

Does it support international DB routes?

Deutsche Bahn Timetable Scraper supports any journey routable through DB's Reiseauskunft, including international routes to Austria, Switzerland, France, Netherlands, Belgium, Poland, and Denmark. Pass any DB-recognised station name and it works.


Need More Features?

Need station-board mode, fare data, or a different rail operator? File an issue or get in touch.

Why Use Deutsche Bahn Timetable Scraper?

  • Affordable — $0.10/start + $0.001/record. A 1000-journey run is roughly $1.10, which is less than the train fare.
  • First on Apify — There is no other Deutsche Bahn scraper on the store. The commercial HAFAS licence runs into thousands of euros per year, which is a different conversation.
  • Real-time aware — Surfaces delays, cancellations, platform changes, and occupancy directly from the same feed bahn.de's app uses, so the data matches what passengers actually see.