Skip to main content

gtfs-rt-kit

CI Docs PyPI Python versions License: MIT Checked with mypy Ruff

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 --strict clean.
  • 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

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)

Source distribution for gtfs-rt-kit 0.1.0
File Size Uploaded
gtfs_rt_kit-0.1.0.tar.gz 38.5 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for gtfs-rt-kit 0.1.0
File Interpreter ABI Platform
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 log

Release 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

Release history Release notifications | RSS feed

This release

0.1.0 This release

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page