aiacademy-kg/bishkek-transport
Bishkek Public Transport Open, continuously-growing data on the public-transport network of Bishkek, the capital of the Kyrgyz Republic. The data originates from the Bishkek mayoralty's public-transport monitoring system (the same feed behind the city's official live transit map and its "My City" mobile service). Only publicly visible transit information is included: stop locations and the live positions of buses, trolleybuses/electric buses, and marshrutkas (shared minibuses).… See the full description on the dataset page: https://huggingface.co/datasets/aiacademy-kg/bishkek-transport.
Bishkek Public Transport
Open, continuously-growing data on the public-transport network of Bishkek, the capital of the Kyrgyz Republic. The data originates from the Bishkek mayoralty's public-transport monitoring system (the same feed behind the city's official live transit map and its "My City" mobile service). Only publicly visible transit information is included: stop locations and the live positions of buses, trolleybuses/electric buses, and marshrutkas (shared minibuses).
The dataset is longitudinal and ongoing. Vehicle positions have been recorded continuously since 2026-07-24 (UTC) and are appended daily, so the tracking subset grows every day. This makes it, to our knowledge, the first openly available historical record of transit movement for Bishkek — the source system exposes only the current snapshot and keeps no public history.
It also includes a second, non-renewable body of data: a one-off raw telematics export obtained directly from the operator, covering ten bus routes in September 2025. Unlike the public feed, it carries device-reported speed and un-processed GPS, which makes it the only available ground truth against which methods built on the feed can be validated. No further such export is expected.
Intended use: academic and research purposes. This dataset is published to support transport research, urban mobility analysis, and machine-learning work for a data-scarce Central Asian city. See Research directions below.
The two data families
Everything here comes from the same municipal system, but through two very different doors — and the difference decides what each is good for.
Both are historical records; the distinction is public feed versus operator telematics, not "current" versus "old". The two do not overlap in time, so they cannot be paired directly — but 135 vehicle plates occur in both, which lets you follow the same physical vehicles across the two periods.
Subsets
The public feed
Scraped from the mayoralty's live transit map. Ongoing.
stops — the stop inventory
A near-complete inventory of physical stopping points in the Bishkek network: 1,501 stops with bilingual names and coordinates.
Coverage spans the city and its immediate suburbs (roughly lat 42.69–43.12, lng 74.41–74.71). Names are complete in Russian and Kyrgyz; English names are almost entirely absent. As a sanity check, stop positions agree closely with independent OpenStreetMap bus-stop data (median distance to the nearest OSM stop ≈ 19 m), while this inventory is substantially more complete than OSM for Bishkek.
tracking — live vehicle positions (appended daily)
A time series of vehicle-position observations, sampled from the live feed roughly every 5 seconds and appended to the dataset every day.
Typical daytime coverage is on the order of ~700 vehicles online; at night trolleybuses and marshrutkas stop running, so only buses appear.
Peak service is ~850 moving vehicles between 08:00 and 10:00 local time, falling to 5–15 overnight.
`lat`/`lng` here are not raw GPS. The upstream platform places every position on the route polyline before publishing it. Taking three consecutive fixes of one vehicle and measuring how far the middle one sits off the chord between the outer two gives a median offset of 8.6 × 10⁻¹⁰ m — zero to floating-point precision. The positions are already map-matched; the geometric noise you would expect from GPS has been removed upstream. See Data caveats for what this means in practice.
The operator telematics (2025)
Six tables from a single export out of the operator's Traccar database, covering 10 bus routes (5, 35, 36, 48, 49, 52, 56, 100, 105, 243) over 2025-09-01 → 2025-09-19. Field names and values are in English; the source column names were Russian.
telematics — raw device fixes
8,793,453 fixes from 197 reporting devices.
telematics_devices — tracker registry
209 rows, one per registered device; device_id, plate and the source registry id are mutually one-to-one.
telematics_routes — route versions
11 rows for the 10 routes: route 5 exists in two versions under different operators.
telematics_route_shapes — route geometry, long form
18,925 vertices. This is the official route alignment for September 2025 and is the natural linear reference for segment-based work.
telematics_route_stops — stops served, in order
1,004 links. 973 of the 1,004 `stop_id` values (96.9%) resolve against the `stops` subset, so this connects the operator's route definitions to the public stop inventory.
telematics_waybills — dispatch sheets
20,013 waybills covering 74 route labels city-wide — far beyond the ten tracked routes — for the same 19 days. This is planned dispatch, so it supports comparing plan against what the vehicles actually did.
(plate, date) is very nearly unique: 19,841 pairs, of which only 79 carry two waybills. Joining waybills onto telematics will therefore duplicate a small number of fixes — filter or aggregate deliberately.
De-identification
The waybills as received named the drivers. The published tables do not.
- `driver1`, `driver2`, `phone_number1`, `phone_number2` were dropped and are not present in any file.
- In their place,
driver_refandrelief_driver_refcarry a random surrogate per person (2,235 distinct), so shift-level and driver-level analysis remains possible. The name → surrogate map was generated from an unseeded permutation and discarded; it is neither reversible nor reproducible, so the surrogates in this release cannot be regenerated or matched against any other build. - Device IMEIs were dropped. Teltonika devices authenticate to the platform by IMEI, so publishing the live fleet's identifiers would invite position spoofing. The field carries no research value.
- Vehicle plates are kept. The
trackingsubset already publishes plates from the public feed, and they are the only bridge between the two periods.
Residual risk worth stating plainly: a vehicle plate plus a date, combined with an internal roster nobody outside the operator holds, could still point back to a person. Nothing in this dataset provides that roster.
Usage
from datasets import load_dataset
REPO = "aiacademy-kg/bishkek-transport"
# --- the public feed ---
stops = load_dataset(REPO, "stops", split="train") # 1,501 stops
tracking = load_dataset(REPO, "tracking", split="train") # live positions, appended daily
# --- the 2025 operator telematics (ground truth) ---
fixes = load_dataset(REPO, "telematics", split="train") # 8.79M raw fixes
devices = load_dataset(REPO, "telematics_devices", split="train")
routes = load_dataset(REPO, "telematics_routes", split="train")
shapes = load_dataset(REPO, "telematics_route_shapes", split="train")
rstops = load_dataset(REPO, "telematics_route_stops", split="train")
waybills = load_dataset(REPO, "telematics_waybills", split="train")The telematics* tables are small enough to query directly without downloading the whole subset:
import duckdb
duckdb.sql("""
SELECT route, direction, stop_seq, stop_id
FROM 'hf://datasets/aiacademy-kg/bishkek-transport/telematics/route_stops.parquet'
WHERE NOT deleted AND NOT is_repeat AND route = 48
ORDER BY direction, stop_seq
""")Coordinates are WGS84 decimal degrees and can be used directly with GeoPandas, folium, kepler.gl, or any GIS tool.
Joining the pieces. telematics.device_id → telematics_devices.device_id for plate and route; telematics_routes.route_ref → telematics_route_shapes and telematics_route_stops for geometry and stop order (not on route, see caveats); telematics_route_stops.stop_id → stops.id for stop names and coordinates; telematics_waybills on (plate, date) for the planned side; and telematics_devices.plate → tracking.gov_number to follow the same vehicles into the 2026 feed.
Why this dataset matters for Bishkek
Bishkek faces the mobility problems common to fast-growing cities — congestion, irregular headways, and winter air quality worsened by idling traffic — but, unlike cities in high-income countries, it has no open, historical transit data to study them with. Planning decisions are hard to evaluate without a baseline of how the network actually behaves over time.
This dataset provides that baseline. Because it is longitudinal and reproducible, it enables evidence-based questions that were previously unanswerable locally: where and when the network slows down, how reliable service is, and how weather and the calendar reshape demand and travel time. Most public transit-ML benchmarks come from a handful of wealthy cities; an open Central Asian record is a genuine scientific contribution — a testbed for methods under real-world constraints (sparse sampling, noisy telemetry, no passenger counts) that rarely appear in curated Western datasets.
What is measurable, and what is not
This deserves its own section, because the obvious first move on this data is the wrong one.
Instantaneous speed cannot be recovered from the feed by differencing positions. Not because of noise, but because the platform emits a new position on a combined trigger — roughly every 10–20 s of movement, hard-capped at about 110 m of travel — so the sampling process itself depends on the speed being measured. Averaging over a longer window makes the result smooth, not correct.
The limit is not an artefact of the feed's processing, either. On the telematics subset, where raw 7-decimal fixes arrive every ~10 s and the device reports its own Doppler speed, position-differenced speed still disagrees with the reported speed: Pearson r = 0.834, median absolute error 4.8 km/h, p90 14.3 km/h. Doppler speed is information that was never present in the position sequence, and no amount of aggregation puts it there.
What is measurable is the time at which a vehicle crossed a fixed point. Because feed positions are snapped to the route polyline, place is known almost exactly and all the uncertainty sits in time. Interpolating between the two fixes that bracket a chosen point along the route gives a crossing time, and every useful quantity is a difference of crossing times:
This was validated against the ground truth rather than assumed. Taking raw telematics tracks, degrading them into what the public feed would have recorded (telemetry upload lag, 5 s polling, duplicate collapsing) and re-measuring travel time over a 700 m segment across 731 vehicle passes gives:
So the degradation costs almost nothing — for this quantity. The same experiment sets the design rule. An RMSE of 3.67 s on a difference of two crossings implies roughly 2.6 s of uncertainty per crossing, so the relative error on a segment is set by how long the segment takes to traverse: about 4 % for 500 m at 20 km/h, under 2 % for 500 m in congestion, but ~10 % for a 200 m segment at 20 km/h. Hence segments of ~500 m or longer; inter-stop spacing in Bishkek is comfortably above that.
Two honest limits on that figure: the simulation reproduced the upload lag, the 5 s polling and the duplicate collapsing, but not the platform's polyline snapping (which should only reduce noise further), and it was measured on one straight 700 m segment of one route. Expect worse on segments containing turns or stops.
If you report speed, derive it from a segment travel time and say over what distance. Do not report a pointwise derivative.
Research directions
The data is rich enough for a range of studies. What follows is a map of what is achievable, with the methods each task calls for.
1. Congestion mapping & a mesoscale network model
Segment each route into links between consecutive stops and accumulate the distribution of link travel times by time-of-day and day-of-week. The result is a speed/reliability map of the city and a mesoscale model answering "how long to get from A to B right now" and "where is time systematically lost". Methods: robust travel-time estimation from crossing times; kernel density / hot-spot analysis. Note: classical GPS map-matching (e.g. the Newson–Krumm HMM) is largely unnecessary on the tracking subset — the platform has already snapped positions to the route line. It is appropriate on telematics, whose fixes are raw. For either subset, telematics_route_shapes supplies the official 2025 alignment to match against; note that alignments changed between 2025 and 2026, so it describes the 2025 tracks, not today's network.
2. Arrival-time prediction (ETA)
Predict when the next vehicle reaches a given stop. Frame this as predicting a crossing time, not a speed to be integrated — see What is measurable. Methods, in increasing complexity: historical-average baselines; a Kalman filter over link travel times (online, uncertainty-aware); gradient boosting (e.g. LightGBM) with features such as recent upstream link travel times, headway to the leading vehicle, time-of-day, weather, and the age of the last fix; quantile regression to report a range ("4–9 min") rather than a false-precise point. The telematics subset gives a held-out way to score any of these against ground truth before trusting them on the feed.
3. Headway regularity & bus bunching
Detect bunching (vehicles arriving in a convoy followed by a long gap) and quantify service regularity against the scheduled headway. Methods: headway time-series analysis; classical holding-control strategies to counter bunching.
4. Fleet sizing & dispatch (regularity, not demand)
Cycle (round-trip) time is directly measurable from the data, including its variance — the core input to fleet planning, via N = cycle_time / headway. This supports optimising regularity: how many vehicles a target headway needs, where cycle time inflates and eats service. telematics_waybills adds the planned side for September 2025: planned_runs is how many vehicles the operator intended to put out, and run_index / run_total identify the individual dispatch runs — so plan and delivery can be compared directly rather than inferred. Note the plan covers 74 route labels while the GPS covers 10 routes; the two meet on plate and date. Hard ceiling: true demand-based optimisation is not possible from this data alone — there are no passenger counts. Dwell time at stops is the only available demand proxy. Pairing with fare-validation or passenger-count data would lift this limit.
5. Anomaly & incident detection
Sudden network-wide slowdowns, vehicle breakdowns, and off-route events are detectable as deviations from the learned space-time profiles. Off-route detection is well posed here because telematics_route_shapes gives the intended alignment; the waybills also record genuine off-route assignments (charters, school runs, workshop trips), which are reassignments rather than anomalies.
6. Method validation against ground truth
Because telematics carries device speed and un-snapped positions while tracking does not, the pair supports a benchmark that most transit datasets cannot offer: degrade the raw stream into feed-like observations, run your estimator on the degraded version, and score it against the truth you held back. This is the only way to put an error bar on anything derived from the feed, and the export is non-renewable — so treat it as a test set and resist fitting on it.
Enriching with external data
The dataset becomes considerably more powerful when joined with open external sources on the same dates:
- Weather (e.g. Meteostat, Open-Meteo): rain, snow, and ice strongly depress speeds — critical for Bishkek winters. Historical series are needed so weather aligns with the tracked dates.
- Calendar / holidays, with local specifics that generic "holiday" flags miss: Nooruz, Orozo Ait and Kurman Ait follow the lunar calendar and shift year to year; Ramadan moves the evening peak toward iftar for a whole month; the school calendar reshapes the morning peak; the heating season correlates with seasonal smog.
- Road network & geometry (OpenStreetMap): road links, intersections, and turn restrictions for network analysis. Note that route alignments are already supplied for the ten 2025 routes by
telematics_route_shapes, and feed positions are already snapped, so OSM is needed for the road network rather than for matching. - Elevation / terrain for energy and speed modelling.
telematics.altitude_mgives a rough on-board reading for the ten 2025 routes, but it is GNSS altitude and noisy.
Data caveats (read before modelling)
The data faithfully reflects a real municipal feed, with the imperfections that implies. The most important ones:
- Two different timestamps.
tsis UTC and marks the polling cycle (shared by ~700 vehicles), not an individual fix.device_timeis the device clock in local time (UTC+6), truncated to the minute. They are not interchangeable. - Stale / lagging telemetry.
device_timetrailsts— median ~1 minute, but the tail is long (about 5% of records are 11+ minutes stale, ~1% are 24+ minutes). A plotted position can be well out of date. - "Ghost" vehicles. The feed keeps returning the last-known position of a vehicle that has parked or lost signal, without flagging it. On the order of a few dozen vehicles at a time show a frozen position; they inflate any naive "vehicles online" count. Filter by requiring movement over a time window.
- ~65% duplicate positions. The feed is polled every ~5 s but a new position only appears when the platform emits one, so most consecutive rows repeat the previous position. Collapse repeats first.
- Positions arrive in ~110 m steps, and that ceiling is in the device. The trigger is combined — roughly every 10–20 s of movement or about 110 m of travel, whichever comes first. Measured on the raw
telematicsstream, the 100–120 m bin holds 123,630 steps while everything above 120 m collapses to a few hundred. Consequently a vehicle's position along the route is known to no better than ~110 m, and step length grows with speed until it saturates: median 44 m below 5 km/h, 105 m above 30 km/h. - Marshrutkas are under-represented. Type
3contributes far fewer observations than buses — many minibuses are not GPS-tracked in the feed. - Night hours. Trolleybuses (
1) and marshrutkas (3) stop running at night; their absence then is real, not missing data. - Possible recording gaps. Collection is continuous but not guaranteed gap-free (network interruptions). Distinguish "no service" from "not recorded".
- Stops share names. Many same-named stops sit within ~120 m of each other — these are the two sides of a street / opposite directions, not duplicates. Key stops by `id`, never by name.
- Transit is not general traffic. Vehicles must stop at stops; a stationary vehicle may be dwelling for boarding rather than stuck in a jam. Use the
stopssubset to tell dwelling from congestion. GPS jumps and outliers also occur and should be filtered.
Caveats specific to the telematics* subsets
- All timestamps are UTC, at second resolution — unlike
tracking.device_time, which is local (UTC+6) and truncated to the minute. Do not carry a timezone assumption across subsets. - `speed_kmh` was converted. The source stored speed in knots, as the device's integer km/h value multiplied by 0.539957. It is published already converted back to integer km/h; the true resolution is therefore 1 km/h.
- The device does not report while stopped. No fix carries a speed below 1 km/h. A dwell shows up as a gap between fixes, not as a run of zeros — do not look for
speed_kmh = 0. - Speed outliers are present and were left in. Per-route maxima reach 261 km/h (route 35), 170 (100) and 141 (36). These are GNSS/Doppler glitches; filter them, but they are not removed upstream and were not removed here.
- Upload lag has a long tail.
upload_lag_shas a median of 2 s, but the 99th percentile is ~7,450 s: devices buffer while offline and dump later. This is the mechanism behind the staleness seen in the public feed. - 10,506 rows are missing from route 100. The source CSV for that route contained truncated lines (0.955 % of the file) that cannot be parsed. The published subset holds 8,793,453 of 8,803,959 exported rows.
- The device registry over-states the fleet.
telematics_deviceslists 209 devices withactive = true, but 12 produced no fixes at all and one produced only 533 over the 19 days. Count reporting devices fromtelematics, not rows in the registry. - Route 5 has two versions.
telematics_routesholdsroute_ref3 and 209 for route 5 under different operators. Join geometry and stops onroute_ref; joining onroutesilently doubles route 5's geometry. - The stop list repeats itself for route 100. In
telematics_route_stops,route_ref50 direction 1 lists each of its 32 stops eight times. The source has no sequence column at all —seqfollows source row order, so usestop_seq(first occurrences only) andis_repeatto get a usable sequence. - 46 stop links point to a route version that no longer exists (
route_ref2, an older incarnation of route 5). All are flaggeddeleted; theirrouteis null. - `route_label` in the waybills is free text, not a code. Values look like
52 "12 МКРН - КОЛМО 22 ВЫХ..". The parsedrouteandplanned_runscolumns are best-effort; 233 rows are legitimately route-less assignments (ЗАКАЗ ШКОЛЬНЫЙ АВТОБУС,РЕМОНТ,ТЕХПОМОЩЬ) and carry null. - Plates mix Cyrillic and Latin glyphs at source (
01KG459ВАwith Cyrillic В and А). All plates here are normalised to Latin. Apply the same normalisation before joining against any other source, or joins will silently lose rows. - Columns present in the export but not published: driver names and phone numbers, and device IMEI (see De-identification);
protocol,valid,accuracy,address,attributesandnetwork, which were constant or empty throughout; andcauseandbreakdown_time, which were blank and constant00:00:00respectively.
Notes
- Coordinates are WGS84 (EPSG:4326) decimal degrees throughout.
- The
stopssubset is a periodically-refreshed snapshot;trackingis append-only and grows daily; thetelematics*subsets are a fixed, one-off export and will not be extended. - The upstream platform is Traccar with Teltonika on-board devices. This is not documented by the operator but is evident from the export, and it explains several of the artefacts above.
- Provided for academic and research use.
