GIS Analyst · Chicago

GIS that makes the overlooked undeniable.

Real maps, real data, real people who needed someone to notice. New ones posted here roughly every week.

← Back to civic work
Civic — Independent Study

The 309 Doesn't Always Leave Elmhurst

A month of Pace's own bus tracker data, checked against Pace's own schedule: which buses never showed up, where, when, and why the wait at my stop was worse than any average suggested.

Aug 30 to Sep 30, 2026 86 Pace routes 123,187 scheduled trips checked
1.06–1.89%Of Pace trips never on the tracker
68%Of confirmed missing trips are on 10 routes
103 of 525Elmhurst 309 departures that never left
34%Missing in the weekday afternoon rush

I catch the Pace 309 at the Elmhurst Metra station. It's the start of the line: every eastbound 309 trip begins there, at 1st Street and York, and heads out along Lake Street to Austin Boulevard. More than once this summer I stood at that stop on a weekday afternoon for over an hour with no bus. At that time of day, Pace's schedule says one should leave every half hour.

I wanted to know whether that was bad luck or a pattern. Pace doesn't publish any record of where its buses actually went, so I started keeping one.

How I got the data

Pace's Bus Tracker website shows live bus positions on a map. Behind that map is a request the page makes to Pace's server, route by route, that returns every bus currently on the route with its location. It needs no login or key. I wrote a small script that makes the same request for all 94 routes on the tracker, every minute or two, and saves the answers.

It ran from August 30 to September 30, 2026, and collected about 2.3 million bus positions from 575 different buses.

Then I compared those positions to Pace's published schedule (the GTFS feed Pace gives to Google Maps and other apps). For every scheduled trip, I checked each of its stops: did any bus on that route come within 500 meters of the stop within 15 minutes of the scheduled time? A trip where at least five stops could be checked, and not one of them was served, counts as a ghost trip: a trip on the schedule that never appeared on Pace's own tracker.

A few things this can and can't do:

  • My computer wasn't watching all the time. The collector went down a few times (a reboot, a sleeping computer). Any stretch it wasn't watching is marked "unknown," not counted as a ghost.
  • The tracker doesn't cover every route. Its route menu lists 94 routes. Another 40 routes that run on weekdays, about 17% of Pace's weekday trips, aren't on it at all, so I can't say anything about them. One more route, the 221 on Wolf Road, appears on the menu but showed just 2 positions all month. I left it out rather than call it a 100% ghost route.
  • "Never appeared on the tracker" is not the same as "never ran." A bus that ran with its tracker switched off looks exactly like a bus that didn't run. I can't tell those apart, and nobody outside Pace can.
  • The test is generous. Any bus on the route counts, in either direction, so a bus going the other way past a stop gives that stop credit. I'll come back to why that matters.

That left 123,187 scheduled trips on 86 routes that I could judge.

The whole system

Between 1.06% and 1.89% of the trips I could check never appeared on the tracker. That's roughly 1 in 94 to 1 in 53. On a typical weekday Pace schedules about 5,450 trips on these routes, and somewhere between 52 and 95 of them didn't show up.

It's a range because some trips are hard to call. When I looked closer at each ghost trip, some had a bus labeled with a different route passing a lot of their stops. Sometimes that's a bus running the trip under the wrong route number on the tracker; sometimes it's just two routes sharing a street. Trips where one such bus covered most of the stops I dropped as explained. The low end counts only trips where no single bus covered more than a fifth of the stops. The high end adds the ones in between, which I can't call either way.

