Query API guide

August 18, 2026 · View on GitHub

The built-in query helpers read SQLite synchronously. Open the database once and close it when the work is complete. When exactly one database is open, query helpers use it automatically:

import { closeDb, getRoutes, openDb } from 'gtfs';

openDb({ sqlitePath: './gtfs.sqlite' });

try {
  const routes = getRoutes(
    {},
    ['route_id', 'route_short_name'],
    [['route_short_name', 'ASC']],
  );
  console.table(routes);
} finally {
  closeDb();
}

Example output (values depend on the imported feed):

┌─────────┬─────────────┬──────────────────┐
│ (index) │ route_id    │ route_short_name │
├─────────┼─────────────┼──────────────────┤
│ 0       │ 'route-1'   │ '1'              │
│ 1       │ 'route-101' │ '101'            │
└─────────┴─────────────┴──────────────────┘

Pass { db } in the fourth argument when more than one database is open or when you want to make the selected connection explicit.

Common arguments

Query helpers use this shape:

getRoutes(query, fields, orderBy, options);

All four arguments are optional. Supply empty objects or arrays when you need a later argument.

query

An object of column/value filters. Multiple properties are combined with AND:

const trips = getTrips({ route_id: '12', direction_id: 0 });

An array produces an IN query. An empty array always returns no records:

const stops = getStops({ stop_id: ['123', '234', '345'] });

fields

An array of columns to return. An empty array selects every column:

const routes = getRoutes({}, ['route_id', 'route_short_name']);

In TypeScript, selected fields narrow the inferred result type.

orderBy

An array of [field, direction] pairs. The direction must be ASC or DESC:

const routes = getRoutes(
  {},
  [],
  [
    ['route_short_name', 'ASC'],
    ['route_long_name', 'ASC'],
  ],
);

options

All getters accept { db }. Stop queries also accept bounding_box_side_m.

const nearbyStops = getStops(
  { stop_lat: 37.7749, stop_lon: -122.4194 },
  [],
  [],
  {
    db,
    bounding_box_side_m: 1000,
  },
);

Query helpers by namespace

Most functions query the table corresponding to the function name with the four-argument signature shown above. Specialized helpers are described below.

GTFS Schedule

FunctionGTFS File
getAgenciesagency.txt
getAreasareas.txt
getAttributionsattributions.txt
getBookingRulesbooking_rules.txt
getCalendarscalendar.txt
getCalendarDatescalendar_dates.txt
getServiceIdsByDatecalendar.txt, calendar_dates.txt
getFareAttributesfare_attributes.txt
getFareLegJoinRulesfare_leg_join_rules.txt
getFareLegRulesfare_leg_rules.txt
getFareMediafare_media.txt
getFareProductsfare_products.txt
getFareRulesfare_rules.txt
getFareTransferRulesfare_transfer_rules.txt
getFeedInfofeed_info.txt
getFrequenciesfrequencies.txt
getLevelslevels.txt
getLocationslocations.geojson
getLocationGroupslocation_groups.txt
getLocationGroupStopslocation_group_stops.txt
getNetworksnetworks.txt
getPathwayspathways.txt
getRiderCategoriesrider_categories.txt
getRoutesroutes.txt
getRouteNetworksroute_networks.txt
getShapesshapes.txt
getShapesAsGeoJSONshapes.txt
getStopAreasstop_areas.txt
getStopsstops.txt
getStopsAsGeoJSONstops.txt
getStoptimesstop_times.txt
getTimeframestimeframes.txt
getTransferstransfers.txt
getTranslationstranslations.txt
getTripstrips.txt

GTFS-Realtime

GTFS-Realtime uses protocol buffer entities rather than .txt files.

FunctionGTFS File
getServiceAlertsGTFS-Realtime Alert entity
getServiceAlertInformedEntitiesAlert.informed_entity
getTripUpdatesGTFS-Realtime TripUpdate entity
getStopTimeUpdatesTripUpdate.stop_time_update
getVehiclePositionsGTFS-Realtime VehiclePosition entity

GTFS-Plus

FunctionGTFS File
getCalendarAttributescalendar_attributes.txt
getDirectionsdirections.txt
getRouteAttributesroute_attributes.txt
getStopAttributesstop_attributes.txt

GTFS-Ride

FunctionGTFS File
getBoardAlightsboard_alight.txt
getRideFeedInforide_feed_info.txt
getRiderTripsrider_trip.txt
getRidershipridership.txt
getTripCapacitiestrip_capacity.txt

GTFS-to-HTML

FunctionGTFS File
getTimetableNotestimetable_notes.txt
getTimetableNotesReferencestimetable_notes_references.txt
getTimetablePagestimetable_pages.txt
getTimetableStopOrderstimetable_stop_order.txt
getTimetablestimetables.txt

TODS

FunctionGTFS File
getDeadheadTimesdeadhead_times.txt
getDeadheadsdeadheads.txt
getOpsLocationsops_locations.txt
getRunEventsrun_event.txt
getRunsPiecesruns_pieces.txt

