MOTIS plans multimodal journeys across transit, walking and sharing mobility
multimodal routing, geocoding, and map tiles
At a glance
- What is it?
- MOTIS is a C++ platform that combines OpenStreetMap street data, GTFS and NeTEx timetables, real time feeds and GBFS sharing mobility data into one routing engine with a REST API and an OpenAPI specification. It is built for planet sized datasets on modest hardware, and the day to day cost is a preprocessing step that has to stay in step with your feeds.
- Who is it for?
- MOTIS fits a transport data team or a MaaS product that needs one routing engine across public transport, walking, cycling, car and sharing mobility, and that has to serve a region the size of a country from a single binary.
- Can I use it commercially?
- Yes. MIT is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
- Is it still maintained?
- Yes. The repository received new commits within the last day.
- What is it written in?
- Mainly C++, according to GitHub's language statistics.
Answers come from the project's GitHub data, last synced on October 22, 2026, and from our analysis. They are not legal advice.
Editorial analysis
One router across every mode of transport
MOTIS stands for Modular Open Transportation Information System, and it is described as an open source software platform for efficient planning and routing in multi modal transportation systems.
The multi modal part is where the engineering effort sits. MOTIS integrates walking, cycling, sharing mobility such as e-scooters, bike sharing and car sharing, and public transport, and produces optimized routing solutions across them. The routing feature supports one mode of walking, bike, car, sharing mobility, or combined modes.
On top of routing there are three more capabilities. Geocoding provides multi language address and stop name completion with fuzzy string matching and resolution to geo coordinates, which matters for a transit planner where the user types a stop name rather than an address. Reverse geocoding resolves coordinates to the closest address. And a tile server produces background map tiles.
The design goal is stated as a note above the feature list: MOTIS is optimized for high performance with low memory usage, which is what enables planet sized deployments on affordable hardware. It describes itself as a swiss army knife for mobility, which is a fair characterisation of a single binary that does routing, geocoding and tiles.
Features can be turned on and off as needed, which matters when the same binary has to serve a production routing endpoint and a small test instance.
Four input families, and a lot of format support
The supported input formats fall into four groups, and the breadth here is what makes MOTIS interesting to a transit data team.
First, one OpenStreetMap osm.pbf file provides the street network, addresses and indoor routing. Second, multiple GTFS and NeTEx feeds provide static timetables, including GTFS Flex and GTFS Fares v2. Third, multiple real time feeds cover GTFS-RT, SIRI-ET, SIRI-SX, SIRI-FM and VDV 454 AUS, delivering delays, cancellations, track changes and service alerts. Fourth, multiple GBFS feeds describe sharing mobility, including geofencing, station status and vehicle availability.
The real time half is what separates MOTIS from a plain GTFS router. A static timetable says a train should arrive at 14:32. A GTFS-RT or SIRI feed says it is actually delayed, cancelled, or that its platform changed, and MOTIS folds that into the journey. For a user planning a trip that involves a transfer, that difference is the difference between a usable planner and a misleading one.
The topics recorded for the project track the same surface: gbfs, gtfs, gtfs-fares, gtfs-fares-v2, gtfs-flex, gtfs-rt, intermodal, maas, mobility-as-a-service, multimodal, netex, openapi, openstreetmap, real-time, routing, routing-engine, siri and transit. The primary language is C++, and the licence is MIT.
Traffic day bitsets make a year of timetables cheap
One implementation detail in the feature list explains how the memory claim is achieved. MOTIS uses efficient traffic day bitsets, which allows efficient loading of full year timetables, and the documentation states that loading one year of timetable does not take much more RAM than loading one month.
This is worth pausing on, because timetables are the part of transit data that scales badly. A static GTFS feed for a large region contains service patterns for every day of a year, each of which expands into a set of trips. The naive representation is a large number of objects, and a year of them is a large number of objects. A bitset per service pattern, indexed by day of year, collapses that into one bit per pattern per day, which is small and which can be queried directly.
The consequence for an operator is that the difference between serving today's timetable and next year's is small enough to be irrelevant, which removes a whole class of operational pressure. The same idea applies to the calendar of a feed that changes seasonally.
The other half of the performance story is the static data path. Because MOTIS preprocesses its input rather than parsing it per request, the server does no heavy parsing at request time, and that is why the quick start separates the import step from the server step rather than doing everything at start up.
Config, import, server: three commands
The quick start is three commands, and the split is the architecture. You create a folder with the input files, download MOTIS from the latest release and extract the archive, put an OpenStreetMap dataset in as osm.pbf for example from Geofabrik, and put one or more GTFS datasets in the same folder.
Then:
./motis config my.osm.pbf gtfs.zip # generates a minimal config.yml
./motis import # preprocesses data
./motis server # starts a HTTP server on port 8080 The config step generates a minimal config.yml from the files you name, the import step preprocesses the data and creates a data folder, and the server then starts on port 8080.
The full worked example for the city of Aachen in Germany is given for Linux and macOS:
# set TARGET to linux-arm64, macos-arm64, ... to fit your setup
# see release list for supported platforms
TARGET="linux-amd64"
wget https://github.com/motis-project/motis/releases/latest/download/motis-${TARGET}.tar.bz2
tar xf motis-${TARGET}.tar.bz2
wget https://github.com/motis-project/test-data/raw/aachen/aachen.osm.pbf
wget https://opendata.avv.de/current_GTFS/AVV_GTFS_Masten_mit_SPNV.zip
./motis config aachen.osm.pbf AVV_GTFS_Masten_mit_SPNV.zip
./motis import
./motis serverThe target variable is how the same documentation covers several platforms, with linux-amd64 shown and the comment noting linux-arm64 and macos-arm64 as alternatives to fit your setup. A Windows equivalent is given as a PowerShell block that downloads motis-windows.zip and an aachen.zip archive and runs the same three commands.
The container image follows the same shape. The Dockerfile starts from alpine:3.20, adds the platform tarball, creates a motis group and user, makes a /data directory owned by that user, exposes 8080, declares /data as a volume, switches to the motis user and runs the server against it.
An outdated timetable silently empties the results
There is an important note attached to the quick start, and it is the kind of failure that produces a working server with empty results.
The documentation says to ensure a valid timetable is used, and that if the timetable is outdated, it will not contain any trips to consider for upcoming dates. There is no error message in that case. The routing engine is doing exactly what it was told, because the trips it has are all in the past.
This matters more for MOTIS than for a smaller router, because MOTIS is built for deployments that span a whole timetable horizon at once. A feed that stopped updating months ago still imports cleanly, still produces a config file, still starts a server, and still answers with a plausible looking response. The failure surfaces as journeys that cannot be found rather than as a crash.
The same logic applies to the real time feeds. They are described as optional inputs, and their value is entirely in their freshness. A planning system built on MOTIS therefore has a dependency on feed operators, not just on the software, and the operational work of monitoring that freshness is part of adopting it.
It is worth noting what the documentation does not say. There is no mention in the available text of a scheduler, a cron style job, or a documented refresh command for the real time inputs, and the import step is described as preprocessing the input files rather than as an incremental update. An operator planning a production deployment needs to work out that refresh strategy against the actual data pipeline, and the Advanced Setups document in docs/setup.md is the place to look for it.
The API is the contract, and the spec is in the repo
MOTIS exposes an easy to use REST API with JSON over HTTP, described by an OpenAPI specification. The specification is hosted for browsing and its source is openapi.yaml in the repository root, which means clients for any language can be generated from a spec you can read and diff.
A pre-generated JS client is published on npm as @motis-project/motis-client, and more client libraries are listed at Transitous.
That last point leads to the other half of the story. Transitous operates a MOTIS instance with global coverage, as far as available, at api.transitous.org, and the README asks that you read the Usage Policy at transitous.org/api before integrating that endpoint into an app. So there are two deployment paths: run MOTIS yourself, or call a hosted instance that someone else runs and operates.
The hosted path is what many integrators will start with, and it removes the entire operational burden of feeding and preprocessing data. It also means your routing depends on a third party's coverage and their usage policy, and on their data being current for your region, which is exactly the freshness question raised above.
The repository also carries itinerary_id.proto at the top level, which is a protocol buffer definition, and an ui directory, so there is a web front end component alongside the server. The C++ build uses CMake with CMakePresets.json, a .clang-format and .clang-tidy.in configuration, and the project uses the pkg dependency manager from motis-project/pkg with its own .pkg and .pkg.lock files.
Where MOTIS is the wrong answer
Three situations argue against it.
The first is a small operator. MOTIS is explicitly built for large scale transportation data and planet sized deployments. The Aachen example is a city, and even that requires an import step and a data folder. If you run three bus routes, the import pipeline, the feed synchronisation and the server are more infrastructure than the routing deserves, and a hosted public routing API would serve you better.
The second is a team that needs a product rather than a platform. MOTIS gives you an engine, a REST API and an OpenAPI spec. It does not give you an operator interface, a ticketing system, a fare calculation, or a user account model. A MaaS product with those requirements is building several systems, and MOTIS covers one of them well.
The third is a hard real time requirement on arrival predictions. The real time inputs are feeds, and feeds are only as good as the operator publishing them and the transitous network delivering them. If your product promise depends on knowing a train's platform two minutes before it arrives, a feed based pipeline has an inherent lag that no amount of routing engine quality removes.
The alternative worth naming is doing it yourself over OpenStreetMap and GTFS with a smaller focused library, which is viable if you only need static timetable routing for a modest region, and which you should choose if you want a smaller operational surface and accept less of the multi modal and real time surface. The trade is direct. MOTIS gives you a broad feature set in one binary, tuned for very large data, and charges you in preprocessing complexity and feed freshness management. A smaller library gives you less and costs less to run.
Editorial conclusion
MOTIS fits a transport data team or a MaaS product that needs one routing engine across public transport, walking, cycling, car and sharing mobility, and that has to serve a region the size of a country from a single binary. It is the wrong tool for a single city or a small operator, where the preprocessing pipeline and feed ingestion are more work than the routing itself, and it is the wrong tool if you need a hosted API without running the service, since the public instance is operated by Transitous under a usage policy. Before adopting it, check three things: that your timetable data is current, since the documentation warns that an outdated timetable contains no trips for upcoming dates and the whole engine keys off that, that you can run the import step on the scale of your region, and that the openapi.yaml contract in the repository matches the client generation you intend to rely on, since that file is what other language clients are built from.
Frequently asked questions
What is MOTIS and what does it do?
MOTIS, the Modular Open Transportation Information System, is an open source C++ platform for planning and routing in multi modal transportation. It provides routing across walking, cycling, car, sharing mobility and public transport, plus geocoding, reverse geocoding and a background map tile server, all behind a REST API.
How do I run MOTIS for the first time?
Put an osm.pbf file and one or more GTFS datasets in a folder, then run ./motis config my.osm.pbf gtfs.zip to generate a config.yml, ./motis import to preprocess the data into a data folder, and ./motis server to start the HTTP server on port 8080.
Which data formats can MOTIS read?
One OpenStreetMap osm.pbf file for the street network, addresses and indoor routing, multiple GTFS and NeTEx feeds including GTFS Flex and GTFS Fares v2 for timetables, multiple GTFS-RT, SIRI-ET, SIRI-SX, SIRI-FM and VDV 454 AUS feeds for real time updates, and multiple GBFS feeds for sharing mobility.
Why does MOTIS return no routes even though the server starts?
The documentation warns to ensure a valid timetable is used, because if the timetable is outdated it will not contain any trips to consider for upcoming dates. The engine starts normally and simply has no trips to plan with, so the symptom is empty results rather than an error.
Is there a hosted MOTIS API I can use instead of running it?
Yes. Transitous operates a MOTIS instance with global coverage at api.transitous.org, and the README asks that you read the Usage Policy at transitous.org/api before integrating that endpoint into an app. A pre-generated JS client is also published on npm as @motis-project/motis-client.
Official sources
Add this badge to your README
If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.
[](https://hysenlabs.com/projects/motis-project-motis)Was this useful?