Quickstart#

This page shows how to get from a place name to the timetables and street data a routing tool needs. Our example is the city of Turku in Finland, on Wednesday 14 October 2026.

transitio works with two kinds of open data: GTFS feeds (General Transit Feed Specification), the timetables public-transport operators publish, and OpenStreetMap extracts, which hold the streets and paths people walk along. It finds the feeds serving a place in its feed index, a catalogue of the world’s feeds and the places they serve, then downloads the data and crops it to the place.

Install the feed index#

transitio reads the feed index from your computer. Install the newest snapshot once (the first download is about 70 MB):

import transitio

transitio.index.refresh()

Find a place#

Let’s start by looking up Turku in the index:

import transitio

turku = transitio.place("Turku")
turku
Place(tp_17305, city, 'Turku')

Notice that the index keys each place by an id of its own, here tp_17305, and knows its kind: a city.

Choose the feeds#

Several feeds often serve the same place, and many of them run the same buses and trains. recommend() tells which feeds to take for a day, and why it leaves out the others:

rec = turku.recommend("2026-10-14")
print(rec)
Turku (city), 2026-10-14: take 1 feed, covering over 99 % of the departures the index records there, each counted once
  + f-u6x-turunlinja~autoilijainosakeyhtiö~savonlinjaoy~sl~autolinja (Turku): covers over 99 % of the place's departures (100 % of bus)
  - f-vr~fi (Finnish passenger rail (Digitraffic)): adds too little: 0.063 % of the place's departures

As we can see, the feed of Turku’s own operator carries nearly every departure in the city, so it is the only one taken; the national rail feed would add too little.

Fetch the data#

Now we can fetch what the recommendation takes. fetch reads the place and the day from it, downloads the feed (or reuses a copy it downloaded earlier), crops it to Turku, validates it, and downloads an OpenStreetMap extract for the parts of Turku that have stops:

result = transitio.fetch(feeds=rec, directory="turku")
Fetching 1 feed for Turku
[1/1] f-u6x-turunlinja~autoilijainosakeyhtiö~savonlinjaoy~sl~autolinja: cropping and validating
Fetching the OSM extract
Done in 15 s: 1 feed delivered, 0 skipped, 13.1 MB downloaded

fetch reports its progress as it goes; in Jupyter each download also shows a progress bar. With directory="turku", a copy of each delivered feed lands in the folder turku.

The selection table sums up what happened to each feed:

table = result.selection_table()
table[["name", "decision", "fetched_from", "cache", "feed_window", "stops_outside_osm"]]
name decision fetched_from cache feed_window stops_outside_osm
0 Turku delivered producer downloaded [2026-08-10, 2027-06-06] 1181

result.paths maps each delivered feed to its file, and result.osm_pbf is the cropped OpenStreetMap extract:

print(result.paths)
print(result.osm_pbf.name)
{'f-u6x-turunlinja~autoilijainosakeyhtiö~savonlinjaoy~sl~autolinja': PosixPath('turku/f-u6x-turunlinjaautoilijainosakeyhtiosavonlinjaoyslautolinja+ca23bf3049e064ba45a72fc64e47bf328192c3b3765e1e2eca2356351af63b34.zip')}
aoi_22.03718_60.31916_22.48742_60.75166_33c8233e2d3e.osm.pbf

Hand the data to a routing tool#

The result goes straight to cafein, which builds a routable network from the feeds and the extract:

network = result.to_cafein()
print(network.stop_count, "stops,", network.trip_count, "trips,", network.transfer_count, "transfers")
UserWarning: 736 stop(s) are farther than 1600.0 m from the walking network and get no footpaths
2954 stops, 15687 trips, 62396 transfers

The warning counts the stops that cafein found too far from any street or path. fetch keeps every trip that serves Turku whole, so some buses run on to stops in the neighbouring towns, while the OpenStreetMap extract covers the parts of Turku with stops and 1.6 km around them. The stops_outside_osm column above counts the stops beyond that area; cafein still connects those within 1.6 km of a street or path, and gives the others no walking connections. Fetching data explains this in more detail.

result.to_pyrosm() opens the extract in pyrosm instead, for reading the street network, buildings or points of interest.

Next steps#

The user guide covers each step in more depth: