8.3 KiB
Deutsche Bahn / Fahrplan-Datenabruf: Realität & Workarounds (2026-08-08)
Nützlich beim Bau von Reise-/Verbindungs-Websites (z.B. Zugverbindungs-Liste urlaub.perfekt-ohne-en.de), die echte Fahrtzeiten abfragen müssen.
Kernbefund: DB automatisiert NICHT von einem Server aus
Beim Versuch, echte deutsche Nahverkehrs-Verbindungen (RE/RB/S-Bahn) automatisiert zu bekommen, schlugen ALLE Server-seitigen Wege fehl:
| Weg | Ergebnis |
|---|---|
https://www.bahn.de/ im Browserbase-Browser |
❌ Bot-Erkennung: Fehler 753 „Verhalten Ihres Browsers ähnelt dem eines Bots" — auch im echten Browser (stealth-Warnung: „Running WITHOUT residential proxies"). |
DB-Web-API (/web/api/reiseloesung) |
❌ OPS_BLOCKED |
VRR EFA (efa.vrr.de) |
⚠️ Funktionierte für Verbund-Haltestellen (Radevormwald/Remscheid), liefert aber keine Fernziele (Frankfurt/Hannover außerhalb des VRR-Gebiets) — nur lokale Verbunde. |
api.transport.rest / GTFS |
❌ nicht erreichbar (DNS/Timeout) |
| Web-Suche (Firecrawl) | ❌ nicht konfiguriert |
Warum es so ist: bahn.de + DB-API betreiben aktive Anti-Bot-Abwehr, unabhängig davon ob der Zugriff von einem Python-Skript oder einem headless-Browser kommt. Das ist eine bewusste, dauerhafte Serverseite — kein Setup-Fehler, der sich fixen lässt.
Funktionierende Workarounds
-
Regionale EFA (Verbund-API) für lokale Strecken:
https://efa.vrr.de/std3/(JSON viaXSLT_STOPFINDER_REQUEST/XSLT_TRIP_REQUEST2) funktioniert für Haltestellen im jeweiligen Verkehrsverbund. Nur für Nahziele im Verbund nutzen, nicht für Fernziele. -
Nutzer liefert die Zeiten manuell (bewährt): Auf bahn.de / DB-Navigator funktioniert die Suche für menschliche Nutzer einwandfrei. Bei 1-2 Zielen: Nutzer gibt die schnellste Verbindung durch ☞ Master trägt die echten Zeiten ein. Das ist zuverlässig + kostenlos + umgeht die Bot-Sperre.
-
Schätz-/Richtwerte mit ehrlichem Hinweis (Standard-Fall für viele Ziele): Wenn keine echte Verifikation möglich ist, Netzwerk-Takte/Geographie als Richtwert aufführen und auf der Seite + im PDF deutlich markieren: „vor der Fahrt gegen bahn.de/DB-Navigator prüfen". NICHT als echte Fahrzeit ausgeben.
-
DB-Deep-Link pro Verbindung (Nutzer-Idee): statt die Zeiten automatisiert zu verifizieren, einen Link auf die DB-Suche VORBEFÜLLEN, den der Nutzer in seinem Browser öffnet. Da der Nutzer keine Bot-Sperre hat, sieht er dort die echten aktuellen Zeiten.
⚠️ WICHTIG — LIVE-VERIFIZIERT am 2026-08-08 (Muss über den früheren Stand): Die Deutsche Bahn bietet 2026 KEIN stabiles URL-Deep-Link-Format mehr an. Alle vorher als „stabil" geltenden Schemata sind empirisch tot:
- ❌
reiseauskunft.bahn.de/bin/query.exe/dn?...→ toter DNS (DNS_PROBE_FINISHED_NXDOMAIN), Domain existiert nicht mehr. - ❌
reiseauskunft.de/bin/query.exe/...→ toter Pfad („Seite existiert nicht mehr"). - ❌
www.bahn.de/buchung/fahrplan/suche?...mit Query-Parametern → DB-SPA übernimmt die Eingaben NICHT (zeigt nur leere Suchseite). - ❌
www.bahn.de/buchung/fahrplan/suche#query=start:…;destination:…→ undokumentierte interne SPA-Fragmentroute, bricht (Einträge werden nicht übernommen, nur Fehlermeldung → leere Suche).
✅ Funktionierende, ehrliche Lösung 2026-08-08: Ein einfacher, zuverlässiger Link auf die noch erreichbare Sucheseite
https://www.bahn.de/buchung/fahrplan/sucheauf einer Zwischenseite, die Start+Ziel (readonly) anzeigt + einen Button „In DB-Suche öffnen" (neuer Tab) + Fallback-Link. Der Nutzer tippt Start/Ziel dort manuell ein (10 Sekunden) — aber der Link landet garantiert auf einer funktonierenden Seite statt auf einem Deadlink. Verifiziere jede DB-URL mitcurl -s -o /dev/null -w "%{http_code}"VOR dem Einsatz — Sub-Agenten-Reviews können veraltete Formate als „korrekt/getestet" bestätigen, ohne es live geprüft zu haben (passiert hier real). Eine muntere Vorbefüllung ist 2026 nicht mehr zuverlässig möglich; wer sie trotzdem versucht, scheitert an der SPA.⚠️ Die offizielle DB-API (api.deutschebahn.com) wäre die robusteste Quelle für programmatische Zeiten, braucht aber einen API-Key — und ist weiterhin vorbehaltlich Bot/Key-Zugang zu prüfen.
- ❌
Google Maps als ÖPNV-Quelle? NEIN — ICE lässt sich nicht rausfiltern (2026-08-08)
Nutzer-Idee beim Bau einer Verbindungs-Site: „Kann man Google Maps-Öffis-Daten nehmen?" — ehrliche Antwort, die in Zukunft nicht neu hergeleitet werden muss:
- Google Maps zeigt ÖPNV (Bus, S-Bahn, RE, ICE, IC), aber als schnellste Route schlägt es standardmäßig ICE/IC vor.
- Es gibt KEINEN sauberen „nur Regionalverkehr / Deutschlandticket"-Filter in
Google Maps (nur ein grober Transit-Filter).
regional-onlyvon ICE zu trennen ist nicht zuverlässig möglich. - Dieselben GTFS-Fahrpläne wie überall (DB/Verkehrsverbünde) — also nichts Besseres /qchlechteres als reiseauskunft.
- Google Maps blockt zudem Bots (wie die DB), sodass saubere Automatisierung nicht klappt.
- Fazit: Für eine „kein ICE / nur Deutschlandticket“-Anforderung ist unser
DB-Deep-Link zur noch erreichbaren Sucheseite (
https://www.bahn.de/buchung/fahrplan/suche, ohne Vorbefüllung, siehe Abschnitt 4) besser — die Seite hat einen expliziten Deutschlandticket-Filter, den der Nutzer einen Klick entfernt sieht. (Der früher genanntequery.exe/dn-Deep-Link ist tot — siehe Abschnitt 4.)
Label nach ECHTER Fahrtzeit, nicht nach Wunsch-Kategorie (2026-08-08)
Nutzer: „Nicht EINE Fahrt 5-7h in der Liste, ich sehe nur <5h oder >7h." Ursache war zweifach, beides wartbar:
- Label-Mismatch-Bug: 168 Ebene-2-Zeilen waren als
Kernziel (5-7h)markiert, obwohl ihre Fahrtzeiten real 0,3–4h waren. Beim Seeden wird gern „5-7h" als Wunsch-Category an die Fernziele gehängt. Fix: Kategorie aus der echten Fahrtzeit ableiten (Parser~h→ float, dann<5 → unter 5h,5–7 → Kernziel (5-7h),>7 → über 7h), nicht als Design-Wunsch beim INSERT setzen. - Geographische Realität: per reinem Nahverkehr sind echte 5–7h-Ziele selten (viele Großstädte entweder <3h Nahzone oder >8h Fernzone). Das ist kein Bug, sondern Physik — die Seite soll alle Kategorien ehrlich anzeigen und „5-7h" nur dort führen, wo es sie wirklich gibt (ab weiter südlich/östlich gelegenen Städten: Frankfurt→München/Dresden, Hannover→Stuttgart etc.).
Ehrlichkeits-Regel (Nutzer erwartet dies)
- Niemals fabrizierte „fahrhatige" Verbindungen oder konkrete Uhrzeiten als real ausgeben, wenn sie nur geschätzt sind.
- Schätzwerte IMMER als Bereich (
~5-5,5 h) + mit Verweis auf bahn.de labeln.
RAPTOR statt Dijkstra für echte GTFS-Routing (2026-08-19, Team-Unraid)
Für GTFS-Verbindungssuche auf großen Knoten ist einfacher Dijkstra instabil — bei benachbarten Zielen kamen absurde Differenzen (Mainz→Berlin 11h vs. Nachbar Wiesbaden 3h). Standard-Lösung ist RAPTOR (Round-Based Public Transit Optimized Route): erweitert die Reichweite Runde um Runde über echte Trips und behandelt "Zug nehmen → aussteigen → umsteigen" natürlich, statt auf einem statischen Graphen zu kürzen.
- Stop-Mehrdeutigkeit (ein Bahnhof, mehrere stop_ids, nur 1 aktiv in
st) → eindeutig überparent_station/Geo-Mapping auflösen. - Umstiegsbuffer (4 min) + sauberes Ziel-Stop-Matching verhindern die "benachbarte Ziele, extrem abweichende Zeiten"-Inkonsistenz.
- Verifizieren mit Plausibilitäts-Ankern (z.B. Trier→Saarbrücken ~1h, Köln→Aachen ~50min) — nie den Algorithmus blind vertrauen.
- Wenn der Nutzer einen Konkreten echten Wert liefert (z.B. „Trier 6h"), ihn bevorzugt übernehmen statt der Schätzung.
Fakten zur Ziel-Menge (Zugverbindungs-Website, Kontext)
- Schwelle kann variieren (250k → 100k Einwohner → weit mehr Ziele, ~33 in dieser Site).
- Reichweite per reinem Nahverkehr (kein ICE) ab Bergisch-Land/Ruhrgebiet: die meisten Großstädte sind entweder <3h (Nahzone: Köln, Düsseldorf, Ruhrgebiet) oder >8h (Fernzone: Berlin, München). Echte 5–7h-Ziele sind selten — das sind genau die Grenzfälle (Frankfurt ~5h, Wiesbaden ~5,5h, Hannover ~5,5–6,5h, Kassel ~6,5–7h). Regional-Agenten (SwitchHermes/LaptopHermes) lieferten dazu gute Geographie-Analysen.