Deutsche Bahn Train Tickets Scraper - Fares & Timetables avatar

Deutsche Bahn Train Tickets Scraper - Fares & Timetables

Pricing

from $2.00 / 1,000 train connections

Go to Apify Store
Deutsche Bahn Train Tickets Scraper - Fares & Timetables

Deutsche Bahn Train Tickets Scraper - Fares & Timetables

Scrape Deutsche Bahn train tickets: connections, ICE and regional timetables, Sparpreis fares, BahnCard prices and delays. $4 per 1,000 connections.

Pricing

from $2.00 / 1,000 train connections

Rating

0.0

(0)

Developer

Muhammad Afzal

Muhammad Afzal

Maintained by Community

Actor stats

0

Bookmarked

4

Total users

2

Monthly active users

11 days ago

Last modified

Security

Limited permissions

Share

Deutsche Bahn Train Tickets Scraper returns Deutsche Bahn train connections between any two DB stations, with departure and arrival times, changes, ICE, IC and regional products, platforms, delays, and current ticket offers such as Super Sparpreis, Sparpreis and Flexpreis in EUR. It is built for travel apps, fare-monitoring dashboards, mobility researchers and AI agents, and costs $4.00 per 1,000 connections on the Apify Free plan plus a $0.005 start fee per run.

The Actor reads Deutsche Bahn's public journey data, handles data access itself, and saves one validated row per connection. It never books, reserves or buys tickets, and it charges only for connections it actually saves.

What Deutsche Bahn train ticket data does it return?

Each dataset row is one connection (one journey option from origin to destination).

FieldWhat it holds
connectionIdStable 20-character ID for deduplication
origin, destination, originId, destinationIdResolved station names and DB station IDs
departureTime, arrivalTimeCurrent departure and arrival, ISO 8601 with offset
plannedDepartureTime, plannedArrivalTimeTimetable times, so you can compute delays
durationMinutes, changes, direct, cancelledJourney summary
price, currency, partialFareLowest fare Deutsche Bahn returned for the journey, or null when none was offered
ticketOffersEach fare's name, price, currency, class, partial-fare flag and conditions
products, operatorsTrain types (ICE, IC, RE, RB, S-Bahn, bus) and operating companies
legsPer-leg stations, times, delay seconds, platforms, line, operator, load factor and notices
remarksService notices for the whole journey
adults, travelClass, bahnCard, searchedOrigin, searchedDestination, searchedAtThe search that produced the row
source, sourceProfile, sourceUrlProvenance

Every run also writes an OUTPUT record in the key-value store. Its outcome is DATA, EMPTY, REJECTED, BLOCKED or FAILED, with delivered and charged counts, resolved stations and warnings, so you can tell a real empty timetable from an access problem.

When should you use it, and when not?

Use it when you need:

  • DB train tickets, fares and timetables for specific routes and dates, for example Berlin Hbf to München Hbf tomorrow at 08:00;
  • German train ticket prices for second or first class, with or without a BahnCard 25, 50 or 100;
  • a fare monitor that checks the same route on a schedule and records Sparpreis changes;
  • structured connections for an AI travel assistant or a comparison page.

Do not use it when:

How do I search Deutsche Bahn connections and fares?

Enter two station names and, optionally, a date and time. Station names such as Berlin Hbf, München Hbf or Frankfurt(Main)Hbf work best; the Actor picks the exact name match, otherwise the first station DB suggests.

  • travelDate is YYYY-MM-DD in Germany time. Leave it empty to search tomorrow, which keeps saved Tasks and schedules evergreen. Words such as "tomorrow" are not accepted; dates in the past or more than 365 days ahead are rejected.
  • travelTime (default 08:00) with searchBy set to departure (leave at or after) or arrival (arrive by).
  • adults (1-5) and adultAge (18-99), travelClass (second or first) and bahnCard (none, bahncard25, bahncard50, bahncard100) shape the fares.
  • directOnly, includeLocalTransport (S-Bahn, U-Bahn, tram, bus and ferry legs) and bike filter the connections.
  • includeTicketOffers (default on) fetches every fare for each connection. Turn it off when the lowest price is enough.
  • maxResults caps the rows, from 1 to 20 (default 5).
{
"origin": "Berlin Hbf",
"destination": "München Hbf",
"travelTime": "08:00",
"searchBy": "departure",
"adults": 1,
"travelClass": "second",
"bahnCard": "bahncard25",
"includeTicketOffers": true,
"maxResults": 5
}

Use it from an AI assistant

Deutsche Bahn Train Tickets Scraper works from Claude, ChatGPT, Cursor or any other MCP client through Apify's MCP server. Add https://mcp.apify.com/?tools=muhammadafzal/deutsche-bahn-train-tickets-connections-scraper as a server, and the assistant can call the Actor as a single tool. Example prompt: "Find the five earliest Deutsche Bahn trains from Hamburg Hbf to Köln Hbf next Friday after 07:00 and list the cheapest second-class fare for each."

How do I run it from code?

JavaScript (apify-client):

import { ApifyClient } from 'apify-client';
const client = new ApifyClient({ token: process.env.APIFY_TOKEN });
const run = await client.actor('muhammadafzal/deutsche-bahn-train-tickets-connections-scraper').call({
origin: 'Berlin Hbf',
destination: 'München Hbf',
travelTime: '08:00',
maxResults: 5,
});
const { items } = await client.dataset(run.defaultDatasetId).listItems();
console.log(items.map((c) => `${c.departureTime} ${c.products.join('/')} ${c.price} ${c.currency}`));

