BYTETOOLS

Mobilités M (Grenoble) API

Free Grenoble public transport API with no key: tram and bus routes, stops, live arrivals and journey planning on an OpenTripPlanner backend. Tested example included.

No API key requiredCORS enabledHTTPSFree tier

Endpoint tested and returned HTTP 200 on 2026-08-21

What is the Mobilités M (Grenoble) API?

Mobilités M publishes a free, key-free API for public transport in the Grenoble metropolitan area. Built on OpenTripPlanner, it serves tram and bus routes with their official colours, stop lists, live arrival times and full journey planning.

Because the backend is OpenTripPlanner, the routes, stops and planning endpoints follow OTP's own conventions rather than a bespoke design — which is a real advantage if you have worked with OTP before, since the response shapes and the `agency:id` identifier format will already be familiar. `SEM:A` is the tram A operated by SEM; the prefix is the agency and the suffix the route.

Two identifiers appear side by side and they are not interchangeable. `id` is the OTP internal identifier and `gtfsId` is the one used in the published GTFS feed, so joining live API data to a downloaded timetable means matching on `gtfsId`. The `color` and `textColor` pair arrives without a leading hash, unlike several other operators in this directory, so prepend one before using them as CSS. The `pdfTimeSheet` and `pdfMap` booleans indicate whether printable material exists for a route.

Quick facts

Base URL
https://data.mobilites-m.fr/api
Authentication
No API key or account. Open data published by the Grenoble-Alpes Métropole mobility authority.
Rate limit
No published quota. Route and stop data change only with timetable revisions; cache them rather than re-fetching.
Pricing
Free.
CORS
Enabled — callable directly from browser JavaScript
Official docs
Read the docs

How to use the Mobilités M (Grenoble) API

Every request below was executed against the live API on 2026-08-21, and the response shown is the real body it returned — not an illustration.

1. List every tram and bus route in the Grenoble network

GET https://data.mobilites-m.fr/api/routers/default/index/routes

curl
curl 'https://data.mobilites-m.fr/api/routers/default/index/routes'
JavaScript (fetch)
const res = await fetch("https://data.mobilites-m.fr/api/routers/default/index/routes");
if (!res.ok) throw new Error(`Request failed: ${res.status}`);
const data = await res.json();
console.log(data);
Python (requests)
import requests

