As a transit fan and lover of maps, I’ve always been captivated by the screens in control rooms that show the status of every vehicle in service.
Those maps inspired me to use the real-time data provided by transit agencies to create one of my own. Before long, a simple set of pins on a map spiraled into a comprehensive “bird’s-eye view” of the entire transit system.

Today I’m releasing it as the Puget Sound Transit Operations Tracker. Every in-service vehicle (that actively reports data) will appear on the map for eight area transit agencies, including King County Metro, Sound Transit, and Community Transit. Each vehicle has also been matched to its make and model information, and icons can be filtered by these parameters and more. Check out the full set of features and future plans after the jump.

Icons for each transit vehicle are colored according to the agency that owns it. Pierce Transit buses are green, and Everett Transit buses are dark red. King County Metro has four colors: red for RapidRide coaches, purple for trolleybuses, blue for 60-foot coaches, and green for 40-foot or shorter coaches. Unidentifiable vehicles for all agencies are white. Tapping an icon reveals the full set of known information about the vehicle, including, for some agencies, the trips assigned to the vehicle and the schedule for its current trip.

There’s also an option to switch the icon colors according to schedule status, so on-time buses appear green, early buses appear blue, and late buses appear red. Vehicles with no active trip will appear white with this setting.

Additionally, icons can have a data overlay which shows the route number and vehicle ID. This is off by default because it slows down panning and zooming the map in most browsers.

You can filter the map to display only a certain route; a specific vehicle ID number or series; a make, model, or length of vehicle ; and vehicles running early, on-time, late, or very late. The last filter is “coach anomalies,” which detects certain unusual assignments like a non-RapidRide bus on a RapidRide route, an agency bus serving an ST Express route, the inverse of these, and more. During the snowstorm, combining the length filter with the on-time color theme yielded interesting insights.

The Statistics bar summarizes all the data about vehicles being displayed on the map. This shows information like the number of each model in service, the current on-time performance, and the number of vehicles on each route. It’s worth underscoring that this only looks at vehicles on the map—active filters will alter this, as will changing which agencies are showing.

Looking Forward

Right now, these are the only available statistics. The next major of version of P-Track is going to record or analyze information over time, enabling features such as checking a trip’s on-time performance over recent days and more.

Other features will include viewing the assignment history for each vehicle, which will highlight more kinds of unusual coach assignments, and expanding the information about a vehicle’s current block and trip.

You can check it out for yourself at Have any questions, comments, or other feedback? Let me know in the comments below!

Kona Farry is a student at the University of Washington

