GTFS + GTFS-Realtime Transit Feed Monitor (open-licensed)
Under maintenancePricing
Pay per event
GTFS + GTFS-Realtime Transit Feed Monitor (open-licensed)
Under maintenanceNormalize and monitor open-licensed public-transit feeds. Static GTFS (zipped CSV) to schedule snapshots and diffs; GTFS-Realtime (protobuf) to alerts, vehicle positions and trip updates. Only verifiably open-licensed feeds are decoded; each record carries its source license and attribution.
Pricing
Pay per event
Rating
0.0
(0)
Developer
ByteHaven Studios
Maintained by CommunityActor stats
0
Bookmarked
2
Total users
1
Monthly active users
4 days ago
Last modified
Categories
Share
GTFS + GTFS-Realtime Transit Feed Monitor
Normalize and monitor open-licensed public-transit feeds. Static GTFS (zipped CSV) becomes a schedule snapshot and, in monitoring mode, a schedule diff. GTFS-Realtime (Protocol-Buffers binary) becomes normalized service alerts, vehicle positions, or trip updates. Every record is stamped with its source feed's license and attribution.
This Actor is compliance-first. It decodes and redistributes feed content only for feeds whose license is verifiably open. See the data-source & licensing section below — it is load-bearing, not boilerplate.
Modes
mode | Input feed | Output records |
|---|---|---|
vehicle-positions | GTFS-RT .pb | vehicle id/label, trip, route, lat/lon, bearing, speed, status, stop, timestamp |
service-alerts | GTFS-RT .pb | cause, effect, header/description text, active periods, informed entities |
trip-updates | GTFS-RT .pb | trip, route, per-stop arrival/departure delays + predicted times |
static-diff | GTFS .zip | first run: schedule snapshot (route/stop/trip counts, service window); later runs: added/removed routes/stops/trips vs the previous run |
Input
| Field | Type | Default | Notes |
|---|---|---|---|
feeds | string[] | — (required) | Mobility Database mdb_source_ids (e.g. mdb-1 or 1) or direct GTFS/GTFS-RT URLs |
mode | enum | vehicle-positions | see table above |
openLicensesOnly | boolean | true | compliance filter — keep ON (see below) |
sinceDate | string | "" | monitoring filter (YYYY-MM-DD) |
maxRecordsPerFeed | integer | 0 | 0 = no cap |
requestDelayMs | integer | 500 | polite pacing between feed fetches |
fetchRetries | integer | 2 | extra attempts on transient fetch failures (network / HTTP 408/429/5xx), exponential backoff; permanent 4xx never retried |
retryBaseDelayMs | integer | 500 | retry backoff base; wait doubles each attempt |
proxyConfiguration | object | proxy off | most open feeds are plain public HTTP; enable only if an agency rate-limits by IP |
Mobility Database IDs are resolved against the CC0 catalog CSV automatically; direct URLs skip the catalog.
Output
One dataset item per normalized record, plus these fields on every item:
_feed{ sourceId, url, dataType }_license,_licenseUrl,_attribution— the source feed's license and provider (always propagate these downstream)_mode,_fetchedAt
Feeds skipped by the license filter emit a { _skipped: true, reason: "license-not-open", … } marker
instead of content. Fetch/decode failures emit { _error: true, stage, … } (stage = fetch /
decode / emit — where it broke). A feed reached and decoded but carrying no entities emits an
un-charged { _empty: true, … } marker so an idle feed is recorded rather than silently dropped.
Transient fetch failures are retried with backoff before an _error is emitted (see fetchRetries).
Pricing (pay-per-event)
Charges one record-returned event per normalized record pushed. Skipped/errored feeds are not
charged. Honors the platform per-run charge limit (eventChargeLimitReached) and stops cleanly.
Data source & licensing — READ THIS
This Actor sits on top of the Mobility Database and public agency feeds. The compliance posture is captured in full in ./COMPLIANCE.md. Summary:
- Catalog metadata is CC0. "All metadata generated by MobilityData is licensed under CC0 1.0 Universal." So resolving feed IDs, URLs, provider, and location from the catalog is unrestricted.
- Feed content is each agency's license, and the consumer is responsible. Per the Mobility Database Terms: "Content within the feeds is licensed by their respective data owners" and "API users are solely responsible for ensuring compliance with the licensing requirements for each feed they access." MobilityData grants no rights to the underlying schedules/positions.
- Therefore this Actor filters to verifiably-open feeds only. With
openLicensesOnly = true(the default), a feed is decoded/redistributed only if its catalog license matches a standard open license (CC0 / CC-BY / ODC-BY / public-domain) or it is on the built-in verified-open allowlist (feeds hand-confirmed open out-of-band, e.g. MBTA — the Mobility Database carries no license metadata for real-time feeds). - Reality of the open universe: in the current US catalog, ~85 % of static feeds declare no
license and only ~0.5–0.9 % carry a standard open license. This Actor is intentionally scoped to
the open subset, not "every transit feed." Turning
openLicensesOnlyoff shifts per-feed license compliance onto you. - Attribution: every emitted record carries
_license/_licenseUrl/_attribution. Open licenses (notably CC-BY / ODC-BY and MBTA) require attribution on downstream use — keep these fields.
The GTFS-Realtime format decoder derives from the google/transit spec (Apache-2.0); decoding the
format is unrestricted — the constraint is on the feed data, handled by the license filter above.
Docs
- ./docs/SCOPE.md — what the Actor is and honestly is not (curated open-feed sizing).
- ./docs/PRICING.md — pay-per-event model (concrete price values owner-gated).
- ./docs/LISTING.md — Apify Store copy draft.
- ./COMPLIANCE.md — the load-bearing license gate.
Local development
npm installnpm run smoke # one request to the MBTA open feed; proves license filter + protobuf decodeapify run # full Actor run (needs an input.json / Apify CLI)