Kaggle simulation competitions produce thousands of match replays, but the website only lets you reach them one click at a time. Kaggle Replays gives you one screen to browse competitions, submissions, and episodes, filter by outcome, and bulk-download replays — without hammering Kaggle's API or risking your account.
Studying replays is one of the best ways to improve a competition agent, but doing it by hand is slow, and automating it naively is dangerous: Kaggle's internal API rate-limits aggressively, and a tight request loop can get your account throttled or banned. This project is built around avoiding exactly that.
Browse competitions, submissions, and per-submission episodes; see real skill-rating scores; filter episodes by win, loss, or draw; and bulk-download replays as JSON or ZIP with live progress.
Every read in the interface is served from a local database cache. The live Kaggle API is touched only by a once-a-day scheduler or an explicit "Sync now" — never automatically on page loads or navigation.
Lists the competitions you have entered, with active or completed status.
Real skill-rating scores and episode counts per submission, served from cache.
Each episode classified as win, loss, or draw from the agents' terminal rewards.
Download replays as JSON or ZIP, optionally filtered by outcome, with live WebSocket progress.
Current public standings with the top-ten-percent cutoff, a competition selector, and search.
Dated leaderboard snapshots and the replay episode IDs of the top performers over time.
Kaggle has no public API for simulation episodes, so the backend drives an already-authenticated Playwright browser session (saved once via an interactive login) to call the same internal endpoints the website uses. The results are written to MySQL, and the interface reads from there.
competitions → submissions → episodes → replays. Each level is fetched once, cached, then served locally.
A submission's score is the agent skill rating from the latest episode, not the empty "formatted" field — so it never shows a misleading 0.
Live calls happen only on a daily schedule or an explicit sync, paced sequentially, stopping on the first rate-limit response.
| Component | Responsibility |
|---|---|
| downloader.py | Async Playwright client for Kaggle's internal API: list competitions / submissions / episodes, fetch replays in batches, classify outcomes. |
| backend/ (FastAPI) | REST + WebSocket API, MySQL persistence, JWT auth, security layer, per-user Playwright context pool, and a daily sync scheduler. |
| MySQL | The cache the UI reads from: competitions, submissions, episode lists, scores, and dated leaderboard snapshots. |
| Frontend (React + TS) | Vite single-page app with an in-memory access token, light/dark themes, and live download progress. |
Full instructions are in the repository README. In short:
# 1. Database brew services start mysql # create the kaggle_replays DB + a user # 2. Backend cd Backend python3 -m venv .venv .venv/bin/python -m pip install -r backend/requirements.txt .venv/bin/python -m playwright install chromium cp backend/.env.example backend/.env # fill in DB URL + JWT secrets .venv/bin/python login.py # log in to Kaggle once -> auth.json .venv/bin/python -m alembic -c backend/alembic.ini upgrade head .venv/bin/python -m uvicorn backend.main:app --port 8000 # 3. Frontend (another terminal) cd Frontend npm install npm run dev # http://localhost:5173
Why this is a local tool. The backend authenticates to Kaggle as you, using your saved browser session (auth.json). Hosting the live application on a public server would place your personal Kaggle credentials there and could violate Kaggle's Terms of Service, so the application is meant to run locally for your own account. This page is the project's public face; the app itself stays on your machine.