gtfs-rt-kit
Typed Python client and toolkit for public-transport realtime data: GTFS-Realtime feeds (vehicle positions, trip updates, service alerts) plus helpers for static GTFS archives.
- Typed models: frozen dataclasses, timezone-aware datetimes, enum names;
mypy --strictclean. - Sync and async clients on httpx with timeouts, exponential backoff and
Retry-After. - Lazy static GTFS loader: only the files you touch are parsed.
- Matching and delays: vehicles to trips and routes, predictions vs. the timetable (overnight trips and DST handled).
- CLI:
gtfs-rt-kit vehicles <url> --route 15 --json.
Documentation: https://maciejziel.github.io/gtfs-rt-kit/
Installation
pip install "gtfs-rt-kit[http]" # with the HTTP clients (httpx)
pip install gtfs-rt-kit # decoding and static GTFS only
Python 3.10-3.13.
Usage
Fetch and decode a feed
from gtfs_rt_kit import GtfsRtClient, RetryPolicy
with GtfsRtClient(timeout=5.0, retry=RetryPolicy(attempts=4)) as client:
feed = client.fetch("https://mkuran.pl/gtfs/warsaw/vehicles.pb")
print(feed.timestamp, len(feed.vehicles))
vehicle = feed.vehicles[0]
print(vehicle.vehicle_id, vehicle.trip_id, vehicle.position, vehicle.timestamp)
Already have the bytes or a file? Use parse_feed(data) or load_feed("vehicles.pb").
Async
import asyncio
from gtfs_rt_kit import AsyncGtfsRtClient
async def main() -> None:
async with AsyncGtfsRtClient() as client:
vehicles, alerts = await asyncio.gather(
client.vehicles("https://mkuran.pl/gtfs/warsaw/vehicles.pb"),
client.alerts("https://mkuran.pl/gtfs/warsaw/alerts.pb"),
)
print(len(vehicles), "vehicles,", len(alerts), "alerts")
asyncio.run(main())
Static GTFS, matching and delays
from gtfs_rt_kit import StaticGtfs, filter_by_route, match_vehicles, trip_delays
gtfs = StaticGtfs("gtfs.zip") # lazy: nothing is parsed yet
matched = match_vehicles(feed, gtfs)
for item in filter_by_route(matched, "15"): # route id or short name
print(item.vehicle.vehicle_id, item.line, item.mode, item.trip and item.trip.headsign)
update = updates_feed.trip_update_for(trip_id)
for stop in trip_delays(update, gtfs):
print(stop.stop_id, stop.scheduled, stop.predicted, stop.delay)
Command line
$ gtfs-rt-kit vehicles https://mkuran.pl/gtfs/warsaw/vehicles.pb --warsaw --route N91
VEHICLE LINE TRIP LAT LON TIMESTAMP
V/N91/187 N91 2026-10-09:N91:PtS:187:2453 52.28374 20.90525 2026-10-09T23:13:02Z
V/N91/188 N91 2026-10-09:N91:PtS:188:2515 52.22932 21.00283 2026-10-09T23:13:04Z
2 vehicle(s), feed time 2026-10-09T23:13:14Z
$ gtfs-rt-kit vehicles https://example.org/vehicle_positions.pb --route 15 --json
$ gtfs-rt-kit trip-updates https://example.org/trip_updates.pb --static gtfs.zip
$ gtfs-rt-kit alerts https://mkuran.pl/gtfs/warsaw/alerts.pb --lang pl --active
Examples
examples/warsaw_live.py: live Warsaw (ZTM) vehicles of a line, matched to the timetable, with alerts.examples/generic_feed.py: summary and most delayed trips of any GTFS-Realtime feed, using the async client.
API overview
| Area | API |
|---|---|
| Decoding | parse_feed, load_feed, Feed, FeedHeader |
| Models | VehiclePosition, TripUpdate, StopTimeUpdate, StopTimeEvent, Alert, TripDescriptor, VehicleDescriptor, Position, TranslatedString, TimeRange, EntitySelector |
HTTP (http extra) |
GtfsRtClient, AsyncGtfsRtClient, RetryPolicy |
| Static GTFS | StaticGtfs, Agency, Stop, Route, Trip, StopTime, parse_gtfs_time |
| Matching | match_vehicles, match_vehicle, filter_by_route, MatchedVehicle, gtfs_rt_kit.warsaw |
| Delays | trip_delays, StopDelay, estimate_vehicle_delay, scheduled_datetime |
| Errors | GtfsRtKitError, FeedDecodeError, FeedFetchError, StaticGtfsError |
See the API reference for details.
Development
uv sync --all-extras # runtime, http extra and dev tools
uv run pytest --cov # tests (no network access needed)
uv run ruff check && uv run ruff format --check
uv run mypy # strict mode
uv sync --all-extras --group docs && uv run mkdocs serve
Test fixtures live in tests/fixtures; regenerate the realtime feeds with
uv run python tests/fixtures/make_fixtures.py.
Releases are published to PyPI from version tags via Trusted Publishing; see RELEASING.md.
License
MIT © 2026 Maciej Zieliński. Third-party components are listed in 3rdparty_licenses.md.
Metadata
Release files for gtfs-rt-kit 0.1.0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| gtfs_rt_kit-0.1.0.tar.gz | 38.5 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| gtfs_rt_kit-0.1.0-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 64.9 kB
Release files / gtfs_rt_kit-0.1.0.tar.gz
| Download URL | gtfs_rt_kit-0.1.0.tar.gz |
|---|---|
| Size | 38.5 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
bc21ef4251f98a01f709dd15f66aa5e91f22dab5f12c6aec44f7cab5213511ae
|
|
BLAKE2b-256 checksum How to use checksums |
2f78d17a34fc63b7e78b49229d7dea8901742d3b8ace55bda548f85bac0edb62
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
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 Oct 10, 2026.
Transparency logRelease files / gtfs_rt_kit-0.1.0-py3-none-any.whl
| Download URL | gtfs_rt_kit-0.1.0-py3-none-any.whl |
|---|---|
| Size | 26.4 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
4a8eb90ef8f9dec02acfbda0aad9f9edaf5012c241324cd8547e220d5fec7350
|
|
BLAKE2b-256 checksum How to use checksums |
b713d8bb9714a04aa360835303cd7451a0e0175b820bffe257a31d2d861699e8
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
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 Oct 10, 2026.
Transparency log