Boarding pass scanner
The fastest way to log a flight you’re about to take or just took: point your phone camera at the boarding pass.
The parser handles three pass formats — IATA-standard PDF417 barcode (international air), Aztec / QR (newer e-tickets), and visual-only (some hand-stamped passes from regional carriers). Each is read by a different combination of barcode + vision parser.
How it works
Section titled “How it works”1. You upload an image (camera, phone gallery, scanned PDF page)2. Barcode decoder runs first ↓ if barcode found, parse IATA bcbp string → done, fields filled ↓ if no barcode, fall through3. Vision parser cascade reads the visual - Ollama vision (default, local) - OpenAI Vision (paid, faster) - Anthropic Claude Vision (paid, alternative) - Tesseract OCR (always available, fallback)4. Whichever step extracts a usable flight number wins5. Flight-lookup API fills in aircraft, distance, scheduled times6. Review screen — you confirm or edit, then saveMost modern boarding passes carry a PDF417 or Aztec barcode that decodes in milliseconds, so step 2 catches them. The vision cascade is for older, non-barcoded, or poorly-photographed passes.
What the barcode contains
Section titled “What the barcode contains”The IATA “Bar Coded Boarding Pass” (bcbp) standard packs everything about the flight into a single string:
M1WITTKE/DENNIS EFRA LHR LH 401 137Y012A0024 348>2180WW6098B …Decoded:
M1= Mandatory format, one legWITTKE/DENNIS= Passenger nameEFRA= Booking referenceLHR= Departure airport (this is the arrival in this example because the pass is for the return leg)LH 401= Operating carrier and flight number137= Day of year (= 17 May)Y= Cabin class (Y = Economy)012A= Seat 12A0024= Sequence number
TravStats’ barcode parser handles all four mandatory fields plus the optional fields most airlines fill in. Even a corner-mangled photograph of the barcode usually decodes — the format is heavily error-corrected by design.
Uploading
Section titled “Uploading”Flights → Import → Boarding Pass. Three input methods:
- Camera — for boarding passes you have in hand. Click Use camera, the browser asks for permission, point at the pass.
- File upload — for PDF passes, screenshots, or photos already in your phone gallery.
- Drag and drop — for desktop browsers, drag any image file onto the page.
Image size limit is 20 MB. Anything in JPEG, PNG, WebP or PDF (single page).
The vision cascade in detail
Section titled “The vision cascade in detail”Configured under Admin → Settings → Boarding Pass Parser. Each tier has an enable/disable toggle and a priority rank. Defaults:
| Tier | Default rank | Notes |
|---|---|---|
| Ollama vision | 1 | Free, runs in your bundled Ollama container if you’ve pulled a vision model |
| OpenAI Vision | 2 | Cloud, paid, ~$0.001 per scan, fastest and most accurate |
| Anthropic Claude | 3 | Cloud, paid, comparable quality to OpenAI |
| Tesseract OCR | 4 | Always available, slowest, less accurate, last resort |
The full breakdown is on the Vision parsers page.
When barcoded vs visual matters
Section titled “When barcoded vs visual matters”| Pass type | Decoding path |
|---|---|
| Modern e-ticket on phone | Aztec or QR → barcode decoder → done in ms |
| Modern paper boarding pass | PDF417 → barcode decoder → done in ms |
| Hand-stamped paper pass (regional carriers) | No barcode → vision cascade |
| Scanned PDF from a print-out | Barcode decoder runs first; if scan was clean it works, otherwise vision cascade |
| Photo of an old boarding pass (retroactive logging) | Visible barcode? barcode wins. No barcode? vision cascade |
The vision cascade also fires on barcoded passes whose barcode didn’t decode — usually because of glare on the photo. So even when you take a bad picture, you’ll usually still get a result.
What gets filled in
Section titled “What gets filled in”Once the parser has a flight number and date, the flight-lookup API auto-fills the rest:
- Aircraft type (from AirLabs / Aviationstack / OpenSky)
- Operating carrier vs marketing carrier (codeshare resolution)
- Scheduled departure / arrival times in canonical UTC
- Distance (computed from airport coordinates)
If you haven’t configured any flight-data API key yet, you’ll see just what the pass itself carries — flight number, date, seat, class, departure/arrival airport. Aircraft type stays blank until you enable enrichment or fill it in manually.
Re-scanning the same pass
Section titled “Re-scanning the same pass”If you’ve already entered the flight manually and now scan its boarding pass, TravStats matches on flight number + calendar day + departure/arrival airports and fills in fields you didn’t manually set. Curated fields are never overwritten.
You’ll see a flightMerged toast on the dashboard reporting how many fields were filled. The merge fires whether the source is a barcode decode or a vision-parser result — same row gets enriched either way.
Privacy
Section titled “Privacy”Image processing happens inside your TravStats container by default — the bundled Ollama vision model never sees the public internet, and Tesseract OCR is purely local.
The image only leaves your network if the cascade reaches a cloud parser (OpenAI / Claude). You explicitly opt into that by configuring those providers and ranking them in the cascade.
For maximum privacy, configure only Ollama vision + Tesseract; for maximum accuracy with cents-per-year cost, add OpenAI; for both, keep Ollama at rank 1 and OpenAI at rank 2 so the local parser tries first and only falls through on hard cases.