caltrain-api
Caltrain schedules and train positions -- latitude/longitude, milepost from SF 4th & King, and plain-English descriptions ("approaching Redwood City") -- from Caltrain's static GTFS and 511.org real-time data.
Install
pip install caltrain-api
Python 3.11+. Real-time data needs a free 511.org API key; without one, everything works from the published timetable.
Usage
import os
from datetime import date
from caltrain_api import CaltrainAPI, Direction
api = CaltrainAPI(api_key=os.environ.get("CALTRAIN_511_API_KEY")) # None -> schedule only
for train in api.get_active_trains():
p = train.position # best estimate
print(train.number, train.service_type.value, f"mp {p.milepost:.1f}",
p.description, train.delay) # e.g. 124 local mp 30.0 at Palo Alto 0:01:58
train = api.get_train(124)
train.position # ESTIMATED: from real-time predicted times
train.reported_position # REPORTED: raw feed lat/lon (can be minutes stale)
train.scheduled_position # SCHEDULED: where the timetable says it should be
train.next_stop, train.stops, train.alerts
for d in api.get_departures("Palo Alto", direction=Direction.NORTHBOUND, limit=5):
print(d.train.number, d.stop.departure, d.stop.delay)
for j in api.get_schedule("Palo Alto", "San Francisco",
api.schedule.typical_service_date("weekday", date.today())):
print(j.train.number, j.origin_stop.scheduled_departure, j.scheduled_duration)
api.get_stations() # in milepost order, SF first
api.get_alerts()
Every method that takes at= answers for any moment (timezone-aware datetimes); real-time data applies only within 5 minutes of now.
Positions offer three expressions: lat/lon, milepost (miles along the track from SF 4th & King = 0.0, ~76.8 at Gilroy; computed from GTFS geometry, so close to but not identical with Caltrain's official mileposts), and description plus a structured relation (AT, PASSING, APPROACHING, DEPARTED, BETWEEN, WAITING, ARRIVED). Thresholds (0.2 mi "at", 0.5 mi "approaching/departed") are configurable via DescriptionPolicy.
Data handling
- The static GTFS is downloaded on first use, cached in the user cache dir (
~/Library/Caches/caltrain-apion macOS), and re-checked daily or when the feed expires.api.refresh_schedule(force=True)forces it. Offline, the cached copy is used. - Real-time data is fetched lazily, at most every 120 s (511 allows 60 requests/hour; positions only change every few minutes). Empty feeds and failures keep the last good data for up to 10 minutes, then fall back to the schedule. Rate limiting backs off automatically.
CaltrainAPIis thread-safe; share one instance.
See docs/data-findings.md for what the data sources actually provide and how that shaped these choices.
License
MIT
Development
From a clone of https://github.com/jsinnott/caltrain-api:
uv sync --extra dev
.venv/bin/pytest tests/unit # offline, pinned fixtures
CALTRAIN_511_API_KEY=... .venv/bin/pytest -s tests/integration # live; ~2 511 requests
.venv/bin/mypy --strict src
Unit tests use a pinned GTFS feed and a captured 511 response (2026-11-13 11:45 PT) in tests/fixtures/. tools/one-off-*.py are survey/measurement scripts for the live data sources.
Changelog
- 1.0.1 -- Packaging for PyPI: LICENSE file, project URLs, classifiers,
py.typedmarker (type checkers now use the library's annotations), README links that work on PyPI. No code changes. - 1.0.0 -- Stable release: the public API (everything exported from
caltrain_api) is now covered by semantic versioning. No code changes from 0.2.1. - 0.2.1 -- Fix: a train waiting at its origin could be placed miles down the line, because 511 reports its equipment (often finishing a previous run) before departure. Reports no longer constrain estimates before departure, and WAITING/ARRIVED apply only near the origin/destination.
- 0.2.0 --
CaltrainAPI.get_schedule(origin, destination, service_date)returningJourneyobjects (point-to-point timetable);Schedule.typical_service_date("weekday"|"weekend", on_or_after)picks an ordinary non-holiday date. - 0.1.0 -- First working release.
Schedule.load/refresh(download, disk cache, conditional revalidation, offline fallback);SiriRealtimeSource(511 SIRI VehicleMonitoring + ServiceAlerts);CaltrainAPIfacade with lazy polling, empty-feed/failure tolerance, rate-limit backoff, estimated/reported/scheduled positions, delays, alerts,get_departures. - 0.0.1 -- Offline timetable:
Corridor,DescriptionPolicy,Schedule.from_zip.Train.trip_idadded; holiday "M"-prefixed trains parsed to plain numbers. - 0.0.0 -- API stubs for review.
Metadata
Release files for caltrain-api 1.0.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 | Provenance | Actions |
|---|---|---|---|---|
| caltrain_api-1.0.1.tar.gz | 266.6 kB | Without provenance | Details for caltrain_api-1.0.1.tar.gz |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Actions Reset |
|---|---|---|---|---|
| caltrain_api-1.0.1-py3-none-any.whl | Python 3 | none | any | Details for caltrain_api-1.0.1-py3-none-any.whl |
Total release size: 305.7 kB
Release files / caltrain_api-1.0.1.tar.gz
| Download URL | caltrain_api-1.0.1.tar.gz |
|---|---|
| Size | 266.6 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
26633d9ab01f38537b9987480adb33a9becdcf9e5a3d5fe610acf2c76318f40e
|
|
BLAKE2b-256 checksum How to use checksums |
f8be2a5be043fbc4cd1fe5f5eb7e415348670d0eefa7342f7c5e8dbf9bf2427a
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
uv/0.11.17 {"installer":{"name":"uv","version":"0.11.17","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"macOS","version":null,"id":null,"libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}
|
Release files / caltrain_api-1.0.1-py3-none-any.whl
| Download URL | caltrain_api-1.0.1-py3-none-any.whl |
|---|---|
| Size | 39.1 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
a8ead2c5ac415de5712f3e3d6c4d296b838b1c042af33dceff869045c6d1b4bc
|
|
BLAKE2b-256 checksum How to use checksums |
154e1ef440d269ee95075f03f3036d4bf76ce174cebe1f1d4e42ad938e9efff3
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
uv/0.11.17 {"installer":{"name":"uv","version":"0.11.17","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"macOS","version":null,"id":null,"libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}
|
Security for caltrain-api 1.0.1
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.
No provenance found
None of the files in this release were uploaded with provenance metadata.
A note on package security
PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.
To learn more about protecting yourself from malicious actors, visit our package security documentation.