Munich Transport
Async Python client for Munich public transport data.
This package is intentionally independent from Home Assistant. A Home Assistant integration can later use it as a thin adapter.
This project is not affiliated with, endorsed by, or sponsored by MVG, MVV, or Stadtwerke München.
Endpoint Source
The endpoint shapes in this package are based on network traffic captured from the official MVG website with Chrome DevTools MCP. External client implementations and the legacy integration are not used as references.
See docs/endpoint-discovery.md for the captured browser calls and docs/home-assistant-request-strategy.md for Home Assistant request sharing and backoff guidance.
Station Schedule Catalog
MunichTransportClient.station_schedules(global_id) returns the station
timetable PDF entries shown on the MVG station page's "Infos" tab. These
entries include MVG line/direction variants and temporary validity text, such
as construction termini.
The station schedule catalog is separate from live departures. Use it for
stable user-selectable line/direction options, and use departures() for
current realtime results. MVG does not expose every operator through this
catalog; for example, S-Bahn lines can appear in lines() and departures()
without appearing in station_schedules().
Direction Grouping
MVG schedule PDF filenames include a schedule code:
U3_H_BP_52.pdf
U3_I_BP_52.pdf
U3_R_BP_51.pdf
U3_S_BP_51.pdf
The library parses this into StationSchedule.schedule_code,
station_abbreviation, stop_number, and direction_key. Temporary variants
are normalized so H and I share direction key H, while R and S share
direction key R.
Use MunichTransportClient.station_direction_groups(global_id) to build
rich user-selectable line/direction groups:
groups = await client.station_direction_groups("de:09162:410")
for group in groups:
print(group.line_label, group.direction_key, group.directions)
For integration config flows, station_direction_options() returns a compact
shape with a stable id and cleaned direction strings. It intentionally does
not format UI text; adapters such as Home Assistant should localize and render
labels themselves.
options = await client.station_direction_options("de:09162:410")
for option in options:
label = f"{option.line_label} -> {' / '.join(option.directions)}"
print(option.id, label)
For Bonner Platz this produces two U3 options:
SUBWAY:U3:H U3 -> Fürstenried West / Sendlinger Tor / Fürstenried West
SUBWAY:U3:R U3 -> Moosach Bf / Implerstraße / Moosach Bf
If the integration already has a station abbreviation from Station.abbreviation,
it can avoid a station metadata request:
options = await client.station_direction_options_by_abbreviation("BP")
schedules = await client.station_schedules_by_abbreviation("BP")
At runtime, fetch live departures and match the stored selector against
Departure.line.label and Departure.direction_key. The raw MVG lineId is
also exposed as Departure.line_id.
selected = options[0]
departures = await client.departures("de:09162:410")
matching = [
departure
for departure in departures
if departure.line.label == selected.line_label
and departure.direction_key == selected.direction_key
]
Development
uv sync
uv run pytest
uv run ruff check .
uv run mypy
Live endpoint smoke test:
uv run python scripts/smoke_mvg.py
Bounded probe for transient response headers:
uv run python scripts/probe_retry_after.py --max-attempts 100 --delay 1.0
Metadata
Release files for munich-transport 0.1.1
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| munich_transport-0.1.1.tar.gz | 87.5 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| munich_transport-0.1.1-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 104.5 kB
Release files / munich_transport-0.1.1.tar.gz
| Download URL | munich_transport-0.1.1.tar.gz |
|---|---|
| Size | 87.5 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
8a6ea2944f20bb2d5abf5a7f67a99a98703dc1decd976bcb1840a02ded292620
|
|
BLAKE2b-256 checksum How to use checksums |
941a3dec4ee8f9510335093aa3125b80a2959adcdff4954557402aadded057a2
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/6.1.0 CPython/3.13.12
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on May 21, 2026.
Transparency logRelease files / munich_transport-0.1.1-py3-none-any.whl
| Download URL | munich_transport-0.1.1-py3-none-any.whl |
|---|---|
| Size | 17.0 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
7fb379c53196e2ac78c4c6cfec703bda5b44cc242331cb5c19c85350caa5d98e
|
|
BLAKE2b-256 checksum How to use checksums |
a488ca8eb6bc681c3c593567e82330ded7ff50e70e08080ab437fcdd27c66329
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/6.1.0 CPython/3.13.12
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on May 21, 2026.
Transparency log