Every Pace route, colored by the share of its scheduled trips that never appeared on Pace's tracker in September (the low end of each route's range, so the colors are conservative). Hover or tap a route for its full range. Dashed gray routes aren't on the tracker, so I couldn't measure them. The dot is the Elmhurst Metra stop.
All 86 measured routes as a table
RouteNameTrips checkedNever appeared
366Park Forest - Chicago Heights1,06910.8% to 26.4%
367University Park - Park Forest73825.5% to 26.1%
357Lincoln Highway1,5357.8% to 13.6%
356Harvey - Homewood - Tinley Park1,4832.1% to 9.2%
542Bluff City1,1713.0% to 9.1%
890Chicago Heights - UPS Hodgkins Limited2323.0% to 9.1%
604Wheeling - Schaumburg1,0058.5% to 8.7%
508East Joliet5504.4% to 8.6%
564Jackson / 14th5340.2% to 7.9%
354Harvey - Oak Forest Loop6343.1% to 7.7%
358Torrence7597.2%
509Joliet-Fairmont7512.5% to 5.7%
471Highland Park-Northbrook Court4130.0% to 5.6%
359Robbins - South Kedzie Avenue1,1135.1% to 5.4%
310West Madison - Hillside8070.1% to 5.2%
35395th/Dan Ryan CTA-Calumet City-Homewood1,7614.9% to 5.1%
803Carpentersville Local8763.1% to 4.8%
801Elgin-Geneva4074.7%
350Sibley3,1754.0% to 4.4%
549South Randall8400.6% to 3.9%
392Green Line Cicero CTA - UPS Hodgkins Limited1582.5% to 3.8%
317Westchester1,3370.0% to 3.4%
39595th/Dan Ryan CTA - UPS Hodgkins Limited4093.2%
314Ridgeland Avenue6281.4% to 2.4%
223Elk Grove - Rosemont CTA Station2,6690.7% to 2.2%
270Milwaukee Avenue7840.0% to 2.2%
541Northeast Elgin1,1920.2% to 2.1%
302Ogden - Stanley6741.5% to 1.9%
472Highland Park - Highwood4151.4% to 1.9%
561Castlecrest via McAree4920.0% to 1.8%
563Great Lakes Naval Station6300.2% to 1.6%
505West Joliet Loop1,0730.3% to 1.6%
319Grand Avenue9101.3% to 1.4%
571Zion1,1481.1% to 1.3%
507Plainfield1,1900.3% to 1.3%
308Medical Center2,0510.1% to 1.2%
208Golf Road1,9240.6% to 1.1%
316Laramie Avenue1,2760.6% to 1.1%
305East Roosevelt1,3820.9% to 1.1%
349South Western3,2301.0% to 1.0%
215Crawford-Howard1,7171.0%
552North State - Spring Hill Mall1,1380.0% to 0.9%
290Touhy Avenue3,3000.7% to 0.8%
543Dundee-Carpentersville7870.1% to 0.8%
606Rosemont - Schaumburg Limited2,5480.2% to 0.8%
524West Aurora5630.4% to 0.7%
384Narragansett - Ridgeland5730.0% to 0.7%
303Forest Park - Rosemont1,1980.0% to 0.7%
332River Road - York Road7610.0% to 0.7%
554Elgin - Woodfield7630.4% to 0.7%
834Joliet - Downers Grove6900.6%
574CLC - Hawthorn Mall5750.5%
559Illinois Route 591,0410.0% to 0.5%
547Wing Park1,0870.0% to 0.5%
548Highland1,0890.0% to 0.5%
379Midway - Orland Park1,5850.3% to 0.4%
272Milwaukee Avenue North9740.4%
301Roosevelt Road1,9770.2% to 0.4%
352Halsted4,5670.3% to 0.4%
572Washington1,1390.0% to 0.3%
570Fox Lake - CLC6260.3%
364159th Street2,8300.3%
100Pulse Milwaukee Line3,7490.2%
330Mannheim - LaGrange Roads2,1250.1% to 0.2%
568Belvidere1,3860.2%
309Lake Street1,1390.0% to 0.2%
331Cumberland - 5th Avenue1,8790.1% to 0.2%
533Northeast Aurora1,2700.2%
307Harlem2,9580.1%
565Grand Avenue1,3890.1% to 0.1%
38195th Street3,5210.1%
250Dempster Street1,0920.0% to 0.1%
313St. Charles Rd.1,2120.0% to 0.1%
383South Cicero2,4080.1%
386South Harlem1,2350.1%
530West Galena - Naperville1,2270.1%
501West Jefferson1,3650.1%
315Austin Boulevard3,4370.1%
322Cermak Road - 22nd St.3,4810.0%
101Pulse Dempster Line3,8880.0%
213Green Bay Road1,8750.0%
311Oak Park Avenue1,6310.0%
318West North Avenue3,2070.0%
390Midway CTA - UPS Hodgkins Limited3140.0%
722Ogden Avenue1,2130.0%
802Aurora - Geneva via Lake Street1,2330.0%

Where: the south suburbs

The missing trips are not spread evenly. The 10 routes with the most confirmed ghost trips account for 68% of them, while running only 11% of the trips.

These are the 10 routes with the highest rates, among routes with at least 100 trips checked:

RouteNameTrips checkedNever appeared
366Park Forest to Chicago Heights1,06911% to 26%
367University Park to Park Forest73826%
357Lincoln Highway1,5358% to 14%
356Harvey, Homewood, Tinley Park1,4832% to 9%
542Bluff City1,1713% to 9%
890Chicago Heights to UPS Hodgkins2323% to 9%
604Wheeling to Schaumburg1,0059%
508East Joliet5504% to 8%
564Jackson / 14th5340% to 8%
354Harvey to Oak Forest6343% to 8%