res = requests.get("https://data.mobilites-m.fr/api/routers/default/index/routes", timeout=20)
res.raise_for_status()
print(res.json())
Response — HTTP 200 (truncated)
[
  {
    "id": "SEM:A",
    "gtfsId": "SEM:91",
    "shortName": "A",
    "longName": "Fontaine La Poya / Le Pont-de-Claix L'Étoile",
    "color": "3376B8",
    "textColor": "FFFFFF",
    "mode": "TRAM",
    "type": "TRAM",
    "timeSheet": true,
    "pdfTimeSheet": true,
    "pdfMap": true
  },
  {
    "id": "SEM:B",
    "gtfsId": "SEM:92",
    "shortName": "B",
    "longName": "Grenoble Oxford / Gières Plaine des Sports",
    "color": "479A45",
    "textColor": "FFFFFF",
    "mode": "TRAM",
    "type": "TRAM",
    "timeSheet": true,
    "pdfTimeSheet": true,
    "pdfMap": true
  },
  {
    "id": "SEM:C",
    "gtfsId": "SEM:93",
    "shortName": "C",
    "longName": "Seyssins Le Prisme / Saint-Martin-d'Hères Université – Condillac",
    "color": "C20078",
    "textColor": "FFFFFF",
    "mode": "TRAM",
    "type": "TRAM",
    "timeSheet": true,
    "pdfTimeSheet": true,
    "pdfMap": true
  },
  {
    "id": "SEM:D",
    "gtfsId": "SEM:94",
    "shortName": "D",
    "longName": "Grenoble Gares / Saint-Martin-d'Hères Étienne Grappe",
    "color": "DE9917",
    "textColor": "FFFFFF",
    "mode": "TRAM",
    "type": "TRAM",
    "timeSheet": true,
    "pdfTimeSheet": true,
    "pdfMap": true
  },
  {
    "id": "SEM:E",
    "gtfsId": "SEM:95",
    "shortName": "E",
    "longName": "Fontanil-Cornillon Palluel / Grenoble Louise Michel",
    "color": "533786",
    "textColor": "FFFFFF",
    "mode": "TRAM",
    "type": "TRAM",
    "timeSheet": true,
    "pdfTimeSheet": true,
    "pdfMap": true
  },
  {
    "id": "SEM:NAVA",
    "gtfsId": "SEM:27",
    "shortName": "NAVA",
    "longN

Parameters

ParameterTypeRequiredDescription
(routes)pathOptional`/routers/default/index/routes` lists every route in the network. routes
(one route)pathOptional`/routers/default/index/routes/{id}` returns a single route. SEM:A
(stops for route)pathOptional`/routers/default/index/routes/{id}/stops` lists the stops a route serves. stops
(stop times)pathOptional`/routers/default/index/stops/{id}/stoptimes` returns upcoming departures at a stop.
(journey planning)pathOptional`/routers/default/plan?fromPlace=&toPlace=` plans a trip using OTP's planner.

Response fields

idstring
OpenTripPlanner identifier in `agency:route` form, such as "SEM:A".
gtfsIdstring
The identifier used in the published GTFS feed. Different from `id` — this is the one to join on.
shortName / longNamestring
The label shown on the vehicle and the full description with both termini.
color / textColorstring
Official hex colours without a leading hash. Prepend `#` before using them in CSS.
mode / typestring
`TRAM`, `BUS` and so on. Both fields carry the same value in this feed.
timeSheet / pdfTimeSheet / pdfMapboolean
Whether a timetable and printable route material exist for the route.

What you can build with the Mobilités M (Grenoble) API

  • Build a Grenoble route browser with official line colours
  • Show live departures at a tram or bus stop
  • Plan journeys across the Grenoble metropolitan network
  • Join live API data to the published GTFS feed via gtfsId
  • List every stop on a tram line for a route diagram

Common errors and how to fix them

Colours render as default styling

`color` has no leading hash.

Fix: Prepend `#` before applying it as CSS. Several operators include the hash and this one does not, so do not assume.

A join against GTFS finds nothing

You matched on `id` rather than `gtfsId`.

Fix: OTP's internal id and the GTFS id are different values. Use `gtfsId` whenever the other side of the join is the published feed.

404 on a route id

The identifier needs its agency prefix.

Fix: Routes are addressed as `SEM:A`, not `A`. URL-encode the colon if your client does not.

Empty stop times

Nothing is due within OTP's forward window.

Fix: The window is short by design. Use the schedule endpoints for planned times outside it, and expect nothing overnight.

Mobilités M (Grenoble) API — frequently asked questions

Is the Grenoble transport API free?

Yes, free with no key or account. It is open data published by the Grenoble-Alpes Métropole mobility authority.

What backend does it run on?

OpenTripPlanner, which is why the paths and response shapes follow OTP conventions. If you have integrated OTP elsewhere, most of what you know transfers directly.

What is the difference between id and gtfsId?

`id` is OpenTripPlanner's internal identifier and `gtfsId` is the one in the published GTFS feed. They look similar but are not the same, and joining on the wrong one silently returns nothing.

Can it plan journeys, not just list routes?

Yes. The `/routers/default/plan` endpoint is OTP's journey planner, taking origin and destination coordinates or stop ids and returning itineraries with legs and times.

Tools that pair with this API

Mobilités M (Grenoble) is an independent third-party service and is not affiliated with ByteTools or ByteVancer. Details on this page were verified on 2026-08-21; always check the official documentation before relying on this API in production, as terms and limits can change.