Python (apify-client 3.x):

import os
from apify_client import ApifyClient
client = ApifyClient(os.environ["APIFY_TOKEN"])
run = client.actor("muhammadafzal/deutsche-bahn-train-tickets-connections-scraper").call(
run_input={"origin": "Berlin Hbf", "destination": "München Hbf", "travelTime": "08:00", "maxResults": 5}
)
for item in client.dataset(run.default_dataset_id).iterate_items():
print(item["departureTime"], item["changes"], item["price"], item["currency"])

What does the output look like?

Two connections from a default run (Berlin Hbf to München Hbf, searched 2026-10-26), shortened: legs and the long fare conditions are trimmed.

[
{
"connectionId": "273d7daa274ac4bd318b",
"origin": "Berlin Hbf",
"destination": "München Hbf",
"departureTime": "2026-10-27T08:29:00+01:00",
"arrivalTime": "2026-10-27T13:08:00+01:00",
"durationMinutes": 279,
"changes": 0,
"direct": true,
"cancelled": false,
"price": 107.99,
"currency": "EUR",
"products": ["ICE"],
"operators": ["DB Fernverkehr AG"],
"ticketOffers": [
{ "name": "Super Sparpreis", "price": 107.99, "currency": "EUR", "firstClass": false, "partialFare": false, "conditions": ["Train selection. Cancellation. No City-Ticket"] },
{ "name": "Flexpreis", "price": 178.9, "currency": "EUR", "firstClass": false, "partialFare": false, "conditions": ["Train selection. Cancellation. City-Ticket"] }
],
"legs": [{ "line": "ICE 505", "departurePlatform": "3", "arrivalPlatform": "20", "loadFactor": "high" }],
"travelClass": "second",
"bahnCard": "none",
"source": "Deutsche Bahn"
},
{
"connectionId": "28507d977bc881082540",
"departureTime": "2026-10-27T08:43:00+01:00",
"arrivalTime": "2026-10-27T13:08:00+01:00",
"durationMinutes": 265,
"changes": 1,
"direct": false,
"price": 83.99,
"currency": "EUR",
"products": ["ICE"],
"legs": [
{ "line": "ICE 371", "origin": "Berlin Hbf", "destination": "Erfurt Hbf" },
{ "line": null, "origin": "Erfurt Hbf", "destination": "Erfurt Hbf", "walking": true },
{ "line": "ICE 505", "origin": "Erfurt Hbf", "destination": "München Hbf" }
]
}
]

Pricing: how much does a Deutsche Bahn search cost?

You pay per connection saved, plus a small start fee. Platform usage is included in these prices.

EventFREEBRONZESILVERGOLD
Train connection (primary event, per saved row)$0.004$0.004$0.004$0.002
Actor start (per started GB of allocated memory)$0.005$0.005$0.005$0.005

PLATINUM and DIAMOND plans pay the GOLD price. The default memory is 256 MB, so a normal run pays one start event.

Worked totals on the Free plan:

  • Default run, 5 connections: $0.005 + 5 × $0.004 = $0.025.
  • Maximum run, 20 connections: $0.005 + 20 × $0.004 = $0.085 (GOLD: $0.045).

Rejected inputs, empty searches and blocked runs save no rows and charge no connection events; only the start fee applies. If you set a maximum cost per run, the Actor stops cleanly when it is reached.

How reliable is it, and what are its limits?

  • The default run (Berlin Hbf to München Hbf, 5 connections) finished in about 17 seconds on 2026-10-26 and saved 5 connections with fares.
  • Up to four result pages are read per search, and at most 20 connections are saved per run.
  • Ticket offers are fetched for every returned connection in small parallel batches. If one fare lookup fails, the connection is still saved and a warning goes to OUTPUT.
  • Prices and seats change constantly. Each row is a snapshot at searchedAt; confirm on the official DB site before you travel.
  • The Actor handles data access itself. If Deutsche Bahn refuses every attempt, the run ends BLOCKED with no connection charges.

FAQ

Does it buy or reserve Deutsche Bahn tickets?

No. It only reads public connection and fare data. Booking, seat reservation and payment stay on the official Deutsche Bahn website or app.

How far ahead can I search, and what date is used by default?

Any date from today up to 365 days ahead, in YYYY-MM-DD format. With no date, the Actor searches tomorrow in Germany time, so a saved Task always looks one day ahead.

Can I get BahnCard and first-class prices?

Yes. Set bahnCard to 25, 50 or 100 and travelClass to first or second. The same discount and age apply to every adult in the search.

Why is price empty for some connections?

price is null when Deutsche Bahn returns no fare for that journey. The schedule fields are still filled, and ticketOffers is then usually empty too.

Does it include regional trains, S-Bahn and buses?

Regional and long-distance trains are always searched. includeLocalTransport (on by default) adds S-Bahn, U-Bahn, tram, bus and ferry legs; turn it off for rail-only results.

Are delays and platforms included?

Yes, when Deutsche Bahn publishes them. Compare departureTime with plannedDepartureTime, or read departureDelaySeconds and the platform fields on each leg.

What happens if the route has no trains?

The run ends with outcome: "EMPTY" in OUTPUT, saves no rows and charges no connection events.

Deutsche Bahn data is subject to Deutsche Bahn's terms, database rights and local law. Use it for research and planning at a reasonable volume, get any permission your commercial use requires, and do not present scraped fares as guaranteed or as a booking. This Actor is independent and not affiliated with or endorsed by Deutsche Bahn AG.

Last verified: 2026-10-27