zenbus
v2.1.0
Published
Real-time next bus ETA from Zenbus networks via direct API (protobuf)
Maintainers
Readme
zenbus
Real-time next bus ETA from Zenbus networks.
Pure JavaScript ES module — calls the Zenbus API directly using protobuf. No browser, no scraping, no native dependencies.
Requirements
- Node.js ≥ 18
Install
npm install zenbusOr globally for CLI usage:
npm install -g zenbusJavaScript API
zenbus exports an ES module you can import directly.
import { createClient } from 'zenbus';
const client = await createClient({
alias: 'gpso',
itinerary: '5426824545828864',
stop: '5366312231501824',
});
console.log(client.stopName); // e.g. "Main Square"
console.log(client.lineCode); // e.g. "L1"
const data = await client.poll();
console.log(data);createClient(options)
Returns a Promise<ZenbusClient>.
| Parameter | Type | Description |
|---|---|---|
| alias | string | Network alias (e.g. gpso) |
| itinerary | string | Itinerary ID |
| stop | string | Stop ID |
| signal | AbortSignal | Optional — cancel in-flight requests |
client.poll()
Returns a Promise<PollResult>:
{
stop: 'Main Square', // stop name
line: 'L1', // line code
timestamp: '2026-04-11T…', // ISO poll timestamp
now: '14h35', // current time (HhMM)
first: { // closest upcoming bus, or null
eta: 4, // minutes
distance: 1200, // metres
estimatedArrival: '2026-04-11T14:39:00.000Z',
scheduledTime: '2026-04-11T14:42:00.000Z', // null if no schedule data
isLive: true, // true = real-time GPS, false = scheduled
},
next: { … } | null, // second live bus if available
}Cancellation
const ac = new AbortController();
const client = await createClient({
alias: 'gpso',
itinerary: '…',
stop: '…',
signal: ac.signal,
});
// later
ac.abort();CLI
zenbus --alias gpso --itinerary 5426824545828864 --stop 5366312231501824Options
| Option | Env var | Description | Default |
|---|---|---|---|
| --alias | ZENBUS_ALIAS | Network alias | required |
| --itinerary | ZENBUS_ITINERARY | Itinerary ID | required |
| --stop | ZENBUS_STOP | Stop ID | required |
| --interval | ZENBUS_INTERVAL | Poll interval in seconds | 10 |
| --output | — | terminal or json | terminal |
Terminal output
Live-updating display with real-time ETA, distance, scheduled time, and 2nd bus when available. Press Ctrl+C to quit.
JSON output
zenbus --alias gpso --itinerary … --stop … --output jsonPrints one JSON object per poll cycle to stdout — pipe to jq, log to file, or feed into another process.
{
"stop": "Main Square",
"line": "L1",
"timestamp": "2026-04-11T14:35:12.345Z",
"now": "14h35",
"first": {
"eta": 4,
"distance": 1200,
"estimatedArrival": "2026-04-11T14:39:00.000Z",
"scheduledTime": "2026-04-11T14:42:00.000Z",
"isLive": true
},
"next": {
"eta": 12,
"distance": 3400,
"estimatedArrival": "2026-04-11T14:47:00.000Z",
"scheduledTime": "2026-04-11T14:50:00.000Z",
"isLive": true
}
}Tests
npm testUses Node's built-in test runner — no extra test dependencies.
Finding your IDs
Open your stop on zenbus.net. The URL contains everything you need:
https://zenbus.net/publicapp/web/{alias}?line=…&stop={stop}&itinerary={itinerary}License
MIT
