A fast, fully self-contained Windows CLI tool that fetches live PNR status from the Indian Railways enquiry portal. Built in Rust with statically linked Tesseract OCR for captcha solving β the release binary has no runtime dependencies beyond standard Windows system DLLs.
- Live PNR lookup β queries the official Indian Railways API directly
- Automatic captcha solving β preprocesses and solves the arithmetic image captcha using an embedded Tesseract 5 OCR engine (no external setup needed)
- Session caching β reuses the JSESSIONID cookie between runs to skip unnecessary session initialisation
- Waitlist prediction β automatically fetches CNF probability data when any passenger is on a waiting list
- Rich terminal output β colour-coded passenger status, fare, charting status, and a probability bar for WL predictions
- JSON export β optionally writes structured output to a
.jsonfile - Single binary β everything (Tesseract model, OCR engine, TLS, HTTP
client) is statically linked; copy
pnr-scraper.exeanywhere and it works (see portability note in Quick Start if you need to distribute the binary to other machines)
| Requirement | Notes |
|---|---|
| Windows 10 / 11 (x64) | The only supported platform |
| Rust + MSVC toolchain | rustup with the x86_64-pc-windows-msvc target |
| Visual Studio C++ tools | "Desktop development with C++" workload in VS Installer |
| Git | Needed by setup.ps1 to clone vcpkg |
Note: You only need Rust/MSVC/Git to build the project. The compiled
pnr-scraper.exebinary runs on any 64-bit Windows machine with no extra software installed, provided it was built withouttarget-cpu=native(see portability note below).
git clone https://github.com/chunkboi/pnr-scraper.git
cd pnr-scraperThis clones microsoft/vcpkg, compiles it, and then compiles Tesseract + Leptonica + all their image-format dependencies as static libraries. This only needs to be done once. Expect 10β25 minutes on first run.
.\setup.ps1If you get a permissions error on
vcpkg integrate install, re-run with-SkipIntegrateβ the build will still work via theVCPKG_ROOTsetting in.cargo/config.toml:.\setup.ps1 -SkipIntegrate
cargo build --releaseThe finished binary is at target\release\pnr-scraper.exe.
β Portability note: The default
.cargo/config.tomlsets-C target-cpu=native, optimising for your CPU's instruction set (AVX2, SSE4.2, β¦). The resulting binary will not run on older or different CPU models. To produce a generic, portable binary, comment out therustflagsblock in.cargo/config.tomlbefore building:# [target.'cfg(target_arch = "x86_64")'] # rustflags = ["-C", "target-cpu=native"]
pnr-scraper [OPTIONS]
Options:
-p, --pnr <PNR> 10-digit PNR number
-e, --export <FILE> Export structured JSON to a file (e.g. data.json)
--show-json Print raw API JSON to the console
-v, --verbose Step-by-step debug logging with per-stage timings
--ttl <SECONDS> Local session TTL before force re-init [default: 900]
-h, --help Print help
-V, --version Print version
# Interactive β prompts for PNR
pnr-scraper.exe
# Pass PNR directly
pnr-scraper.exe --pnr 1234567890
# Export to JSON
pnr-scraper.exe --pnr 1234567890 --export status.json
# Show raw API response + verbose debug output
pnr-scraper.exe --pnr 1234567890 --show-json --verbose ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
π PNR STATUS RESULT
ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β PNR Number 1234567890
β As of 05-Apr-2026 [14:32:11 IST]
ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β JOURNEY DETAILS
β βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β Train 12345 β RAJDHANI EXPRESS
β Date 05-Apr-2026
β From β To NDLS β MAS
β Class 1A
ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β PASSENGER STATUS (1 passenger)
β βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β Passenger 1 (GN)
β Booking : CNF/B1/32
β Current : β CNF/B1/32
ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β FARE & CHARTING
β βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β Total Fare βΉ 4560
β Chart Status Chart Prepared
ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β± Fetched in 3.42 seconds
The Indian Railways enquiry portal protects its API with an arithmetic image
captcha (e.g. 47 + 23). On startup, the captcha-required check and the first
image download are issued concurrently (tokio::join!) so no sequential
round-trip is wasted. The solver then:
- Receives the pre-fetched PNG captcha image
- Preprocesses the image:
- Alpha-composite over white background
- Auto-invert if the image is dark-on-light
- Upscale 3Γ with bilinear interpolation
- Median filter (noise removal) β contrast enhancement β unsharp mask
- Binarizes with a fast threshold (128) and tries OCR immediately
- If the fast path fails, tries two fallback thresholds (110, 150) sequentially
- OCR is performed by a single
OcrHandle(a RAII wrapper around Tesseract 5) initialised once whenApiClientis constructed and shared across tasks viaArc.eng.traineddatais embedded in the binary at compile time and extracted atomically to a temp directory on first run. - Evaluates the parsed arithmetic expression and submits the answer
- Pipelining β while the API request is in-flight, the next captcha image
is fetched in the background (
fetch_captcha_owned). On a retry this pre-fetched image is used immediately, saving one full network round-trip (~100β300 ms per retry).
- On the first request a session is initialised by fetching the PNR enquiry
page to obtain a
JSESSIONIDcookie - The cookie is persisted to
~/.pnr_session.jsonand reused for subsequent runs within the TTL window (default 5 minutes) - If the server returns
"Session out or Invalid Request", the session is automatically purged and re-initialised - Disk write failures (session cache, UA cache) are surfaced as visible
[WARN]lines rather than silently discarded
All native libraries (Tesseract 5, Leptonica, libjpeg, libpng, libtiff, zlib,
libwebp, libgif) are compiled with the vcpkg x64-windows-static-md triplet
and linked statically. The resulting .exe depends only on Windows system DLLs
(KERNEL32, WS2_32, VCRUNTIME140, etc.) that ship with every modern
Windows installation.
pnr-scraper/
βββ src/
β βββ main.rs # CLI argument parsing, top-level orchestration
β βββ api.rs # HTTP client, session management, fetch-retry loop
β βββ captcha.rs # OcrHandle (RAII), image preprocessing, captcha solver
β βββ ui.rs # Terminal display, colour-coded output
β βββ models.rs # Shared data types (PnrResult, SessionCache, β¦)
βββ tessdata/ # β gitignored β created at build time
β βββ eng.traineddata # Tesseract English model (embedded into binary at compile time)
βββ .cargo/
β βββ config.toml # VCPKGRS_TRIPLET + VCPKG_ROOT + target-cpu flag (relative path)
βββ setup.ps1 # One-time vcpkg bootstrap script
βββ Cargo.toml
βββ Cargo.lock
leptonica-sys and tesseract-sys (the Rust FFI crates used by
tesseract-plumbing) use the
vcpkg crate to locate native libraries at
build time. setup.ps1 installs those libraries with the
x64-windows-static-md triplet so they link statically into the final binary.
[env]
VCPKGRS_TRIPLET = "x64-windows-static-md"
VCPKG_ROOT = { value = "vcpkg_tools", relative = true }
# Enable native CPU instruction set (AVX2, SSE4.2, etc.) for auto-
# vectorisation of pixel processing loops. Only safe when you build
# and run on the same machine β comment this out for a portable binary.
[target.'cfg(target_arch = "x86_64")']
rustflags = ["-C", "target-cpu=native"]VCPKG_ROOT uses Cargo's relative = true feature, so it resolves to
<repo_root>/vcpkg_tools regardless of where you clone the repository.
target-cpu=native enables AVX2/SSE4.2 auto-vectorisation for the
pixel-processing loops in the captcha pipeline. Remove or comment out that
block if you need the binary to run on machines other than the one it was built
on.
cargo build --releasevcpkg libraries are precompiled; only the Rust code is recompiled.
MIT β see LICENSE for details.