Yamtrack: a self hosted tracker for films, series, anime, games and books
A self hosted media tracker.
At a glance
- What is it?
- Yamtrack is a Django application that keeps your watch, read and play history in your own database, with Docker as the documented install path. It is a good fit for people who already run a media server; it is not a hosted service.
- Who is it for?
- Yamtrack suits people who already run a home server and want their media history in a database they control, especially if they use Jellyfin, Plex or Emby and want new plays recorded without manual entry. Skip it if you want a zero-maintenance hosted service, or if you expect native iOS and Android clients: the README lists no mobile app, and the calendar reaches external applications only through its iCalendar URL.
- Can I use it commercially?
- Yes, with strict conditions. AGPL-3.0 is a network copyleft licence: if people use a modified version over a network, for example as a hosted service, you must offer them its source code under the same licence.
- Is it still maintained?
- Yes. The repository received new commits within the last day.
- What is it written in?
- Mainly Python, according to GitHub's language statistics.
Answers come from the project's GitHub data, last synced on October 1, 2026, and from our analysis. They are not legal advice.
Editorial analysis
What Yamtrack tracks and who ends up running it
Yamtrack is a self hosted media tracker for movies, tv shows, anime, manga, video games, books, comics, and board games, according to the README. That list is wider than most trackers manage: a single install covers films, serialised television, print, and games, so a household does not need one account on a film site and another on a manga site.
The intended user is someone with a server already running. The repository ships a Dockerfile, a docker-compose.yml, a docker-compose.postgres.yml, an nginx.conf, and a supervisord.conf, which is the layout of an application meant to sit behind your own reverse proxy rather than on someone else's infrastructure. Multi-user functionality is listed as a feature, with individual accounts and personalised tracking, so a shared instance for a household is an expected configuration rather than an afterthought. Authentication is handled through django-allauth, which the README describes as supporting OIDC and 100+ social providers including Google, GitHub and Discord.
The tracking model is deliberately granular. Each season of a tv show is tracked individually and episodes watched are counted. Per entry you can save a score, status, progress, repeats (rewatches, rereads), start and end dates, or a note. Yamtrack also keeps a history of each action on a media item: when it was added, when it was started, when it was started again. That history is the part most trackers drop, and it is what makes the statistics page meaningful rather than decorative.
Two features exist for the edges of a catalogue. Custom media entries cover niche media that the supported APIs cannot find, and personal lists let you group items for any purpose, with other members able to collaborate on the same list.
How the Django app, Celery workers and Redis fit together
The dependency list in pyproject.toml describes the architecture more clearly than the README does. Django 5.2 carries the web application. Celery with django-celery-beat and django-celery-results runs scheduled and background work. Redis appears twice: as the Celery broker through django-redis and redis[hiredis], and as a health check target via django-health-check[celery,redis]. Gunicorn serves the application, and supervisor runs the processes inside the container.
That split explains the Compose file. The yamtrack service declares depends_on: redis, and passes REDIS_URL=redis://redis:6379 to the application, while the redis service runs the redis:8-alpine image. The application container is ghcr.io/fuzzygrim/yamtrack, a prebuilt image rather than a local build. The only volume on the application service is ./db mounted at /yamtrack/db, and the Redis volume is a named volume called redis_data.
Background work is not incidental here. Periodic automatic imports from Trakt, Simkl, MyAnimeList, AniList and Kitsu need a scheduler. Notifications of upcoming releases go out through Apprise, which the README says supports Discord, Telegram, ntfy, Slack, email and others. Integrations with Jellyfin, Plex and Emby poll for newly watched media. All three are the kind of task that must not block a page request, which is why Celery is present.
Persistence has two documented options. The default Compose file uses SQLite, which the README calls enough for most personal installs. PostgreSQL is available through docker-compose.postgres.yml and the psycopg dependency. The trade-off is straightforward: SQLite keeps the backup story to a single directory, while PostgreSQL is the option to reach for when several accounts write concurrently or when the scheduled jobs grow. The README does not state a size at which you should switch, so the decision rests on your own concurrency, not on a documented threshold.
Installing Yamtrack with Docker and adding your first title
The README gives one install path: download the default docker-compose.yml file from the repository, update the environment values, and start Yamtrack. The Compose file defines two services and one named volume, so read it before starting anything.
services:
yamtrack:
container_name: yamtrack
image: ghcr.io/fuzzygrim/yamtrack
restart: unless-stopped
depends_on:
- redis
environment:
- TZ=Europe/Berlin
- SECRET=longstring
- REDIS_URL=redis://redis:6379
volumes:
- ./db:/yamtrack/db
ports:
- "8000:8000"The two values you must change are TZ and SECRET. SECRET is the placeholder string longstring in the default file; leaving it in place on an instance reachable from a network is the mistake to avoid. REDIS_URL points at the redis service by its Compose service name, so it works unchanged as long as you keep both services in the same file. The ./db bind mount is where the SQLite database lands, which makes that directory the thing to back up.
With the file saved, start the stack from the directory that contains it:
docker compose up -dThe README does not describe the first-run output. What you can expect from the configuration is that both containers start, the application listens on port 8000, and the web interface becomes reachable at that port on the host. If you want to try the interface before installing anything, the README offers a demo at yamtrack.fuzzygrim.com with the username demo and password demo.
Once you are in, the first real task is getting your existing history across. The README lists importers for Trakt, Simkl, MyAnimeList, AniList and Kitsu, with support for periodic automatic imports, so a first import can become a recurring sync rather than a one-off. For media the APIs do not cover, create a manual entry instead. The README also documents exporting everything to a CSV file and importing it back, which is the migration path if you later move between instances or database backends.
Where Yamtrack is the wrong tool
The README is silent on mobile clients. Nothing in the feature list describes an iOS or Android application, and the only external surface it documents is the iCalendar (.ics) URL for the calendar, which can be subscribed to in external applications. If your tracking habit happens on a phone, your options are the web interface in a browser or a calendar client, not a native app. That is a real constraint, not a detail.
Operational weight is the second issue. Running the default Compose file means running two containers, and the application image bundles nginx and supervisor alongside Gunicorn and Celery. That is a sensible packaging choice for a single image, but it means the container is doing more than serving HTTP, and the health check depends on Redis being reachable because django-health-check is configured with the celery and redis checks. A Redis outage is not a cosmetic problem here.
There is also a boundary in what the integrations do. Jellyfin, Plex and Emby integration is described as automatically tracking new media watched. That covers playback on those servers. It does not cover a cinema ticket, a borrowed book, or a game played on a console, so manual entry stays part of the workflow no matter how well the integrations are configured.
Finally, the README does not document rollback, nor does it describe what happens to your data when an upgrade goes wrong. The repository carries no upgrade guide that is referenced from the README, so the CSV export is the only documented way back out. Treat that export as part of the install, not as something to discover later.
Yamtrack compared with a hosted tracker such as Trakt
The obvious alternative is the service Yamtrack imports from. Trakt is a hosted tracker: your history lives on someone else's servers, the interface is maintained for you, and clients exist across platforms without you running anything. Yamtrack inverts each of those points. The data sits in a SQLite file or a PostgreSQL database that you host, the upgrade cadence is yours, and the access surface is a web interface on port 8000 plus an iCalendar URL.
The difference in approach shows up in the importers. Yamtrack does not treat Trakt as a competitor to be replaced once; it treats it as a source. The README lists Trakt, Simkl, MyAnimeList, AniList and Kitsu as import sources with support for periodic automatic imports, so the realistic pattern is to keep using a hosted service for discovery and let Yamtrack hold the consolidated record. That is a different posture from a tracker that asks you to abandon your old accounts.
Against a plain spreadsheet, the difference is the media model. A spreadsheet stores rows you type. Yamtrack stores seasons, episodes, repeats, and a per-action history, and it can create entries for media the APIs do not know about. The cost is that you now own a Django deployment with a Redis dependency and a scheduled job queue, which a spreadsheet never asks of you.
Licence, maintenance and what an upgrade costs you
Yamtrack is licensed under AGPL-3.0, as stated in the README badge and the repository LICENSE file. The practical consequence is the one that applies to any AGPL project: if you modify the code and let other people use it over a network, the licence's source-availability terms come into play. Running an unmodified copy for yourself is not the scenario the copyleft clause targets. This is a description of the licence identifier, not legal advice; read the LICENSE file if you plan to redistribute or host for others.
On maintenance, the repository is not archived, and the last push was on 2026-08-28. Releases are frequent and small: v0.26.1 on 2026-08-08, then v0.26.2 and v0.26.3 both on 2026-08-23, with pyproject.toml pinning the project version at 0.26.3. That release pattern, patch versions days apart, suggests fixes ship quickly after they are found.
The upgrade cost is mostly in the dependencies you do not control. The application image is pulled from ghcr.io/fuzzygrim/yamtrack, so upgrading means pulling a new tag and restarting the stack. Because Celery, django-celery-beat and django-celery-results are all present, a version change can involve database migrations for the task tables as well as the application tables, and the README does not document a rollback procedure. The mitigation available to you is the ./db directory for SQLite installs plus the CSV export described in the feature list. Both are worth exercising before an upgrade rather than after.
Editorial conclusion
Yamtrack suits people who already run a home server and want their media history in a database they control, especially if they use Jellyfin, Plex or Emby and want new plays recorded without manual entry. Skip it if you want a zero-maintenance hosted service, or if you expect native iOS and Android clients: the README lists no mobile app, and the calendar reaches external applications only through its iCalendar URL. Before committing, open the demo with the username and password demo, then check the Setup documentation for the PostgreSQL and reverse proxy path, because the repository README only shows the SQLite Compose file.
Frequently asked questions
What is Yamtrack?
Yamtrack is a self hosted media tracker for movies, tv shows, anime, manga, video games, books, comics, and board games, according to the README. It is a Django application distributed as a Docker image, with SQLite as the default database and PostgreSQL as an option.
How do I install Yamtrack with Docker?
The README says to download the default docker-compose.yml file from the repository, update the environment values, and run docker compose up -d. The default Compose file starts the yamtrack container from ghcr.io/fuzzygrim/yamtrack together with a redis service, and exposes port 8000.
Does Yamtrack have an iOS or Android app?
The README does not describe a native iOS or Android application. The only external access it documents is the calendar, which can be subscribed to in external applications using an iCalendar (.ics) URL.
How do I import my existing history into Yamtrack?
The README lists importers for Trakt, Simkl, MyAnimeList, AniList and Kitsu, with support for periodic automatic imports. It also documents exporting all tracked media to a CSV file and importing it back.
Does Yamtrack integrate with Jellyfin, Plex and Emby?
Yes. The README lists integration with Jellyfin, Plex and Emby to automatically track new media watched, alongside notifications of upcoming releases sent through Apprise.
Official sources
Add this badge to your README
If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.
[](https://hysenlabs.com/projects/fuzzygrim-yamtrack)