Six of the ten are in the south suburbs, around Park Forest, Chicago Heights and Harvey. Route 604 in the northwest suburbs stands out because its range is narrow: about 9% either way. On Routes 366 and 367, about one scheduled trip in four never appeared.

I'm deliberately not saying anything here about who lives along these routes. That's worth asking, but it needs Census data, not a guess.

When: late nights and weekends

By time of day, the morning rush is the most reliable: under 1.3% of trips starting between 6 and 9am went missing. After 7pm it climbs, and trips starting around midnight go missing 6 to 7% of the time. Weekends are worse than weekdays, with Saturdays roughly twice the weekday rate.

Why my stop didn't show up in any of this

Here's the part that surprised me. By the whole-trip test, the 309 is one of Pace's most reliable routes: almost none of its trips are ghosts. If I'd stopped there, I'd have concluded my hour-long waits were bad luck.

The problem is the generous test. At rush hour the 309 runs every half hour in both directions. If one trip doesn't run, the buses before and after it, and the buses going the other way, still pass most of its stops within 15 minutes. The trip gets credit for stops it never served. On a busy route, a whole missing trip can look like it ran.

So that system-wide range is a floor. On frequent routes, the real number is probably higher.

To check my own stop properly, I stopped asking "did a bus come near the stop?" and asked the question a rider asks: did an eastbound bus actually leave Elmhurst? Elmhurst is the end of the line, so buses arrive, park for a few minutes and then leave. I counted a departure only when a bus that had been at the station was, within 15 minutes, at least a kilometer and a half away and heading east, and timed it at the moment it left.

Getting that right took a few tries, and two of my early versions were wrong. The first one timed each bus at the moment it arrived rather than when it left. Buses park about 200 meters up York Street before leaving, so a bus that sat there for ten minutes made it look like a 129-minute wait that never happened. I found that by tracing individual buses ping by ping, and only trusted the method once it matched those traces.

What happened at Elmhurst

I paired every scheduled eastbound departure in September with the real departures, one bus per scheduled time, allowing a bus to be up to 5 minutes early and up to 30 minutes late (or until the next scheduled bus, if that's sooner).

103 of 525 scheduled departures never left. That's about one in five. But it depends heavily on the time of day:

WeekdaysScheduled departures checkedNever left
Before 6am215%
Morning rush, 6 to 9am12625%
Midday, 9am to 2pm1004%
Afternoon rush, 2 to 7pm16134%
Evening, after 7pm577%

At midday the 309 runs almost exactly to schedule. At rush hour, when the most people are trying to get home from the train, a quarter to a third of the scheduled buses never leave.

From the platform, that looks like this. Across all of September, the typical wait for the next bus was 4 minutes. But on weekday afternoons between 2 and 6pm, roughly a third or more of the scheduled departures were followed by a wait of over half an hour. On Wednesday, September 2, the 2:57, 3:33, 4:03, 4:33 and 5:03 buses never left. The next bus pulled out at 5:39pm, 2 hours and 42 minutes after the first one that didn't come. That's the kind of afternoon I'd been having.

It's the same trips, over and over. Some scheduled departures were missing on most of the weekdays I could check:

Scheduled departureWeekdays missing
6:31am12 of 21
2:57pm9 of 17
5:03pm9 of 17
3:33pm8 of 18
6:01am8 of 21
4:33pm7 of 17

The 2:57 and the 5:03 are scheduled for the same bus.

The first trip of a bus's day is the one most likely to go missing. Pace's schedule data says which bus is meant to run each trip. When the Elmhurst departure is the first trip of that bus's day, it was missing 45% of the time (17 of 38, a small sample). When it's a later trip, 18%. That points less to buses running late in traffic and more to buses not getting out of the garage on time, or at all. Why that happens (drivers, vehicles, something else) is something only Pace can answer.

I checked the obvious alternative. Nearly every 309 bus also runs Route 313 during the day, switching at the Austin Boulevard end. If the tracker kept showing "313" on a bus that had switched to the 309, my method would have missed it. So I reran everything counting buses of any route label. Not one of the 103 missing departures turned out to have been run by a bus under another label.

What I can't tell you

  • Whether a trip was cancelled or just very late. A bus more than 30 minutes late, or later than the next scheduled one, counts as missing. To someone standing at the stop, those feel the same.
  • Whether a bus ran with its tracker off. I found one bus all month that left Elmhurst and then vanished from the tracker. Counting it or not changes nothing.
  • Anything about the 40 routes the tracker doesn't cover.
  • Whether September was typical. It's one month.

An earlier version

In early September I put up a live page for the Route 309, with a flyer at the stop, using a first version of this method. That version counted hours when my collector was switched off as missed buses, so it overstated the problem. It's still online, marked as out of date, and this page replaces it.