Spotify Statistics Tracker that doesn't require Spotify Premium. Similiar to Your__Spotify
3.8K
A web application that allows users to track and analyze their Spotify listening habits and statistics without Spotify Premium.
/history page with instant AJAX filtering, and track daily listening activity with a contribution-style streak calendar on the Dashboard/playlists page - ready for Spotify or converters like Soundiiz and TuneMyMusic/admingit clone https://github.com/i7Gamer/SpotifyStatsTracker
cd SpotifyStatsTracker
pip install -r requirements.txt
Use this docker-compose file:
version: '3.8'
services:
spotify-tracker:
image: i7gamer/spotify-tracker
ports:
- "5000:5000"
volumes:
- ./Database/Data:/app/Database/Data
- ./autoImport:/app/autoImport #< files put in this folder will be imported automatically
environment:
- FLASK_APP=wsgi.py
- PYTHONUNBUFFERED=1
- TZ=America/Los_Angeles #< don't forget to change this or you will get the wrong times for songs
- FLASK_SECRET_KEY=changeme-generate-your-own-random-value #< YOU MUST CHANGE THIS - the app refuses to start on this exact placeholder (it's public, so it makes sessions forgeable). Generate one with `python -c "import secrets; print(secrets.token_hex(32))"`. A fixed value = sessions survive a restart; unset = a new one is generated each restart, logging everyone out. Also used to encrypt stored Spotify sessions unless DATA_ENCRYPTION_KEY is set - changing it means everyone must log in again.
# - DATA_ENCRYPTION_KEY=changeme-another-random-value #< Optional dedicated key for encrypting stored Spotify sessions/API secrets at rest (falls back to FLASK_SECRET_KEY). Keep it safe alongside your backups: without the key that encrypted them, stored sessions can't be read and every user must re-login with fresh cookies.
# - TRUST_PROXY_HEADERS=1 #< Set when running behind a reverse proxy (nginx/traefik/caddy) so rate limiting sees real client IPs instead of the proxy's; use the number of proxy hops (usually 1). Only set this if a proxy is actually in front - otherwise clients could forge their IP.
# - ENABLE_HSTS=1 #< Send a Strict-Transport-Security header so browsers pin this origin to HTTPS. Only enable behind a TLS-terminating reverse proxy - on plain-HTTP access it will lock browsers out of the site.
# - [email protected] #< Makes this account the instance's only admin (grants access to the Admin Console at /admin to view all user sync states, worker health, and system settings). Without it, the earliest-registered user is promoted automatically.
# - SPOTIFY_CALLBACK_URL=http://localhost:5000/spotify-callback #< Uncomment and set to your public callback URL to enable Spotify Web API backfilling
# - IMPORT_KEYWORD=Weekly #< Uncomment to apply a filter to what files get auto-imported (only files containing this will be imported)
# - FLASK_DEBUG=1 #< To get more detailed logs from Flask (provide this when opening an issue)
# - SKIP_EMAIL_VERIFICATION=1 #< Uncomment to disable the "do these cookies belong to this email" check at login (only do this if you trust everyone who can reach this instance - it's what stops one user from claiming another's account, AND what stops the /reset-password flow from letting anyone set a new password on any account)
restart: always
Then you can run docker compose up -d and the app should start on http://127.0.0.1:5000 or http://yourIp:5000
To update the container if an update is available, run docker compose pull
Note on scaling: the app runs as a single process (Waitress/Flask). In-memory state - the per-IP auth rate limiter, the login-status cache, and the background worker pools - lives in that one process and is not shared, so run one instance rather than scaling it horizontally behind a load balancer.
Listening history, tracks, images, and login sessions live in a single SQLite
database under Database/Data/. If you were relying on secrets/ being mounted (e.g. so
secrets/flask_secret_key.txt persisted across restarts), set FLASK_SECRET_KEY
as shown above instead; otherwise everyone's login session resets on each container
restart.
python app.py
http://localhost:5444
or whatever your IP is
http://127.0.0.1:5444
Note: The Docker container persists data in the Database/Data/ directory on your host machine.
The admin console has an optional "Restart app to apply" button — used after changing worker-pool sizes on the Advanced Tuning panel, since those only take effect on restart. It works by gracefully stopping background workers and exiting, so something must relaunch the process. It stays hidden unless you set ALLOW_INSTANCE_RESTART=1.
restart: always in docker-compose.yml), so it is safe to enable there.python wsgi.py directly, wrap it in a supervisor that restarts on exit (a Windows service via NSSM, a Task Scheduler task, or a simple loop script such as while ($true) { python wsgi.py }) before enabling this — otherwise the button just stops the app with nothing to bring it back.Listening history, tracks, images, and login sessions all live in one SQLite file at Database/Data/spotify_stats.db.
Automatic backups are on by default: the app snapshots the database every 24 hours into Database/Data/Backups/ (covered by the standard volume mount) and keeps the newest 7 snapshots. Tune or disable via environment variables:
# - BACKUP_INTERVAL_HOURS=24 #< how often to snapshot; 0 disables automatic backups
# - BACKUP_RETENTION_COUNT=7 #< how many snapshots to keep; 0 disables automatic backups
These snapshots live on the same disk as the database, so they protect against corruption and accidental deletion - copy them somewhere else (a different disk, cloud storage) for real disaster protection.
You can also export your own play history from the Profile page (JSON in Spotify's extended-export format - re-importable via the Import page - or CSV).
To take a manual snapshot: the app runs the database in WAL mode, so don't just copy the .db file while the container is running - recent writes can still be sitting in a separate -wal file that a raw copy would miss, producing a backup that's silently missing data or corrupt. Use SQLite's own online backup API instead, which is safe to run against a live, in-use database:
docker compose exec spotify-tracker python -c "import sqlite3; sqlite3.connect('/app/Database/Data/spotify_stats.db').backup(sqlite3.connect('/app/Database/Data/spotify_stats_backup.db'))"
This writes spotify_stats_backup.db into the same Database/Data/ folder on your host machine (via the volume mount). Copy that file somewhere else - a different disk, cloud storage, etc. - for it to actually protect you against data loss, and rename or timestamp it before backing up again if you want to keep more than one snapshot.
Stored Spotify sessions and API secrets inside the database are encrypted with the key from DATA_ENCRYPTION_KEY (or FLASK_SECRET_KEY if that's not set - see the compose example above). Two practical consequences: keep that key somewhere safe alongside your backups, since a restored backup is unreadable without the key that encrypted it (listening history stays intact; everyone just has to log in with fresh cookies again) - and don't treat a backup as fully safe to hand around either, because anyone holding both the backup and the key can read every user's live Spotify session.
To enable automatic backfilling of missed plays via the Spotify Developer API, you must configure the SPOTIFY_CALLBACK_URL environment variable:
http://localhost:5000/spotify-callback).SPOTIFY_CALLBACK_URL environment variable in your docker-compose.yml to this exact callback URL.Each user can add their own Last.fm API key to have a background worker fetch genre tags for the artists, albums, and songs in their listening history:
Songs or albums Last.fm has no tags for inherit their artist's genres; the instance admin can toggle whether those inherited genres count towards backfill progress and genre stats from the Admin Console (/admin).
This project is licensed under the MIT License - see the LICENSE file for details.
For support, please open an issue on the GitHub repository or contact me.
Content type
Image
Digest
sha256:dbb1e8441…
Size
96.5 MB
Last updated
about 24 hours ago
docker pull i7gamer/spotify-tracker