Deutsche Bahn Train Times, Fares & Routes Scraper
Pricing
from $11.54 / 1,000 results
Deutsche Bahn Train Times, Fares & Routes Scraper
Scrape German and European train connections from bahn.de: departure and arrival times, duration, transfers, ICE/IC/RE train types and cheapest fares across 5500+ stations. Export to JSON, CSV or Excel.
Pricing
from $11.54 / 1,000 results
Rating
0.0
(0)
Developer
Scrapers Lat
Maintained by CommunityActor stats
0
Bookmarked
2
Total users
1
Monthly active users
21 hours ago
Last modified
Categories
Share
Deutsche Bahn Train Times, Fares & Routes Scraper
Here is one real result, with every field the actor returns (the fares array is trimmed from 11 entries to 4 here for readability; the actor returns all of them):
{"from": "Berlin Hbf","to": "München Hbf","departure": "2026-08-11T08:36:00","arrival": "2026-08-11T12:46:00","durationMinutes": 250,"transfers": 0,"trainTypes": ["ICE"],"trains": ["ICE 1005"],"price": 103.99,"currency": "EUR","priceClass": "KLASSE_2","departurePlatform": "4","arrivalPlatform": "22","operators": ["DB Fernverkehr AG"],"amenities": ["Bordrestaurant", "ICE Sprinter", "Komfort Check-in verfügbar"],"occupancy": [{ "class": "1st", "level": 1, "text": "Geringe Auslastung erwartet" },{ "class": "2nd", "level": 2, "text": "Mittlere Auslastung erwartet" }],"occupancyFirstClass": "Geringe Auslastung erwartet","occupancySecondClass": "Mittlere Auslastung erwartet","runsOn": "nicht täglich; 10. Aug bis 11. Okt 2026","runsWeekdays": ["MO", "DI", "MI", "DO", "FR", "SA", "SO"],"legs": [{"from": "Berlin Hbf","to": "München Hbf","departure": "2026-08-11T08:36:00","arrival": "2026-08-11T12:46:00","train": "ICE 1005","trainType": "ICE","trainNumber": "1005","direction": "München Hbf","stops": 7,"departurePlatform": "4","arrivalPlatform": "22","operator": "DB Fernverkehr AG","amenities": ["Bordrestaurant", "ICE Sprinter", "Komfort Check-in verfügbar"],"occupancySecondClass": "Mittlere Auslastung erwartet"}],"notices": [],"fromExtId": "8098160","toExtId": "8000261","tripId": "c0a26fd4_3","searchDate": "2026-08-11","fares": [{ "name": "Super Sparpreis", "class": "2nd", "price": 77.99, "currency": "EUR" },{ "name": "Sparpreis", "class": "2nd", "price": 112.99, "currency": "EUR" },{ "name": "Flexpreis", "class": "2nd", "price": 161.1, "currency": "EUR" },{ "name": "Probe BahnCard 25", "class": "2nd", "price": 19.9, "currency": "EUR" }],"cheapestFareName": "Probe BahnCard 25","cheapestFarePrice": 19.9,"observedAt": "2026-08-10T14:18:23.098Z","error": null}
The most complete Deutsche Bahn connection scraper available. It returns every field bahn.de exposes for a train connection (times, duration, transfers, trains, platforms, operators, live occupancy and amenities), adds the full fare breakdown (Flexpreis, Sparpreis, Super Sparpreis and BahnCard offers) with the cheapest fare called out, and gives you route, date, time, class and transfer filters to target exactly the connections you need.
📥 Input · 📤 Output · 💰 Pricing · ▶️ Examples
Table of contents
- What it does
- Quickstart
- Input reference
- Output reference
- Example output record
- Run via API and CLI
- Fetch results
- Billing and limits
- FAQ and troubleshooting
What it does
The actor searches bahn.de for train connections between two stations on a given date and time, then writes one normalized record per connection to the run's dataset. Each record carries departure and arrival times, duration, number of transfers, train types and numbers, platforms, operators, live occupancy per class, on-board amenities, and the day-of-week service pattern. Each connection is broken down into per-leg details in legs.
With withDetails on (the default), each connection is enriched with the full fare breakdown in fares (Flexpreis, Sparpreis, Super Sparpreis and BahnCard offers per class), and the cheapest available fare is surfaced as cheapestFareName and cheapestFarePrice. Missing source values are returned as null, never invented. The search covers Germany and connected European hubs such as Wien Hbf, Zürich HB, and Amsterdam Centraal.
Quickstart
Open the actor, paste this into the input, and press Run. It returns the 10 fastest Berlin to München connections tomorrow morning with full fare details.
{"fromStation": "Berlin Hbf","toStation": "München Hbf","time": "08:00","searchType": "ABFAHRT","travelClass": "KLASSE_2","onlyFastConnections": true,"withDetails": true,"maxConnections": 10}
fromStation and toStation are required. Leave date empty to search tomorrow. bahn.de sells tickets roughly 6 months ahead.
Input reference
| Field | Type | Required | Default | Description | Example |
|---|---|---|---|---|---|
fromStation | string | yes | (none) | Origin station or city. | Berlin Hbf |
toStation | string | yes | (none) | Destination station or city. | München Hbf |
date | string | no | tomorrow | Travel date in YYYY-MM-DD. Defaults to tomorrow when empty. | 2026-09-01 |
time | string | no | 08:00 | Departure or arrival time in 24h HH:MM. | 17:30 |
searchType | enum | no | ABFAHRT | Whether time is the desired departure (ABFAHRT) or arrival (ANKUNFT). | ANKUNFT |
travelClass | enum | no | KLASSE_2 | Travel class: KLASSE_2 (2nd) or KLASSE_1 (1st). Prices returned for the selected class. | KLASSE_1 |
maxTransfers | integer | no | (no limit) | Maximum transfers per connection. | 1 |
onlyFastConnections | boolean | no | true | Return only the fastest connections (bahn.de "fast connections"). | false |
withDetails | boolean | no | true | Enrich each connection with the full fare breakdown and cheapest fare. | false |
maxConnections | integer | no | 10 | Maximum number of connections to collect. | 25 |
Output reference
One dataset item per connection. Types: string, number, integer, boolean, object, array, or null when the source value is absent.
| Field | Type | Description |
|---|---|---|
from | string | Resolved origin station name. |
to | string | Resolved destination station name. |
departure | string | Departure timestamp (local ISO, no zone). |
arrival | string | Arrival timestamp (local ISO, no zone). |
durationMinutes | integer | Total travel time in minutes. |
transfers | integer | Number of transfers on the connection. |
trainTypes | string[] | Train categories used, for example ICE, IC, RE. |
trains | string[] | Train names/numbers used, for example ICE 1005. |
price | number | Headline price for the selected class. |
currency | string | Price currency, usually EUR. |
priceClass | string | Class the price applies to (KLASSE_1/KLASSE_2). |
departurePlatform | string | Platform at the origin, or null. |
arrivalPlatform | string | Platform at the destination, or null. |
operators | string[] | Operating companies, for example DB Fernverkehr AG. |
amenities | string[] | On-board amenities, for example Bordrestaurant. |
occupancy | object[] | Live occupancy per class with class, level, and text. |
occupancyFirstClass | string | 1st class occupancy text, or null. |
occupancySecondClass | string | 2nd class occupancy text, or null. |
runsOn | string | Human-readable service period text. |
runsWeekdays | string[] | Weekday codes the connection runs on (MO..SO). |
fares | object[] | Full fare breakdown (with withDetails): each has name, class, price, currency. |
cheapestFareName | string | Name of the cheapest available fare, or null. |
cheapestFarePrice | number | Price of the cheapest available fare, or null. |
legs | object[] | Per-leg breakdown: stations, times, train, platforms, operator, stops, amenities, occupancy. |
notices | array | Service notices/warnings for the connection. |
fromExtId | string | bahn.de external station ID for the origin. |
toExtId | string | bahn.de external station ID for the destination. |
tripId | string | bahn.de trip identifier for the connection. |
searchDate | string | Date searched (YYYY-MM-DD). |
observedAt | string | ISO 8601 timestamp of when the record was collected. |
error | string | null on success. On a failed run, a single item with a populated error field is written instead. |
Example output record
Real record from a live run (input {"fromStation": "Berlin Hbf", "toStation": "München Hbf", "withDetails": true, "maxConnections": 10}), with fares trimmed to 2 entries for brevity:
{"from": "Berlin Hbf","to": "München Hbf","departure": "2026-08-11T08:36:00","arrival": "2026-08-11T12:46:00","durationMinutes": 250,"transfers": 0,"trainTypes": ["ICE"],"trains": ["ICE 1005"],"price": 103.99,"currency": "EUR","priceClass": "KLASSE_2","departurePlatform": "4","arrivalPlatform": "22","operators": ["DB Fernverkehr AG"],"amenities": ["Bordrestaurant", "ICE Sprinter", "Komfort Check-in verfügbar"],"occupancySecondClass": "Mittlere Auslastung erwartet","runsWeekdays": ["MO", "DI", "MI", "DO", "FR", "SA", "SO"],"fares": [{ "name": "Super Sparpreis", "class": "2nd", "price": 77.99, "currency": "EUR" },{ "name": "Probe BahnCard 25", "class": "2nd", "price": 19.9, "currency": "EUR" }],"cheapestFareName": "Probe BahnCard 25","cheapestFarePrice": 19.9,"tripId": "c0a26fd4_3","searchDate": "2026-08-11","observedAt": "2026-08-10T14:18:23.098Z","error": null}
Run via API and CLI
Start a run and wait for it to finish, then read the dataset. Replace <TOKEN> with your Apify API token.
Run synchronously and get dataset items in one call:
curl -X POST "https://api.apify.com/v2/acts/scrapers_lat~deutsche-bahn-scraper/run-sync-get-dataset-items?token=<TOKEN>" \-H "Content-Type: application/json" \-d '{"fromStation":"Berlin Hbf","toStation":"München Hbf","time":"08:00","withDetails":true,"maxConnections":10}'
Start a run asynchronously:
curl -X POST "https://api.apify.com/v2/acts/scrapers_lat~deutsche-bahn-scraper/runs?token=<TOKEN>" \-H "Content-Type: application/json" \-d '{"fromStation":"Hamburg","toStation":"Amsterdam Centraal","date":"2026-09-01","travelClass":"KLASSE_1"}'
Apify CLI:
apify call scrapers_lat/deutsche-bahn-scraper \--input '{"fromStation":"Köln Hbf","toStation":"Frankfurt(Main)Hbf"}'
Fetch results
Every run writes to a dataset. Fetch items as JSON, CSV, or Excel by changing format:
# JSONcurl "https://api.apify.com/v2/datasets/<DATASET_ID>/items?token=<TOKEN>&clean=true&format=json"# CSVcurl "https://api.apify.com/v2/datasets/<DATASET_ID>/items?token=<TOKEN>&clean=true&format=csv"# Paginate large datasetscurl "https://api.apify.com/v2/datasets/<DATASET_ID>/items?token=<TOKEN>&offset=1000&limit=1000"
<DATASET_ID> is returned as defaultDatasetId in the run object. Use offset and limit to page through large result sets. clean=true drops empty and internal fields.
Billing and limits
- Pay per result. You are charged per connection record returned (
resultevent). See the pricing tab for the current per-result price. - Fare details add-on. When
withDetailsis on and the fare breakdown is fetched, a smalldetailscharge applies per enriched connection. TurnwithDetailsoff to skip it. - No charge on failure. If a run errors or no connections are found, the actor writes a single item with a populated
errorfield and does not charge for it. Empty runs cost nothing. - Spend cap respected. Set
maxTotalChargeUsdon the run; once reached, the actor stops emitting and charging further billable results. - Free Apify plans are capped at 10 connections per run. Upgrade for higher
maxConnections.
FAQ and troubleshooting
A run returned "Station not found". Why?
The station name could not be resolved. Use the bahn.de station spelling, for example Berlin Hbf, München Hbf, or Frankfurt(Main)Hbf.
Why is the price different from what I see on bahn.de?
price is the headline fare for the selected class at search time. Fares change with demand and availability. The full breakdown is in fares, with the lowest surfaced as cheapestFareName / cheapestFarePrice.
Can I search by arrival time instead of departure?
Yes. Set searchType to ANKUNFT and time becomes the desired arrival time.
How far ahead can I search? bahn.de sells tickets roughly 6 months ahead. Dates beyond that return no connections.
Does it cover trains outside Germany? It covers connections that bahn.de sells, including European hubs such as Wien Hbf, Zürich HB, and Amsterdam Centraal.
Is this an official Deutsche Bahn tool? No. This actor is independent and has no affiliation with Deutsche Bahn. It reads only data that is publicly available on bahn.de. Use it in accordance with the source's terms.
Related scrapers
- FlixBus Scraper: Bus routes, times, and fares.
- Ryanair Flights Scraper: Ryanair flight fares and schedules.
- Wizz Air Flights Scraper: Wizz Air flight fares and schedules.
- Booking Hotels Scraper: Hotel availability and prices.
- Open-Meteo Weather Scraper: Weather forecasts by location.
- Eventbrite Scraper: Event listings and details.
More scrapers at scrapers.lat
Built and maintained by scrapers.lat, where we publish scrapers for US and Latin American public platforms: company registries, government data, finance, e-commerce and more. Browse the catalog or request a custom scraper at scrapers.lat.
Independent tool, not affiliated with Deutsche Bahn. Accesses only publicly available bahn.de data. Use in accordance with the source's terms of service.
