bahn APIbahn.de ↗
Search Deutsche Bahn train stations by name and find connections with live pricing, schedules, transfers, and leg-level stop data via the bahn.de API.
What is the bahn API?
The bahn.de API exposes 2 endpoints covering Deutsche Bahn's station network and train connection search. The autocomplete_station endpoint resolves partial station names into structured records with coordinates and transport product flags, while search_connections returns full journey options between two stations including per-connection pricing, transfer counts, duration in seconds, and individual leg breakdowns with intermediate stops.
curl -X GET 'https://api.parse.bot/scraper/49ba8b8c-c4c8-4861-a1e8-3e46e71c6656/autocomplete_station?limit=5&query=Berlin' \ -H 'X-API-Key: $PARSE_API_KEY'
Typed, relational, agent-ready
A generated client with real types, enums, and the links between objects — the structure a flat JSON response can't carry. Autocompletes in your editor and reads cleanly to coding agents.
- Fully typed · autocompletes
- Objects link to objects
- Typed errors & pagination
Typed Python client. Set up the SDK in your uv project, then pull this API’s typed client:
uv add parse-sdk uv run parse init uv run parse add --marketplace bahn-de-api
uv run parse add --marketplace pulls a pinned snapshot of this canonical API — it won’t change underneath you. To customize it, subscribe and swap to your own copy.
"""Deutsche Bahn train search — find stations and connections with pricing."""
from parse_apis.deutsche_bahn_bahn_de_scraper_api import (
DeutscheBahn, TravelClass, StationNotFound
)
client = DeutscheBahn()
# Search for stations matching a query
for station in client.stations.search(query="München", limit=3):
print(station.name, station.ext_id, station.products)
# Find a specific station for connection search
origin = client.stations.search(query="Berlin Hbf", limit=1).first()
if origin:
print(f"Origin: {origin.name} ({origin.lat}, {origin.lon})")
# Search connections between two cities
for conn in client.connections.search(
origin="Berlin Hbf",
destination="Hamburg Hbf",
date="2026-07-01",
time="09:00",
travel_class=TravelClass.SECOND,
limit=3,
):
print(conn.departure, conn.duration, conn.transfers, conn.total_price.amount, conn.total_price.currency)
for leg in conn.legs:
print(f" {leg.train} ({leg.category}): {leg.from_} → {leg.to}, stops: {leg.planned_stops}")
# Handle station-not-found errors gracefully
try:
results = client.connections.search(
origin="Nonexistent Station XYZ",
destination="Hamburg Hbf",
date="2026-07-01",
time="10:00",
limit=1,
).first()
except StationNotFound as exc:
print(f"Station not found: {exc}")
print("Exercised: stations.search / connections.search / StationNotFound error handling")
Search for train stations or locations by partial or full name. Returns matching stations with their IDs, coordinates, and available transport products (ICE, regional, S-Bahn, etc.). Results are ordered by relevance. Use the returned station name as input to search_connections.
| Param | Type | Description |
|---|---|---|
| limit | integer | Max number of results to return |
| queryrequired | string | Partial or full name of the station (e.g. 'Berlin', 'Hamburg Hbf') |
{
"type": "object",
"fields": {
"data": "array of station objects with id, extId, name, type, lat, lon, and products"
},
"sample": {
"data": {
"data": [
{
"id": "A=1@O=Berlin Hbf@X=13369549@Y=52525589@U=80@L=8011160@p=1780945770@i=U×008065969@",
"lat": 52.524925,
"lon": 13.369629,
"name": "Berlin Hbf",
"type": "ST",
"extId": "8011160",
"products": [
"ICE",
"EC_IC",
"IR",
"REGIONAL",
"SBAHN",
"BUS",
"UBAHN",
"TRAM"
]
}
]
},
"status": "success"
}
}About the bahn API
Station Search
The autocomplete_station endpoint accepts a query string — anything from a partial city name like Berl to a full station name like Hamburg Hbf — and returns an array of matching station objects. Each object includes a numeric id, an extId for external cross-referencing, a human-readable name, a type classification, geographic coordinates (lat, lon), and a products field that lists which transport modes (ICE, S-Bahn, regional rail, bus, etc.) serve that station. An optional limit parameter caps the result count.
Connection Search
The search_connections endpoint takes an origin and destination station name, a date in YYYY-MM-DD format, and a time in HH:MM format, then returns a list of available connections departing at or after that time. Each connection object carries departure and arrival timestamps, a human-readable duration, a durationSeconds integer useful for sorting or filtering programmatically, a transfers count, and a totalPrice field reflecting current DB fare data. The legs array inside each connection breaks the journey into individual segments, each with its own stop sequence.
Coverage and Data Shape
The optional class parameter accepts '1' (first class) or '2' (second class) and affects the totalPrice returned. Station names passed to search_connections follow the same naming conventions as results from autocomplete_station, so the two endpoints compose naturally: resolve an ambiguous name first, then pass the canonical name into the connection search. The API covers DB's domestic network; cross-border international routes may appear where DB operates them directly.
The bahn API is a managed, monitored endpoint for bahn.de — not a raw scraper you maintain. Every endpoint is automatically health-checked on a schedule, and when bahn.de changes and a check fails, the API is automatically queued for repair and re-verified. It is built to keep working as the site underneath it changes.
This isn't an official bahn.de API — it's an independent, maintained REST wrapper over public data. Where the source has no official API (or only a limited one), Parse gives you a stable contract over a source that never promised one, and keeps it current. Need a new endpoint or field? You can revise it yourself in plain English and the agent rebuilds it against the live site in minutes — contributing the change back to the shared API is free.
Will this API break when the source site changes?+
Is this an official API from the source site?+
Can I fix or extend this API myself if I need a new endpoint or field?+
What happens if I call an endpoint that has an issue?+
- Display station autocomplete suggestions in a travel booking UI using name, lat, and lon fields.
- Compare journey options by transfer count and totalPrice to surface the cheapest direct route.
- Build a fare-monitoring tool that polls search_connections daily on a fixed route and tracks totalPrice changes.
- Calculate exact journey durations in seconds using durationSeconds for logistics or scheduling applications.
- Filter connections by class parameter to show first- vs. second-class pricing side by side.
- Geocode Deutsche Bahn stations by extracting lat/lon from autocomplete_station results.
- Identify which transport products (ICE, S-Bahn, regional) serve a given station using the products field.
| Tier | Price | Credits/month | Rate limit |
|---|---|---|---|
| Free | $0/mo | 100 | 5 req/min |
| Hobby | $30/mo | 1,000 | 20 req/min |
| Developer | $100/mo | 5,000 | 100 req/min |
One credit = one API call regardless of which marketplace API you call. Exceeding the rate limit returns a 429 response. Authenticate with the X-API-Key header.