60 Replies to “Unveiling the Puget Sound Transit Operations Tracker”

  1. Good timing. Now we can see how well the buses do downtown. I have a feature request (that didn’t take long, did it): It would be nice to filter on more than one bus route. That way, for example, I could see if buses are bunching up on the new bus lanes on 6th, or how buses are getting along on 3rd.

    One weird anomaly: I filtered by route 41, and a bus appeared to on 5th, north of 130th (well off route). The icon disappeared, so I guess it was just a data glitch.

    In any event, this is a really cool map. Thanks.

    1. Virtual particles in the transit world. Buses appear somewhere at ramdom and vanish immediately. Some theories say they’re traveling backward in time.

    2. Thank you!

      I did look into a way to have multiple filters going at once, but found it was complicated enough that I’m punting that down the line.

      You’re right though, would be interesting to see how buses are doing on the downtown pathways, given the recent changes. I can manually make a filter that shows all buses that travel on 2nd-6th. Might do that later today.

  2. This is amazing. Where are you getting the data from? Are you collecting it from the APIs for all the agencies, or from a centralized place (like OneBusAway)?

    I’ve recently been thinking about doing a project for taking real-time data, putting it into a database, and making a machine learning model to find out how much certain things affect its timeliness, such as time of day (how much slower is this bus during rush hour), day of the week (Are buses significantly faster on Friday than on Monday), weather (how much slower is traffic during the rain). Other things I thought about analyzing is common corridor delays (how well can timeliness data for buses already on I-5 predict how late a bus that is about to get on I-5 will be) and passing (how well can I predict whether an A-line bus will pass the previous A-line bus).

    If you’re interested, I’d like to start a conversation with you about if and how we can work on something like this. My email is

  3. OneBusAway already has a feature to show the realtime locations of all the buses on one particular route, but it doesn’t show the advanced data that this app shows, nor does OneBusAway support showing the location for buses assigned to multiple routes at a time.

    Another big improvement over OneBusAway is that is shows real-time information for Community Transit routes, which OneBusAway does not.

    One thing I immediately notice looking at the transit ops app – every bus, across the entire fleet, is shown to be exactly at a location containing a bus stop – even routes which spend considerable time sitting in traffic on the freeway. OneBusAway has the same quirk, and I believe this is a problem with the underlying data feed, which considers each bus to be at the location of the bus stop it most recently passed. This quirk doesn’t matter much for local routes which stop everywhere, but it can cause gross inaccuracies for express routes which travel long distances on the freeways. For example every route 594 trip shows up as still in Tacoma until the bus reaches SODO, at which point, its reported location magically teleports to SODO, and the bus’s status suddenly changes from 30 minutes late to on-time.

    I definitely like the transit ops website. My biggest feature request is to produce a mobile-friendly version, which can used as a replacement for OneBusAway, when traveling in the Community Transit area, where OneBusAway real-time doesn’t work.

    1. That may have been a fluke, I can see a 594 on I-5 near S 272nd St right now. I map anything that’s less than five minutes old, so if a vehicle isn’t showing, then it either hasn’t reported recently or it’s a flaw with how the agency reports their realtime data.

      It’s worth noting that CT’s data feeds are brand new, so it may find itself in OneBusAway soon (I know it just launched in Transit App on Friday).

      The website should be fully responsive for mobile devices! I’ve been using it a lot on my phone. Let me know if you have any issues with it.

    2. …Although, I’m currently seeing some 594s in the Burien/White Center area, so something is definitely off. I pull from the GTFS-RT feeds directly, but I’ll see if I can figure out what’s going on here.

    3. Okay, a little more detail on what’s going on here:

      It appears some 594s and 560s are getting identified as each other. I have absolutely no idea why this is the case, though I’m wondering if it has to do with the service change; this definitely didn’t happen before today.

      I checked the source data, and there’s definitely a problem here. OneBusAway is also confused.

      Because the problem is exists at the data level, there’s not much I can do. I’m going to keep looking into it, see if I can identify something more specific, and try to get ahold of someone that can do something about it. Thanks for spotting this!

      1. I’m also seeing a 566 in downtown Seattle right now, which’s probably a misidentified 594. I wouldn’t be surprised if this’s a problem in Pierce Transit’s trackers?

      2. I’ve noticed that with the 590/592/595 routes downtown this week. I assumed it was a OBA data issue with the schedule changes. (I’m one to check the bus info before leaving work; saves me from being on the odd duck Pierce Transit coaches that have ended up on the 590 recently.)

    4. Maybe what I’m seeing is only King County Metro operated bus. But have definitely noticed from experience that, in the world of OneBusAway, there are almost never any buses in the middle of the 520 bridge. Even when I’m riding a bus across the 520 bridge, the bus location always shows up as either Montlake Station (if I’m going east) or Evergreen Station (if I’m going west), and only when I completely clear the bridge, does the position update to the next stop.

      Similarly, when an eastbound 255 or 545 is on I-5, the position always shows up as Olive/Boren, the last stop before the freeway, causing OneBusAway to believe that the bus is standing still at the bus stop, when it is actually making progress. When the bus reaches Montlake Station, the position updates, often resulting in the status of a bus suddenly changing from 8 minutes late to 2 minutes early.

      Even once in awhile, OneBusAway does show a bus as located between stops, but when that happens, it’s often wrong. My theory is that Metro has some hacks on the server side where if an internal data feed hasn’t responded with an update after a certain amount of time, they’ll generate a “fake” update of a bus position, assuming very naively that it makes progress according to the paper schedule since the last known location. My theory is that, unlike the “real” updates, which are tagged to bus stops, the “fake” updates, use linear interpolation to estimate the position of the bus between the stops. That is, if a bus left stop X 6 minutes ago, and is supposed to take 8 minutes to get from stop X to stop Y (according to the printed schedule), assume the bus is 3/4 of the distance from stop X to stop Y.

      While I haven’t looked at any actual code, I have noticed some strong circumstantial evidence that that’s what’s happening. Repeated observation of the 255, before it left the tunnel, provided many clues.

      When the bus was in the tunnel, the position would appear to advance forward, but if you clicked for details, it would always show up as exactly zero seconds late. It is physically impossible to follow the posted schedule down to the second, which is proof already that there’s some kind of software hack going on where, what’s reported as “real-time” is actually just schedule data. Further supporting evidence for this conclusion is that, when I’m actually on the bus passing through Westlake Station, the so-called real-time position provided to OneBusAway is advancing down Pine St., Bellevue Ave., and onto I-5. Furthermore, when the reported position is doing this, the “fake” bus doesn’t advance following a pattern you would expect from an actual vehicle – it zooms through the stoplights on Pine St. at an impossible pace, the compensates by driving I-5 at 40 mph, even when it’s wide open. Real buses don’t do this – they stop at the lights, and drive slowly through congested areas – then, when they reach the freeeway, they drive the speed limit, if it’s open enough for all the other cars to drive the speed limit. The rate of progress made by the “fake” bus is exactly what you would get by taking the printed schedule and doing linear interpolation between the stops, which I believe to be too much of a coincidence.

      Then, when the real bus actually left the tunnel, and was able to start transmitting its GPS location, the pattern would change. The reported bus on the app would suddenly move back from the middle of I-5 to the bus stop at 9th/Pine, then it would stay there until the (real) bus reaches Montlake, at which point, the app position would jump forward to Montlake. It is at this point, that the reported location can now be trusted to be based on actual location, subject to the caveat that if a bus is reported as being “at” stop #n, it can actually be anywhere between stop #n and stop #n+1, and where it actually is within that range is unavailable. (Occasionally, a bus will switch back to linear interpolation mode, even when it’s not in the downtown tunnel, but it happens sporadically enough that I believe it’s done only as a fallback to non-responsive internal services within the Metro data feed).

      Meanwhile, while all of the above is going on within the data feed servers, the OneBusAway software doesn’t know that, so when the data feed reports the bus being at stop n, OneBusAway believes the bus to literally be at stop n, rather than somewhere between stops n and n + 1. For local buses (which whoever coded this up was probably thinking of), it doesn’t matter. But, for express buses, the result is that a naive OneBusAway user thinks the bus is just sitting at a bus stop, accumulating more and more delay when, in reality, the bus is miles past that stop, moving normally, and will probably arrive at its next stop on time.

      While I was looking mostly at the 255, you can see similar behavior with routes. (It seems to happen on all king county metro-operated routes, but it’s most noticable for routes that use the freeway). Notice with the 41, for example, that there are often buses at Northgate Transit Center (southbound) and 5th/Olive (northbound), which are running 10+ minutes late, even at midnight on an empty freeway, and there are almost never any #41 buses appearing in the middle of I-5.

      Another very suspicious sign is that the position of every bus is always shown to be along the bus’s official route, even when the actual bus is on a temporary reroute.

      A look at the source code inside the Metro servers that spew out the data would shed some light on this. But, it is disappointing that there appear to be some serious “hacks” on the server side, where what’s reported as actual positions of the bus is sometimes just the result of naive algorithms trying to predict the position of the bus, given the actual position at some time several minutes in the past and the (static) official schedule data.

      Ideally, the raw data feed shouldn’t be running any kind of prediction algorithms – it should just be reporting the actual information it knows, and acknowledging what it doesn’t know. It is application software, such as OneBusAway, that should be doing all the prediction work. This distinction is crucial. If the raw data and the prediction algorithm are decoupled, it means that the open source community can write their own prediction algorithm, rather than being tied to a very naive one, for the sake of being quick enough to implement for the software contract to fit within Metro’s tiny IT budget. A smart prediction algorithm, for example, would not use linear interpolation between the scheduled stops. It would likely be using some kind of machine learning model, trained from a whole bunch of data, such as speed limits, historical progress of buses along the route, time of day, highway construction schedules, Mariners/Seahawks schedules, holidays, real-time traffic reports from Waze or WSDOT.

      But, if the so-called “raw data” is being pre-processed on the server side, this becomes much harder to do. At best, the software has the added burden of trying to reverse-engineer the hacks going into the data feed and try to “undo” them. At worst, information is lost, so it’s impossible to “undo” it.

      1. Your description is spot-on for the retired AVL-based system. Whether or not they ported any of the interpolation logic to the GPS system I have no idea. I thought they just polled each bus at some predetermined interval and got the actual location, but clearly that is not the case.

      2. I should also mention that OBA specifically does not do schedule predictions because it does not want to step on the patent of a very litigious company.

  4. Naming your subdomain ptrack caused my adblocker to block your entire webpage! I disabled it, just thought I’d pass it along.

  5. About two years ago, the OneBusAway folks were looking for volunteers to help develop their service and mobile apps. If you’d like to do stuff like this and also put it into lots of people’s hands and in daily use, you might chat with them. (I get that OBA is a bit different than your focus here, just just making a suggestion…)

  6. Very nice – you’ve done a nice job!

    I was disappointed when the early Metro tracker went away. I had been in a focus group for their web-based tracker several years ago. Yours give more information (block and trip info, coach year and type) and it’s great!


  7. Question about icons on snow days. Will icons still remain visible for stuck buses? Also, will the icons on this map follow buses on their snow routes?

    1. This mostly depends on the operator and whether they stop the trip. What I noticed is that icons would show for a short time after getting stuck and then going away. However, the icon should follow the bus wherever it goes!

      1. When the bus is turned off (even park mode with exterior lights still on), the bus radio stops transmitting GPS data, even if the radio is still on. If stuck, and the coach is warm enough or the driver needs to leave the coach, it’s turned off.

    1. *raises hand*

      I had an old working implementation off of the BusView data feed, but of course that no longer works. I have a bunch of scripts to make polylines from GTFS markers, so you could get route lines in there!

  8. How about including the SDOT(?) Waterfront Shuttle. This is the ONLY transit that connects ferries and aquarium with hotels, Seattle Center and King Street/Pioneer Sq. Usually a quick ride despite a variable 20 minute headway (or less). A valuable service that needs encouragement.

    1. I just found the feed for it. Their data is not in a standard format, so I’d have to write some custom code to deal with it, but I think that won’t be too complicated.

      1. It would be a good addition. No one serves the waterfront/ferry area at all. The Shuttle service is reasonably frequent but often not uniform. This shuttle supports potential riders throughout the city since it connects with the metro system at many points – completing trips that are otherwise impossible b transit. The timing is important, due to the frequent but variable arrival times.

        This added visibility would be a good addition to our network.

      2. The shuttle is already trackable using the DoubleMap website or app (Android and iOS).

        The Android app crashes as soon as you select Waterfront Shuttle. It’s an easy fix for the DoubleMap folks, and I’m not sure why they haven’t fixed it yet.

      3. Sure enough, the shuttle data which powers their own map is pretty easy to pull and transform into the format I need it in. It’s always possible they’ll block me from accessing it—I don’t think they ever intended for third-parties to use it, so who knows if they’ll notice or care—but for now, I’ve added them to the map!

  9. Is this classing ST buses as their respective operating agencies? I didn’t see you mention ST’s colors anywhere.

    1. Ok I can see them now…any chance of a colorblind-friendly mode? All the reds look identical to me, for example.

  10. I thought Mercer Island had a route called the 204. I don’t know if it’s a regular Metro route, a DART, or it’s been deleted, but I haven’t seen any Mercer Island bus service show up on the Operations Tracker other than the 550 and 554. Why no route 204 icon?

    1. I believe that one is operated by Hopelink. I’m not sure if their buses have any sort of tracking equipment, but if they do, Hopelink doesn’t share the data with Metro.

    2. No tracking equipment on HopeLink buses also means no real-time info for Trailhead Direct, once the season starts up again. It would be nice if this could get fixed. The cost of fixing it is negligible compared to that of actually running the buses.

  11. This is a cool website. I’ve only played around a bit, but it appears that it shows all buses, even when OBA can’t find the bus and only reports the “scheduled” time in gray.

    Highway tracking doesn’t seem to be working. I saw a 522 “warp” from 85th street to Union/6th, just like on OBA.

    The schedule color coding is the opposite of OBA – OBA uses red for early and blue for late. Though to be honest, red makes more sense as a negative color for delays.

    On Chrome / Windows 7, I found the process for adding on ST or other agencies to be non-intuitive. I was confused that the route filter stopped in the 300s until I randomly hovered the mouse of the layers icon. Perhaps consider line of instructions? I also couldn’t figure out how to show multiple routes at once, for instance if I wanted to see the 31 and 32 at the same time.

    But overall very impressive.

    1. I’ve come to see OBA’s use of red for early and blue for late as perfect. Blue is slow, “you’re going to arrive late to your destination”. Red is urgent, “this bus is going to leave without you”. I’ve had more negative consequences with early buses than late ones!

      Either way though, it’d be handy if this tool and OBA came to a consensus.

      1. I debated this for quite a while. Here’s my thinking on the current state of things:

        -In OneBusAway, you’re trying to catch a bus. If it’s early, that could be a big problem, so it should be in the “danger” color—red.
        -In the tracker, you’re observing the system as a whole. On the system scale, problems are delays, so they should be in the “danger” color.

        It’s discontinuous, but I think appropriate for each context.

  12. Am I crazy, or can you not change the transit service on Desktop mode. I’m only able to get King County Metro.

    1. Hmmmm… I’m not having a problem on my desktop at all. Are you still having an issue?

    2. If you have selected filter by you will need to clear filters on the side before the difference agencies show up, then there’s a layers button on the map.

    1. Thanks for the correction—that information all had to be defined by hand, which, as you can imagine, got quite tedious after a while! It’s been fixed.

    1. I went looking around, and it turns out that shuttle data which powers their own map is pretty easy to pull and transform into the format I need it in. It’s always possible they’ll block me from accessing it, but for now, I’ve added them to the map!

  13. I was initially excited about this but suffers from same problem as Onebusaway. Tracked myself on the 7 and we were on Rainier when it still said at Maynard.

    1. I don’t know what they use there, but with the system TriMet uses the bus ping only goes out every minute or so. It tracks continuously inside the bus, but sending that data out for external processing is a different matter.

      PDXbus gives the time since last ping on its readout, so you have some idea of the margin of error you are working with.

    2. Realtime is messed up today. Had the same problem; while I sat on a bus downtown it showed the bus having reported its location <1 minute ago in West Seattle.

  14. This is great work, thanks!

    It would be great if there were an option for the map to indicate bus stops, like they are shown on google maps. Even better would be to be able to toggle on/off stops for various routes to keep the map clean. For example, tracking the waterfront shuttle is great, but I don’t remember where the stops are.

Comments are closed.