How Where Is My Train finds your train without internet or GPS
· 10 min read · Android, Mobile networks, System design
Your phone is talking to a mobile tower all the time, even with mobile data off. Where Is My Train turns that one fact, plus a timetable stored on your phone, into a live position for your train. Here is how it works, how accurate it can be, and how to see the same data on your own phone.
- Topic
- Mobile networks · location · Android
- Based on
- The app's Google Play listing, 3GPP and Android docs, Mozilla's location service docs, and press coverage of the 2018 Google deal
- Edition
- November 2026
TL;DR
- Where Is My Train shows a train's live position in India. Its own listing says that when you're on the train, this feature "can work without internet or GPS as it uses cell tower information to find the location" [1].
- A phone stays registered to a mobile tower whenever it has signal, with data on or off. That's how calls and SMS reach you, and every cell has an ID the phone can read.
- The app keeps the Indian Railways timetable offline on the phone [1], so it already knows your train's route and the order of its stations.
- Matching "which cell am I on right now" to a spot on that known route gives a position with no data connection. When the cell changes, the train has moved on.
- It's an estimate, not a GPS fix: a cell can be small in a city and many kilometres wide in the countryside [6], so precision follows the size of the cell.
- Google bought the app's maker, Sigmoid Labs, in December 2018 [3].
- 0
- internet or GPS needed on the train [1]
- 500M+
- Play Store downloads, Nov 2026 [1]
- 10M+
- downloads when Google bought it, 2018 [2][3]
- Dec 2018
- Google acquires Sigmoid Labs [3]
- 2015
- first Android release [5]
Mobile networks, from zero
A mobile network covers the country with towers (base stations). Each tower serves one or more cells: the patch of ground its antennas cover. Your phone is always "camped" on one serving cell and keeps an eye on the neighbouring ones, so it can switch as you move.
Every cell has a name
Each cell broadcasts an identity. In GSM this is the Cell Global Identity (CGI): four numbers that together are unique worldwide [7].
| Part | What it identifies | Example |
|---|---|---|
| MCC · Mobile Country Code | The country | 404 / 405 = India |
| MNC · Mobile Network Code | The operator in that country | e.g. 45 |
| LAC · Location Area Code | A group of cells (a location area) | e.g. 1302 |
| CI · Cell Identity | One cell inside that area | e.g. 40123 |
4G uses the same idea under another name, the E-UTRAN Cell Global Identity (ECGI), with a longer 28-bit cell ID [7]. The MNC, LAC and CI values above are illustrative.
Your phone reports in, even with data off
To deliver a call, the network has to know roughly where you are. So an idle phone sends a location update whenever it moves into a new location area, and also on a regular timer [8]. None of this uses mobile data: it's the same signalling that lets a call ring on a phone with data switched off.
The part that matters here: the phone itself always knows which cell it's on, and apps can read it (see "See your own cell ID" below).
Why a moving train is hard to track
Problem 1: data comes and goes
On a long journey, coverage keeps changing: city stretches with good 4G, then fields, ghats and tunnels with weak or no data. An app that needs the internet to fetch a live position goes blank exactly when you most want to know where you are.
Problem 2: GPS inside a train isn't easy either
GPS needs a clear view of the sky. Under open sky a smartphone is typically accurate to about 4.9 m, but buildings, bridges and trees make it worse [9]. Inside a metal coach, away from the window, a phone can take a long time to get a fix, and keeping GPS on for hours drains the battery.
Why it matters
- Waking up at the right station is the real job, and it matters most at night, often in exactly the stretches with no data.
- Telling family where you are shouldn't depend on 4G.
- Battery: a long journey with GPS always on is a drained phone.
The insight: the route is already known
Finding a random phone from a cell ID alone is rough, because a cell can be big. But a train is not a random phone.
How it works, step by step
The app's makers haven't published their algorithm, so this is a simplified model built from what the listing says [1] and how mobile networks work [7][8]. Treat the details as a reconstruction, not the app's code.
- 1
Download the timetable once
The Indian Railways timetable (trains, stations, order, times) is stored on the phone [1]. You pick your train, and the app knows its route.
- 2
Know which cells sit along each route
To turn a cell ID into a place, the app needs a map from cell IDs to stretches of track. How Where Is My Train builds this isn't public; a map like this is typically built up from many phones' observations along known routes.
- 3
Read the serving cell
On the train, the phone reports which cell it's camped on (and which neighbours it can see). It's the same information the phone uses for calls, so it works with data off.
- 4
Snap it to the route
The cell is looked up in the map and placed on your train's route: "between Station B and Station C". The timetable helps choose when a cell touches more than one segment.
- 5
Follow the changes
As the train runs, the serving cell changes. Each new cell further down the line moves the train forward on the map. Between changes, the timetable gives a sensible guess of progress.
The picture
📶 Serving cell
MCC · MNC · LAC · CI read from the radio. No data, no GPS.
🗺️ Cell → track map
Which stretch of which line each cell covers (simplified).
🕒 Offline timetable
Stations, order and times for your train [1].
🚆 Position
"Between Station B and C": a live estimate on the route.
The matching idea, in code
A tiny illustration of the last two steps. It is not the app's code; a real system also handles noise, neighbour cells and missing entries.
// a stretch of one line that a cell is known to cover
data class Stretch(val fromStation: String, val toStation: String, val km: ClosedRange<Double>)
// cell id ("mcc-mnc-lac-ci") -> stretches of track it covers (built offline)
val cellMap: Map<String, List<Stretch>> = loadCellMap()
fun locate(cell: String, route: Route, lastKm: Double): Stretch? {
// keep only stretches on THIS train's route
val onRoute = cellMap[cell].orEmpty().filter { route.covers(it) }
// trains don't go backwards: prefer the stretch just ahead of the last fix
return onRoute.filter { it.km.endInclusive >= lastKm }
.minByOrNull { it.km.start - lastKm }
}Two cheap tricks do most of the work: the route filter (a train can't be on another line) and "forward only" (a train can't jump back).
Accuracy and trade-offs
- Cell size sets the precision. Cells are small in cities and large in rural areas. Mozilla's open location service notes GSM cells can reach 35 km, rural 3G cells have been seen at 60–70 km, and 4G cells are often smaller [6]. On a route, though, a big cell still maps to one stretch of track.
- Updates are steppy. The position jumps when the cell changes; in between, it's a guess from the timetable.
- Late or early trains. The timetable says where the train should be; the cell says where it is. When they disagree, the cell wins, but a big cell leaves room for error.
- Coverage gaps. With no signal at all (some tunnels), there's no cell to read either; the app can only estimate until the next cell.
- Privacy and permissions. On Android, reading cell information requires the location permission [10], because a cell ID reveals roughly where you are.
- Battery and data. Reading the serving cell costs almost nothing, which is why the listing calls the app very efficient in battery and data use, with key features working offline [1].
GPS vs a cell tower, to scale
How big is the "you are somewhere in here" circle? Typical radii, drawn to scale against a 10 km rural cell:
GPS figure from GPS.gov [9]. The two cell sizes are illustrative examples within the ranges in [6]; real cells vary by operator, terrain and technology. The GPS bar shows at its minimum visible width.
Ways to track a train, compared
| Approach | Needs | Trade-off |
|---|---|---|
| Official running status (Indian Railways NTES) | Internet | Authoritative, but you need data to see it |
| Phone GPS | Sky view, battery | Precise when it works; weak inside a coach, heavy on battery |
| Shared live location (maps apps) | GPS + internet | Stops updating in dead zones |
| Cell tower + offline timetable | Just the signal you need for calls | Works offline, almost no battery; precision depends on cell size |
See your own cell ID
You can read the same information the app uses. Here's a minimal Android example that prints the cell your phone is camped on.
1. Ask for location permission
Cell information counts as location data, so Android requires ACCESS_FINE_LOCATION for it [10].
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />2. Read the serving cell
TelephonyManager.getAllCellInfo() returns the camped/registered cell and the neighbours the phone can see [10]. The registered one is your serving cell.
val tm = getSystemService(TelephonyManager::class.java)
// call only after the user has granted ACCESS_FINE_LOCATION
val serving = tm.allCellInfo?.firstOrNull { it.isRegistered }
when (serving) {
is CellInfoLte -> serving.cellIdentity.let {
// 4G: mcc / mnc / tracking area / cell id
println("LTE ${it.mccString}-${it.mncString}-${it.tac}-${it.ci}")
}
is CellInfoGsm -> serving.cellIdentity.let {
// 2G: mcc / mnc / location area / cell id
println("GSM ${it.mccString}-${it.mncString}-${it.lac}-${it.cid}")
}
else -> println("no registered cell (no signal?)")
}3. Watch it change
- Turn mobile data off and run it again: you still get a cell. That's the whole trick.
- On a bus or train ride, log it every minute: the ID changes as you pass from tower to tower.
- Newer Android versions cache cell info;
requestCellInfoUpdate()asks for a fresh reading [10].
Code is illustrative and trimmed (no permission prompt or error handling). Field names come from Android's CellIdentityLte and CellIdentityGsm classes [10].
So, how does it find the train?
Tower + timetable.
Your phone always knows which mobile cell it's on, internet or not. The app already has your train's route and schedule on the phone. Put the two together and it can say "your train is between these two stations" from a coach with no data and no GPS.
Getting the best out of it
Caveats
- Not the app's published design. The listing confirms the cell-tower method and the offline timetable [1]; the step-by-step model above is a simplified reconstruction.
- How the cell map is built isn't public. Wikipedia mentions anonymised data from users and reports from Indian Railways' NTES, but cites pages that no longer load [5], so this post doesn't rely on it.
- Two download numbers. "10M+" is from press coverage of the 2018 deal [2][3]; "500M+" is the Play Store counter in November 2026 [1].
- Accuracy figures are general. The cell sizes in [6] come from Mozilla's location service, not from this app or Indian operators.
FAQ
- Does it really work with mobile data off?
- On the train, yes. The listing says the feature can work without internet or GPS because it uses cell tower information [1].
- Does it need a SIM card?
- It needs the phone to be on a mobile network, since the serving cell is what it reads. With no SIM and no network, there's no cell to read.
- Is this the same as triangulation?
- Not quite. Using only the serving cell ID is the simplest form. Combining several towers' signals can do better, but the core idea here needs just the one cell plus the known route.
- Can my operator see where I am?
- The network always knows roughly which cell you're in; that's how calls reach you [8]. The app reading the cell ID on your phone doesn't change that.
- Why does it sometimes show the wrong station?
- Big cells, a late train or a stale reading can put the estimate a stretch off. It corrects itself at the next cell change, or when data comes back.
- Who makes it?
- Sigmoid Labs, the Bengaluru startup Google bought in December 2018 [3]; the listing names "Sigmoid Labs and its affiliates" [1].
Glossary
- Cell
- The area covered by one set of antennas on a tower.
- Serving cell
- The cell your phone is camped on right now.
- CGI / ECGI
- Cell Global Identity: country + operator + area + cell number, unique worldwide (ECGI in 4G).
- LAC / TAC
- Location or tracking area code: a group of cells the network tracks you by.
- Location update
- The idle phone telling the network which area it's in, so calls can reach it.
- NTES
- National Train Enquiry System: Indian Railways' official train running information.
- GPS fix
- A position computed from satellite signals; needs a view of the sky.
Sources
- Where is my Train. Google Play listing (description, downloads), read November 2026.
- Google acquires the Where Is My Train app. Android Authority, December 2018.
- Google acquires Sigmoid Labs, developer of popular Indian app 'Where is my Train'. VentureBeat, 10 December 2018.
- Download count at the time of the deal (10M+): Android Authority [2] and VentureBeat [3].
- Where Is My Train. Wikipedia (launch date; data-source claims with dead citations).
- Accuracy. Ichnaea (Mozilla Location Service) documentation.
- Cell Global Identity. Wikipedia, after 3GPP TS 23.003.
- Location area. Wikipedia.
- GPS Accuracy. GPS.gov.
- TelephonyManager.getAllCellInfo() and CellIdentityLte. Android developer reference.