Skip to content
Docs

JSON feeds

The small JSON files the site's own pages draw from. Rebuilt every night; one fetch each.

Three pages on transitlab.nyc load their numbers from JSON files. You can load the same files. They are rebuilt every night, cached for five minutes, and small enough to fetch from a web page.

All three start with updated, the date the file was built (YYYY-MM-DD). Field names may grow; we won’t rename or remove one without notice here.

const zones = await fetch("https://transitlab.nyc/data/slow-zones.json").then((r) => r.json())
console.log(zones.summary.active, "slow zones active")

Subway slow zones, the same numbers as the subway_slow_zones and subway_slow_zones_weekly tables, already summed up.

FieldTypeWhat it is
updateddateWhen the file was built.
dataThroughdateLast weekday of train data in it.
summary.activenumberSlow zones active in the last week of data.
summary.riderHoursPerWeekdaynumberRider-hours lost each weekday, averaged over the last four full weeks.
summary.trainHoursPerWeekdaynumberThe same in train-hours.
weekly[]listOne entry per week since January 2022.
weekly[].weekdateMonday of the week. The first and last weeks are partial.
weekly[].riderHoursnumberRider-hours lost to slow zones that week.
weekly[].trainHoursnumberTrain-hours lost that week.
active[]listUp to 30 active zones, costliest first. Each is a zone, below.
biggest[]listThe 25 costliest zones since 2022.

A zone has:

FieldTypeWhat it is
segmentstringReadable name, e.g. Queensboro Plaza → 60 St tunnel.
routesstringRoutes through it, space-separated, e.g. N W.
start, enddateFirst and last slow weekday.
slowDaysnumberSlow weekdays in the zone.
baselineSnumberUsual seconds for the segment.
extraSnumberMedian extra seconds per train.
extraPctnumberextraS as a percentage of baselineS.
ridersnumberRiders through the segment on a typical weekday.
riderHoursLostnumberTotal rider-hours lost over the zone.
trainHoursLostnumberTotal train-hours lost.

Bus speeds from two sources: the MTA’s monthly figures (history, a month or so late) and our own daily speeds (recent days).

FieldTypeWhat it is
updateddateWhen the file was built.
mtaThroughmonthLatest month the MTA has published (YYYY-MM).
oursThroughdateLatest day of our own speeds.
periods.routeslist of monthsThe three months the route speeds cover.
periods.routesYearAgolist of monthsThe same months a year before.
summary.citywideMphnumberWeekday citywide speed in mtaThrough.
summary.citywideYearAgonumberThe same month a year before.
summary.cbdLocalChangenumberChange in local bus speed inside the congestion zone, 2024 to 2025, in percent.
summary.outsideLocalChangenumberThe same outside the zone.
summary.slowestrouteThe slowest local or Select Bus route.
monthly[]listWeekday speed by month since 2019: month, citywide and one field per borough (Bronx, Brooklyn, Manhattan, Queens, Staten Island).
cbd[]listLocal buses, weekdays 6 am to 8 pm, since 2023: month, inside and outside the congestion zone, in mph.
daily[]listOur citywide speed by day: date, weekday (true or false), mph.
routes[]listEvery route, slowest first. Each is a route, below.

A route has:

FieldTypeWhat it is
routestringMTA route, e.g. M50.
boroughstringBorough.
typestringMTA route type: LCL/LTD, SBS, EXP and so on.
mphnumberWeekday speed over periods.routes.
mphYearAgonumber or nullOver periods.routesYearAgo.
changePctnumber or nullChange from a year before, in percent.
oursnumber or nullOur speed over our last 14 weekdays.

Speeds are miles over hours summed across routes, so busier routes count for more, as in the MTA’s own figures.

Where buses lose time, for the bus lane map. Coordinates are [longitude, latitude], rounded to about a metre and simplified to within 8 m.

FieldTypeWhat it is
updateddateWhen the file was built.
period.start, period.endmonthThe months of MTA data used.
summary.busHoursLostnumberBus-hours lost each weekday, all stretches.
summary.withoutLanenumberOf those, on stretches without a bus lane.
summary.withLanenumberOn stretches with one.
summary.routeMilesWithoutnumberRoute-miles without a bus lane.
summary.routeMilesWithnumberRoute-miles with one.
streets[]listThe 25 streets without bus lanes where buses lose the most time: street, borough, routes, lost (bus-hours a weekday), mph, lane (share covered, 0 to 1), riders, routeMiles.
stretches[]listEvery stretch between two timepoint stops. Short names keep the file small; see below.
lanes[]list of linesNYC DOT bus lanes, each a list of [lon, lat] points.

A stretch has:

FieldWhat it is
rRoute.
a, bTimepoint stops at each end.
mphAverage speed, 7 am to 7 pm.
bestSpeed in the stretch’s fastest hour.
delayMinutes per bus over the best hour’s time.
busesBuses a weekday, 7 am to 7 pm.
lostBus-hours lost a weekday.
perMilelost per mile.
laneShare of the stretch with a bus lane, 0 to 1.
cThe stretch’s path, a list of [lon, lat] points.

The same stretches, with full names and no shapes, are in the bus_lanes table.