A full-stack lottery draw tracker and analytics platform covering 40+ US states and Canadian provinces. The app scrapes live draw results daily, stores them in PostgreSQL, and surfaces pattern analytics, digit frequency, streak detection, and next-draw countdowns through a real-time Next.js dashboard.
- Live draw results — daily scraping of Pick 3, Pick 4, and Pick 5 games across 40+ states
- Pattern analytics — doubles, triples, quads, pairs, even/odd distributions, sum analysis
- Digit frequency — hot/cold digits per game, overdue digit rankings
- Streak detection — consecutive pattern streaks across all tracked states
- Next-draw countdown — live timer per game session (Morning / Midday / Evening / Night)
- State pages — individual state dashboards with results, stats, and pattern history
- Number generator — smart picks based on frequency and pattern data
- Real-time updates — WebSocket + Server-Sent Events push new draws to the UI as they land
- Canadian lottery support — OLG (Ontario), WCLC (Western Canada), ALC (Atlantic), Loto-Québec
| Layer | Technology |
|---|---|
| Frontend | Next.js 14, React 18, TypeScript, Tailwind CSS |
| Data fetching | TanStack React Query, custom SSE/WebSocket hooks |
| Charts & maps | Recharts, react-simple-maps |
| Backend API | FastAPI, uvicorn, SQLAlchemy 2.0 (async) |
| Database | PostgreSQL + psycopg3 (async driver) |
| Caching | Redis |
| Scraping | Playwright (headless Chromium), BeautifulSoup4 |
| Scheduling | APScheduler |
| Package manager | pnpm (monorepo) |
lottery-tracker/
├── apps/
│ ├── scraper/ # FastAPI backend + scraper service
│ │ ├── app/
│ │ │ ├── api/ # REST & WebSocket route handlers
│ │ │ ├── core/ # Settings, logging, rate limiting
│ │ │ ├── db/ # SQLAlchemy models & async session
│ │ │ ├── scrapers/ # Per-state and per-site scraper modules
│ │ │ └── services/ # Redis cache, APScheduler, WebSocket manager
│ │ ├── scripts/ # One-off data import & backfill utilities
│ │ └── run.py # Entry point (SelectorEventLoop for Windows)
│ └── web/ # Next.js frontend
│ ├── app/ # App Router pages & API routes
│ ├── components/ # Reusable UI and lottery-specific components
│ └── lib/ # API client, hooks, draw schedule config
├── packages/
│ ├── database/ # Prisma schema, migrations, seed
│ └── types/ # Shared TypeScript interfaces
└── scripts/ # PowerShell setup automation
- Node.js 18+ and pnpm 9+
- Python 3.12+
- PostgreSQL 15+
- Redis 7+
- Playwright browsers (installed via
playwright install chromium)
git clone https://github.com/WiseActions/LotteryAnalytics.git
cd LotteryAnalyticspnpm installcd apps/scraper
pip install -e ".[dev]"
playwright install chromium# apps/scraper/.env
DATABASE_URL=postgresql+psycopg://postgres:yourpassword@localhost:5432/lottery
REDIS_URL=redis://localhost:6379/0
CORS_ORIGINS=http://localhost:3000
# apps/web/.env.local
NEXT_PUBLIC_API_BASE_URL=http://localhost:8000# Create the database
psql -U postgres -c "CREATE DATABASE lottery;"
# Run Prisma migrations
cd packages/database
pnpm prisma migrate deploy
pnpm prisma db seed# Terminal 1 — FastAPI backend (from apps/scraper/)
python run.py
# Terminal 2 — Next.js frontend (from apps/web/)
pnpm devOpen http://localhost:3000 to view the app. The API is available at http://localhost:8000.
Windows note: The backend explicitly uses
SelectorEventLoopto satisfy both psycopg3 (async DB) and Playwright (subprocess scraping). Do not useuvicorn --reload— it conflicts with this setup.
| Method | Path | Description |
|---|---|---|
| GET | /api/states |
All active states |
| GET | /api/states/{state}/games |
Games for a state |
| GET | /api/games/{gameId}/results |
Paginated draw results |
| GET | /api/games/{gameId}/results/latest |
Most recent draw |
| GET | /api/games/{gameId}/stats |
Hot/cold digits, jackpot stats |
| GET | /api/stats/summary |
Total draw count across all games |
| GET | /api/dashboard/latest |
Latest draws across all states |
| POST | /api/scrapers/run/{state} |
Trigger a scrape for a state |
| GET | /api/scrapers/status |
Scraper job status |
| POST | /api/admin/cache/clear |
Clear Redis cache (by state) |
Full interactive docs: http://localhost:8000/docs
- lotteryusa.com — Primary source for live US state draws (Playwright-rendered)
- lotterypost.com — Historical backfill (calendar scraper)
- OLG / WCLC / ALC / Loto-Québec — Direct scraping for Canadian provinces
Each state/game combination maps to a StateGameEntry (defined in state_games.py) that specifies the URL slug, draw time sessions, and game type. The LotteryUSAScraper fetches the page via a subprocess-isolated Playwright call (to avoid Windows event loop conflicts), parses draw dates and numbers from the rendered inner text using regex, and upserts results into PostgreSQL — skipping duplicates and correcting stale numbers on re-runs.
The scheduler triggers configured scrapers on a cron schedule and broadcasts new results to connected clients over WebSocket.
- Fork the repo and create a feature branch:
git checkout -b feature/your-feature - Make your changes, following the existing code style (2-space indent, no TypeScript in Python files)
- Commit with a short imperative message:
git commit -m "add NY Pick 5 scraper" - Push and open a pull request against
main
This project is for personal and educational use. Lottery draw data is sourced from publicly available results pages. This tool does not facilitate gambling or claim to predict lottery outcomes.