Transform your Trakt watch history into a beautiful GitHub-style contribution graph
Warning
Project status: unmaintained / archived in practice.
Trakt has changed its API access policy: free accounts can now only register a single API application. Since my one available app slot is used by Kometa, I can no longer run this project on my own account, and my graph is no longer updated.
The code still works if you have a free API app slot available (or a Trakt VIP account, which allows more applications). But I am no longer actively developing or testing it. Issues and pull requests may go unanswered β feel free to fork.
See Trakt API limitations for details and workarounds.
| Feature | Description |
|---|---|
| π¨ Light & Dark Themes | Automatically adapts to GitHub's theme preference |
| π Activity Heatmap | GitHub-style contribution graph showing movie & episode activity |
| π€ Profile Integration | Shows profile picture, display name, and all-time stats |
| π¬ Content Filtering | Display movies only, shows only, or everything together |
| π Multi-Year Support | Generate vertical graphs spanning multiple years |
| π― Streak Highlighting | Hover over stats to highlight your longest activity streak |
| π¬ Interactive Tooltips | Hover over cells to see specific titles watched that day |
| ποΈ Fast & Efficient | Uses the Trakt API with intelligent pagination and caching |
| π Daily Updates | Automated updates via GitHub Actions |
Click the Fork button at the top-right of this page.
Important
Free Trakt accounts are limited to one API application. If that slot is already taken by another tool (Kometa, Tautulli integrations, a Trakt scrobbler, ...), you must either reuse that application's Client ID or upgrade to Trakt VIP. See Trakt API limitations.
- Go to Trakt API App Setup and create a new application.
- For Redirect URI, use
urn:ietf:wg:oauth:2.0:oob. - Copy your Client ID.
- In your GitHub repository, go to Settings β Secrets and variables β Actions.
- Add a new Repository secret:
- Name:
TRAKT_API_KEY - Value:
(Your Trakt Client ID)
- Name:
Edit .github/workflows/update-trakt-graph.yml:
env:
TRAKT_USERNAME: "YOUR_TRAKT_USERNAME"Go to Actions tab β Enable workflows if prompted.
The automatic triggers (schedule and push) are commented out in this repository, because there is no working API key here anymore. In your fork, uncomment them in .github/workflows/update-trakt-graph.yml to get daily updates.
The graph updates daily at midnight UTC, or trigger manually via the Actions tab.
# Install dependencies
npm install
# Set your API Key (Client ID)
$env:TRAKT_API_KEY = "your_client_id" # Windows PowerShell
# export TRAKT_API_KEY="your_client_id" # Linux/macOS
# Basic usage
node src/cli.js <username>
# With options
node src/cli.js <username> [options]| Flag | Description | Default |
|---|---|---|
-y <years> |
Year(s) to generate, comma-separated (e.g. 2025,2024) |
Current year |
-t <type> |
Content type: movies, shows, or all |
all |
-w <day> |
Week start: sunday or monday |
sunday |
-o <path> |
Output path (without extension) | images/github-trakt |
-g <bool> |
Enable username gradient: true or false |
true |
-p |
Export PNG files in addition to SVG | Disabled |
--all-variants |
Generate combined, movies-only, and shows-only graphs in one run | Disabled |
To use the automated workflow, you must provide your Trakt API Key as a GitHub Secret:
- Go to your repository on GitHub.
- Navigate to Settings β Secrets and variables β Actions.
- Create a New repository secret.
- Set the name to
TRAKT_API_KEYand the value to your Trakt Client ID.
Full configuration is available in the workflow file header:
env:
TRAKT_USERNAME: "TheLagacyMiner"
YEARS: "" # e.g. "2025,2024" or empty for current
WEEK_START: "sunday"
GRADIENT: "true"The workflow always generates all three graph variants:
images/github-trakt-*.svgimages/trakt-movies-*.svgimages/trakt-shows-*.svg
It does this in a single CLI run, so Trakt data is fetched once and then reused for all outputs.
trakt-graph/
βββ .github/
β βββ workflows/
β βββ update-trakt-graph.yml
βββ fonts/ # Required for SVG text measurement
βββ images/ # Target directory for generated graphs
βββ src/
β βββ cli.js # CLI entry point
β βββ fetcher.js # Trakt API interaction
β βββ generator.js # SVG layout and rendering
β βββ stats.js # Activity calculations
β βββ exporter.js # PNG export (Sharp)
βββ package.json
βββ README.md
<p align="center">
<a href="https://trakt.tv/users/YOUR_TRAKT_USERNAME/" target="_blank">
<picture>
<source
media="(prefers-color-scheme: dark)"
srcset="https://github.com/YOUR_GITHUB_USERNAME/trakt-graph/blob/main/images/github-trakt-dark.svg"
/>
<source
media="(prefers-color-scheme: light)"
srcset="https://github.com/YOUR_GITHUB_USERNAME/trakt-graph/blob/main/images/github-trakt-light.svg"
/>
<img
alt="Trakt contribution graph"
src="https://github.com/YOUR_GITHUB_USERNAME/trakt-graph/blob/main/images/github-trakt-light.svg"
/>
</picture>
</a>
</p>Trakt tightened its API policy: a free Trakt account can only have one registered API application at a time. The Client ID of that single application is what this project uses as TRAKT_API_KEY.
This has a direct consequence: if you already use your API app for another service β for example Kometa, a scrobbler, or a media-server integration β you cannot simply register a second app for trakt-graph.
Options if you hit this limit:
| Option | What it means |
|---|---|
| Reuse the existing Client ID | Trakt applications are not bound to one tool. You can put the same Client ID into TRAKT_API_KEY and use it for both Kometa and this project. Only viable if the other tool does not depend on app-specific OAuth setup, and it means both tools share the same rate limit. |
| Trakt VIP | A VIP subscription lifts the application limit, so you can register a dedicated app for this project. |
| Delete the other application | Frees the slot, but breaks whatever tool was using it. |
| Stop using the project | What I did β my slot is needed for Kometa. |
Note that this project only performs public, read-only requests (watch history and profile of a public Trakt user), so it needs nothing more than a Client ID β no OAuth tokens, no user authorization.
- Node.js v18 or higher
- Trakt API Key (Client ID)
- GitHub Actions enabled for automation
MIT License. Contributions are welcome!