NOPTIS

FunctionGTFS File
getTripsDatedVehicleJourneystrips_dated_vehicle_journey.txt

TIDES

FunctionGTFS File
getDevicesdevices.txt
getFareTransactionsfare_transactions.txt
getOperatorsoperators.txt
getPassengerEventspassenger_events.txt
getStationActivitiesstation_activities.txt
getStopVisitsstop_visits.txt
getTrainCarstrain_cars.txt
getTripsPerformedtrips_performed.txt
getVehicleLocationsvehicle_locations.txt
getVehicleTrainCarsvehicle_train_cars.txt
getVehiclesvehicles.txt

Specialized queries

Routes by stop or service

getRoutes() accepts stop_id and service_id in addition to fields from routes.txt:

const routes = getRoutes(
  { stop_id: 'place-downtown' },
  ['route_id', 'route_short_name'],
  [['route_short_name', 'ASC']],
  { db },
);

Stops by trip data

getStops() accepts route_id, trip_id, service_id, direction_id, and shape_id in addition to fields from stops.txt:

const stops = getStops(
  { route_id: '12', direction_id: 0 },
  ['stop_id', 'stop_name'],
  [['stop_name', 'ASC']],
  { db },
);

To find stops near a point, provide stop_lat, stop_lon, and the side length of a square bounding box in meters:

const nearbyStops = getStops(
  { stop_lat: 37.7749, stop_lon: -122.4194 },
  ['stop_id', 'stop_name', 'stop_lat', 'stop_lon'],
  [],
  { db, bounding_box_side_m: 1000 },
);

When no orderBy is supplied, bounding-box results are ordered by approximate distance from the provided point.

Trips by date

getTrips() accepts date as a YYYYMMDD number and matches service from calendar.txt and calendar_dates.txt:

const trips = getTrips(
  { route_id: '12', date: 20260817 },
  ['trip_id', 'service_id'],
  [],
  { db },
);

getServiceIdsByDate(date, options) returns only the service IDs active on a date.

Stop times by date or time window

getStoptimes() accepts date, start_time, and end_time in addition to fields from stop_times.txt. GTFS times may be later than 23:59:59:

const stopTimes = getStoptimes(
  {
    date: 20260817,
    start_time: '08:00:00',
    end_time: '09:00:00',
  },
  ['trip_id', 'stop_id', 'arrival_time', 'departure_time'],
  [['departure_time', 'ASC']],
  { db },
);

Shapes by trip data

getShapes() accepts route_id, trip_id, service_id, and direction_id in addition to fields from shapes.txt.

GeoJSON

getStopsAsGeoJSON(query, options) returns a GeoJSON FeatureCollection of stops. getShapesAsGeoJSON(query, options) returns route shapes as GeoJSON.

import { getShapesAsGeoJSON } from 'gtfs';

const geojson = getShapesAsGeoJSON({ route_id: '12' }, { db });

Case-insensitive SQLite comparisons

Schema fields marked caseInsensitiveComparison use SQLite's COLLATE NOCASE. Equality, IN, and default ordering ignore ASCII letter case. GTFS IDs remain case-sensitive.

SQLite NOCASE is not Unicode-aware. Raw SQL can request another collation:

SELECT *
FROM agency
WHERE agency_name COLLATE BINARY = ?;

Advanced queries

advancedQuery(table, options) supports dynamic fields, filters, ordering, and joins:

import { advancedQuery } from 'gtfs';

const rows = advancedQuery('trips', {
  db,
  fields: ['trips.trip_id', 'routes.route_short_name'],
  query: { 'routes.route_type': 3 },
  join: [
    {
      type: 'INNER',
      table: 'routes',
      on: 'trips.route_id = routes.route_id',
    },
  ],
  orderBy: [['routes.route_short_name', 'ASC']],
});

The join.on expression is raw SQL. Do not construct it from untrusted input. For queries beyond this interface, use the better-sqlite3 connection:

const rows = db
  .prepare('SELECT trip_id FROM trips WHERE route_id = ? ORDER BY trip_id')
  .all('12');

Closing or deleting a database

Use closeDb() when you are finished with a connection. Pass the connection explicitly if the application has more than one database open:

import { closeDb, getAgencies, openDb } from 'gtfs';

const db = openDb({ sqlitePath: './gtfs.sqlite' });

try {
  const agencies = getAgencies({}, [], [], { db });
  console.table(agencies);
} finally {
  closeDb(db);
}

deleteDb() closes the connection and permanently deletes its file-backed SQLite database:

import { deleteDb, openDb } from 'gtfs';

const db = openDb({ sqlitePath: './temporary-gtfs.sqlite' });

// Use the temporary database.

deleteDb(db);

Do not use deleteDb() unless the database file is no longer needed. For an in-memory database, it closes the connection without deleting a file.