Read your remaining balance, recent trips, and other information from contactless public transit cards using your NFC-enabled Android or iOS device.
FareBot is a Kotlin Multiplatform app built with Compose Multiplatform, targeting Android (NFC), iOS (CoreNFC), macOS (experimental, via PC/SC smart card readers or PN533 raw USB NFC controllers), and Web (experimental, via WebAssembly).
MIFARE Classic requires proprietary NXP hardware and is not supported on iOS or on Android devices with non-NXP NFC controllers (e.g. most Samsung and some other devices). All other protocols work on both platforms. Cards marked Android only in the tables below use MIFARE Classic.
Supported Cards
Asia
| Card |
Location |
Protocol |
Platform |
| Beijing Municipal Card |
Beijing, China |
ISO 7816 |
Android, iOS |
| City Union |
China |
ISO 7816 |
Android, iOS |
| Edy |
Japan |
FeliCa |
Android, iOS |
| EZ-Link |
Singapore |
CEPAS |
Android, iOS |
| Kartu Multi Trip |
Jakarta, Indonesia |
FeliCa |
Android, iOS |
| KomuterLink |
Malaysia |
Classic |
Android only |
| NETS FlashPay |
Singapore |
CEPAS |
Android, iOS |
| Octopus |
Hong Kong |
FeliCa |
Android, iOS |
| One Card All Pass |
South Korea |
ISO 7816 |
Android, iOS |
| Shanghai Public Transportation Card |
Shanghai, China |
ISO 7816 |
Android, iOS |
| Shenzhen Tong |
Shenzhen, China |
ISO 7816 |
Android, iOS |
| Suica / ICOCA / PASMO |
Japan |
FeliCa |
Android, iOS |
| T-money |
South Korea |
ISO 7816 |
Android, iOS |
| T-Union |
China |
ISO 7816 |
Android, iOS |
| Touch 'n Go |
Malaysia |
Classic |
Android only |
| Wuhan Tong |
Wuhan, China |
ISO 7816 |
Android, iOS |
Australia & New Zealand
| Card |
Location |
Protocol |
Platform |
| Adelaide Metrocard |
Adelaide, SA |
DESFire |
Android, iOS |
| BUSIT |
Waikato, NZ |
Classic |
Android only |
| Manly Fast Ferry |
Sydney, NSW |
Classic |
Android only |
| Metrocard |
Christchurch, NZ |
Classic |
Android only |
| Myki |
Melbourne, VIC |
DESFire |
Android, iOS |
| Opal |
Sydney, NSW |
DESFire |
Android, iOS |
| Otago GoCard |
Otago, NZ |
Classic |
Android only |
| SeqGo |
Queensland |
Classic |
Android only |
| SmartRide |
Rotorua, NZ |
Classic |
Android only |
| SmartRider |
Perth, WA |
Classic |
Android only |
| Snapper |
Wellington, NZ |
ISO 7816 |
Android, iOS |
Europe
| Card |
Location |
Protocol |
Platform |
| Bonobus |
Cadiz, Spain |
Classic |
Android only |
| Carta Mobile |
Pisa, Italy |
ISO 7816 (Calypso) |
Android, iOS |
| Envibus |
Sophia Antipolis, France |
ISO 7816 (Calypso) |
Android, iOS |
| HSL |
Helsinki, Finland |
DESFire |
Android, iOS |
| KorriGo |
Brittany, France |
ISO 7816 (Calypso) |
Android, iOS |
| Leap |
Dublin, Ireland |
DESFire |
Android, iOS |
| Lisboa Viva |
Lisbon, Portugal |
ISO 7816 (Calypso) |
Android, iOS |
| Mobib |
Brussels, Belgium |
ISO 7816 (Calypso) |
Android, iOS |
| Navigo |
Paris, France |
ISO 7816 (Calypso) |
Android, iOS |
| OuRA |
Grenoble, France |
ISO 7816 (Calypso) |
Android, iOS |
| OV-chipkaart |
Netherlands |
Classic / Ultralight |
Android only (Classic), Android + iOS (Ultralight) |
| Oyster |
London, UK |
Classic |
Android only |
| Pass Pass |
Hauts-de-France, France |
ISO 7816 (Calypso) |
Android, iOS |
| Pastel |
Toulouse, France |
ISO 7816 (Calypso) |
Android, iOS |
| Rejsekort |
Denmark |
Classic |
Android only |
| RicaricaMi |
Milan, Italy |
Classic |
Android only |
| SLaccess |
Stockholm, Sweden |
Classic |
Android only |
| TaM |
Montpellier, France |
ISO 7816 (Calypso) |
Android, iOS |
| Tampere |
Tampere, Finland |
DESFire |
Android, iOS |
| Tartu Bus |
Tartu, Estonia |
Classic |
Android only |
| TransGironde |
Gironde, France |
ISO 7816 (Calypso) |
Android, iOS |
| Västtrafik |
Gothenburg, Sweden |
Classic |
Android only |
| Venezia Unica |
Venice, Italy |
ISO 7816 (Calypso) |
Android, iOS |
| Waltti |
Finland |
DESFire |
Android, iOS |
| Warsaw |
Warsaw, Poland |
Classic |
Android only |
Middle East & Africa
| Card |
Location |
Protocol |
Platform |
| Gautrain |
Gauteng, South Africa |
Classic |
Android only |
| Hafilat |
Abu Dhabi, UAE |
DESFire |
Android, iOS |
| Metro Q |
Qatar |
Classic |
Android only |
| RavKav |
Israel |
ISO 7816 (Calypso) |
Android, iOS |
North America
| Card |
Location |
Protocol |
Platform |
| Charlie Card |
Boston, MA |
Classic |
Android only |
| Clipper |
San Francisco, CA |
DESFire / Ultralight |
Android, iOS |
| Compass |
Vancouver, Canada |
Ultralight |
Android, iOS |
| LAX TAP |
Los Angeles, CA |
Classic |
Android only |
| MSP GoTo |
Minneapolis, MN |
Classic |
Android only |
| Opus |
Montreal, Canada |
ISO 7816 (Calypso) |
Android, iOS |
| ORCA |
Seattle, WA |
DESFire |
Android, iOS |
| Ventra |
Chicago, IL |
Ultralight |
Android, iOS |
| Card |
Location |
Protocol |
Platform |
| Crimea Trolleybus Card |
Crimea |
Classic |
Android only |
| Ekarta |
Yekaterinburg, Russia |
Classic |
Android only |
| Electronic Barnaul |
Barnaul, Russia |
Classic |
Android only |
| Kazan |
Kazan, Russia |
Classic |
Android only |
| Kirov transport card |
Kirov, Russia |
Classic |
Android only |
| Krasnodar ETK |
Krasnodar, Russia |
Classic |
Android only |
| Kyiv Digital |
Kyiv, Ukraine |
Classic |
Android only |
| Kyiv Metro |
Kyiv, Ukraine |
Classic |
Android only |
| MetroMoney |
Tbilisi, Georgia |
Classic |
Android only |
| OMKA |
Omsk, Russia |
Classic |
Android only |
| Orenburg EKG |
Orenburg, Russia |
Classic |
Android only |
| Parus school card |
Crimea |
Classic |
Android only |
| Penza transport card |
Penza, Russia |
Classic |
Android only |
| Podorozhnik |
St. Petersburg, Russia |
Classic |
Android only |
| Samara ETK |
Samara, Russia |
Classic |
Android only |
| SitiCard |
Nizhniy Novgorod, Russia |
Classic |
Android only |
| SitiCard (Vladimir) |
Vladimir, Russia |
Classic |
Android only |
| Strizh |
Izhevsk, Russia |
Classic |
Android only |
| Troika |
Moscow, Russia |
Classic / Ultralight |
Android only (Classic), Android + iOS (Ultralight) |
| YarGor |
Yaroslavl, Russia |
Classic |
Android only |
| Yaroslavl ETK |
Yaroslavl, Russia |
Classic |
Android only |
| Yoshkar-Ola transport card |
Yoshkar-Ola, Russia |
Classic |
Android only |
| Zolotaya Korona |
Russia |
Classic |
Android only |
South America
| Card |
Location |
Protocol |
Platform |
| Bilhete Único |
São Paulo, Brazil |
Classic |
Android only |
| Bip! |
Santiago, Chile |
Classic |
Android only |
Taiwan
| Card |
Location |
Protocol |
Platform |
| EasyCard |
Taipei |
Classic / DESFire |
Android only (Classic), Android + iOS (DESFire) |
Identification Only (Serial Number)
These cards can be detected and identified, but their data is locked or not stored on-card:
| Card |
Location |
Protocol |
Platform |
Reason |
| AT HOP |
Auckland, NZ |
DESFire |
Android, iOS |
Locked |
| Holo |
Oahu, HI |
DESFire |
Android, iOS |
Not stored on card |
| Istanbul Kart |
Istanbul, Turkey |
DESFire |
Android, iOS |
Locked |
| Nextfare DESFire |
Various |
DESFire |
Android, iOS |
Locked |
| Nol |
Dubai, UAE |
DESFire |
Android, iOS |
Locked |
| Nortic |
Scandinavia |
DESFire |
Android, iOS |
Locked |
| Presto |
Ontario, Canada |
DESFire |
Android, iOS |
Locked |
| Strelka |
Moscow Region, Russia |
Classic |
Android only |
Locked |
| Sun Card |
Orlando, FL |
Classic |
Android only |
Locked |
| TPF |
Fribourg, Switzerland |
DESFire |
Android, iOS |
Locked |
| TriMet Hop |
Portland, OR |
DESFire |
Android, iOS |
Not stored on card |
Cards Requiring Keys
Some MIFARE Classic cards require encryption keys to read. You can obtain keys using a Proxmark3 or MFOC. These include:
- Bilhete Único
- Charlie Card
- EasyCard (older MIFARE Classic variant)
- OV-chipkaart
- Oyster
- And most other MIFARE Classic-based cards
Requirements
- Android: NFC-enabled device running Android 6.0 (API 23) or later
- iOS: iPhone 7 or later with iOS support for CoreNFC
- macOS (experimental): Mac with a PC/SC-compatible NFC smart card reader (e.g., ACR122U), a PN533-based USB NFC controller (e.g., SCL3711), or a Sony RC-S956 (PaSoRi) USB NFC reader
- Web (experimental): Any modern browser with WebAssembly support. Card data can be imported from JSON files exported by other platforms. Live NFC card reading is supported in Chrome/Edge/Opera via WebUSB with a PN533-based USB NFC reader (e.g., SCL3711).
Building
$ git clone https://github.com/codebutler/farebot.git
$ cd farebot
$ make # show all targets
| Command |
Description |
make android |
Build Android debug APK |
make android-install |
Build and install on connected Android device (via adb) |
make ios |
Build iOS app for physical device |
make ios-sim |
Build iOS app for simulator |
make ios-install |
Build and install on connected iOS device (auto-detects device) |
make desktop |
Run macOS desktop app (experimental) |
make web |
Build web app (experimental, WebAssembly) |
make web-run |
Run web app dev server with hot reload |
make test |
Run all tests |
make clean |
Clean all build artifacts |
Development Container
A devcontainer is provided for sandboxed development with Claude Code. It runs Claude with --dangerously-skip-permissions inside a network-restricted Docker container so agents can work unattended without risk of arbitrary network access.
What's included
- Bun runtime + Claude Code
- Java 21 + Gradle (via devcontainer feature)
- tmux, zsh, git-delta, fzf, gh CLI
- iptables firewall allowing only: Anthropic API, GitHub, Maven Central, Google Maven, Gradle Plugin Portal, JetBrains repos, npm/bun registries
- All other outbound traffic is blocked
Quick start
bun install -g @devcontainers/cli # one-time
.devcontainer/dc up # build and start
.devcontainer/dc auth # one-time: authenticate with GitHub
.devcontainer/dc claude # run Claude (--dangerously-skip-permissions, in tmux)
The dc claude command runs Claude inside a tmux session. Re-running it reattaches to the existing session instead of starting a new one. Other commands:
.devcontainer/dc shell # zsh shell in the container
.devcontainer/dc run <cmd> # run any command (e.g. ./gradlew allTests)
.devcontainer/dc down # stop the container
Git push uses HTTPS via gh auth — no SSH keys are mounted. Credentials persist in a Docker volume across container restarts.
Compatible with Zed, VS Code (Remote - Containers extension), and the devcontainer CLI.
Tech Stack
Project Structure
base/ — Core utilities, MDST reader, ByteArray extensions
card/ — Shared card abstractions
card/*/ — Card protocol implementations (classic, desfire, felica, etc.)
transit/ — Shared transit abstractions (Trip, Station, TransitInfo, etc.)
transit/*/ — Transit system implementations (one per system)
app/ — KMP app framework (UI, ViewModels, DI, platform code)
app/android/ — Android app shell (Activities, manifest, resources)
app/ios/ — iOS app shell (Swift entry point, assets, config)
app/desktop/ — macOS desktop app (experimental, PC/SC + PN533 + RC-S956 USB NFC)
app/web/ — Web app (experimental, WebAssembly via Kotlin/Wasm)
Written By
Thanks To
[!NOTE]
Huge thanks to the Metrodroid project, a fork of FareBot that added support for many additional transit systems. All features as of v3.1.0 (04a603ba) have been backported.
License
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.