Skip to content

Repository files navigation

Uzbekistan Railways ticket bot — seat monitor & auto-booker for eticket.railway.uz

Watches eticket.railway.uz (O'zbekiston Temir Yo'llari) for train seats on your route, holds them the second they appear, and sends a link to your phone so you can pay from bed.

Built on the site's own JSON API — no browser automation, no Selenium, no Playwright in the hot path. A poll is one HTTP request; grabbing a seat is one call. Includes a full reference for the undocumented eticket.railway.uz API, which may be the most useful part of this repo if you're building something else against it.

Next.js TypeScript Tailwind CSS License

The problem

Tickets for popular Uzbek routes — Toshkent → Nukus, Toshkent → Buxoro, anything to Samarqand in season — sell out the hour they open. Seats do come back: cancellations, blocks released by the railway, people whose holds expire. They appear at random, often at 3am, and they're gone in minutes.

So the bot polls every ~8 seconds. When enough seats appear together, it holds them — the same call the website makes when you press Davom etish — which locks them for ~11 minutes and blocks other buyers. Then it messages you on Telegram with a link. You open it on your phone, type your Uzcard/Humo number and the SMS code, and go back to sleep.

The bot never pays. It only holds, which is reversible and expires on its own. The card step is always a human decision.

Features

  • Seat monitor — polls one or more dates, filters by train number and carriage class
  • Group-aware seat picking — prefers a whole empty compartment, otherwise the tightest cluster that still meets your bottom-berth requirement (nobody wants to give grandma a top bunk)
  • Auto-hold — one API call, so it wins races against people clicking through the UI
  • Pay from your phone — a mobile payment page served from your own machine
  • Live hold countdown — the authoritative deadline from the server, not a guess
  • One-tap release — free the seats instantly if you change your mind
  • Telegram alerts — start, matches, holds, failures, and a periodic "still alive"
  • Survives restarts — if the process dies overnight it resumes watching by itself
  • Tickets afterwards — passengers, seats, PDF, and the verify-QR link once payment clears

Quick start

git clone https://github.com/AydosJs/railway-bot.git
cd railway-bot
npm install

Create .env.local:

RAILWAY_USERNAME=998XXXXXXXXX     # your eticket.railway.uz phone login
RAILWAY_PASSWORD=your-password
TELEGRAM_BOT_TOKEN=...            # from @BotFather
TELEGRAM_CHAT_ID=...              # from @userinfobot
# PUBLIC_URL=https://your-tunnel  # only if you expose the dashboard beyond your wifi

Then:

npm run build
npm run overnight        # caffeinate + next start, so the Mac doesn't sleep through the drop

Open http://localhost:3000, set your route, dates and passengers, tick Auto-grab, press Start watching.

Passenger names are matched against the saved-passengers list on your railway account, so add everyone there first. If a name doesn't match, the bot alerts you instead of holding — it will never book a stranger because of a typo.

How it works

lib/railway.ts    typed API client — auth, search, seat maps, hold, cancel, payment
lib/seatpick.ts   which seats to take
lib/monitor.ts    the poll loop and the grab
lib/paywatch.ts   the payment-status WebSocket
app/dashboard.tsx control panel
app/pay/          the phone payment flow
scripts/          the capture tooling used to reverse-engineer all of it

Three findings made this simpler than expected, all documented in API.md:

  1. CSRF is self-serve. The server only checks that X-XSRF-TOKEN matches the XSRF-TOKEN cookie — a UUID you generate yourself is accepted. No browser session required.
  2. The login endpoint has no captcha. The login page does, but POST /api/v1/auth/login takes username and password directly and returns a JWT.
  3. Card payment is plain JSON. No hosted checkout, no iframe, no redirect: payme/do-paymentpayme/create-card (number + MM/YY) → payme/verify-card (SMS code), with results pushed over wss://eticket.railway.uz/ws. That's why payment doesn't have to happen on the machine that made the hold — this app hosts the card form itself.

Paying from your phone

The server binds to 0.0.0.0, so anything on your wifi can reach it. The Telegram message contains http://<your-lan-ip>:3000/pay/<orderId>. Tap it and you get the seats, the price, a live countdown, then card → SMS → done. Away from home? Point a tunnel (ngrok, Tailscale, Cloudflare) at port 3000 and set PUBLIC_URL.

Card details are forwarded straight to the railway payment API and never touch disk — only the last four digits appear in the activity log.

API reference

API.md documents the endpoints captured from the live site: search, seat maps, saved passengers, the order/hold lifecycle, hold deadlines and cancellation, the full Payme card chain, and the status WebSocket protocol. Each entry notes how it was verified. If you're building anything against eticket.railway.uz, start there — it will save you the week this took.

Disclaimer

Automated booking probably violates the site's terms of service. This was written for one family buying four tickets, not for resale or scale.

  • Keep polling at 8 seconds or slower (the UI enforces a 5-second floor).
  • A hold is real: it ties up seats on your account and appears in your order list. Unpaid holds expire in ~11 minutes; Release frees them immediately.
  • Auto-grab is off by default. Arming it is always a deliberate click.
  • Don't use this to hoard inventory. Someone else needs that berth.

Provided as-is, for education and personal use. You are responsible for how you use it.

License

MIT — see LICENSE.


Keywords: Uzbekistan Railways API, eticket.railway.uz, O'zbekiston Temir Yo'llari, UTY, UZ railway train tickets, Toshkent Nukus Samarqand Buxoro poyezd chiptasi, train ticket bot, seat availability monitor, ticket alert, Afrosiyob booking, Payme API integration, Uzcard Humo payment, reverse engineered API, Next.js TypeScript automation.

About

Uzbekistan Railways (eticket.railway.uz) seat monitor and auto-booker. Watches for train tickets, holds seats instantly via the site's own API, and lets you pay from your phone. Includes a full reference for the undocumented API.

Topics

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages