Self-hosted service
FuzzyGrim/Yamtrack avatar
FuzzyGrim/Yamtrack

Yamtrack: a self hosted tracker for eight media types in one Django app

A self hosted media tracker.

3,563 stars313 forksPythonAGPL-3.0

At a glance

What is it?
Yamtrack is an AGPL-3.0 Django application that tracks movies, TV, anime, manga, games, books, comics and board games, with Docker Compose as the intended deployment path. Its value is breadth and ownership of the database; its cost is that you run and upgrade the stack yourself.
Who is it for?
Adopt Yamtrack if you want one database for film, television, anime, print and games, and you are willing to run a Django container with either SQLite or PostgreSQL. Do not adopt it if you need a hosted service with no operational work, or if your library is small enough that a single-purpose client already covers it.
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 last received commits 19 days ago.
What is it written in?
Mainly Python, according to GitHub's language statistics.

Answers come from the project's GitHub data, last synced on September 15, 2026, and from our analysis. They are not legal advice.

DEEP OPEN-SOURCE ANALYSIS

The problem Yamtrack solves: one ledger for media that other trackers split apart

Most tracking tools pick a lane. Film and television apps do not handle manga volumes; anime trackers do not handle board games; game libraries do not handle books. If your consumption is spread across those categories, you either run several accounts or you keep a spreadsheet. Yamtrack's README lists eight tracked types in a single application: movies, tv shows, anime, manga, video games, books, comics, and board games. That is the whole pitch, and it is a narrower claim than it first appears. The project is not trying to be a recommendation engine or a social network. It is a record of what you have watched, read or played, plus the dates and scores attached to those events.

The audience follows from that. Someone who already runs a home server, is comfortable with Docker Compose, and wants their watch history in a database they control. The README also documents multi-user functionality, with individual accounts and personalized tracking, so a household can share one instance. Nothing in the material suggests a hosted tier or a paid plan; the demo at yamtrack.fuzzygrim.com with the username and password both set to demo is the only public instance mentioned. If you want a service where someone else handles backups and uptime, this is the wrong shape of project.

How the pieces fit: Django, a media table, and per-action history

The repository topics name the stack directly: django, docker, docker-compose, media-tracker, postgresql, sqlite, tailwindcss. So this is a server-rendered Django application, not a JavaScript single-page app talking to a separate API, and the front end is built with Tailwind CSS. The database is either SQLite or PostgreSQL depending on the Compose file you use.

The data model visible from the feature list has a few distinct layers. There is the media entry itself, which can come from a supported API or be created by hand for niche items that the APIs do not return. There is your relationship to that entry: score, status, progress, repeats, start and end dates, and a free-text note. There is a history layer, described in the README as a tracking history with each action on a media, recording when you added it, when you started it, when you started watching it again. And there is a list layer, separate from tracking, where you group media for any purpose and can add other members to collaborate.

Television gets its own sub-structure. Seasons are tracked individually and episodes are tracked as watched, which is the difference between marking a show as finished and knowing that you stopped three episodes into season four. That granularity is the reason the season and episode screenshots exist as separate entries in the README's screenshot table.

Two integration paths feed the database from outside. The first is media server integration with Jellyfin, Plex and Emby, described as automatically tracking new media watched. The second is the importers: Trakt, Simkl, MyAnimeList, AniList and Kitsu, with support for periodic automatic imports. The .ics calendar URL and Apprise notifications are output paths, pushing upcoming releases out to a calendar client or to Discord, Telegram, ntfy, Slack or email.

Getting it running: one Compose file, then environment values

The installation instructions in the README are deliberately short. Download the default docker-compose.yml from the repository, update the environment values, then run:

docker compose up -d

The default Compose file uses SQLite, which the README says is enough for most personal installs. PostgreSQL is the alternative, and the README points to the setup documentation at fuzzygrim.github.io/Yamtrack/release/setup/ for full SQLite, PostgreSQL and reverse proxy instructions. That is where the actual environment keys live; the README itself does not enumerate them, so I cannot tell you from this material which variables control OIDC, Apprise or the media server connections. Treat the setup page as required reading rather than optional.

Development is a separate path, documented at fuzzygrim.github.io/Yamtrack/release/development/ rather than in the README. If you intend to run from source instead of the published image, that page is your entry point.

The release cadence is worth noting because it affects how you deploy. The three most recent releases listed are v0.26.3 and v0.26.2, both dated 2026-08-23, and v0.26.1 dated 2026-08-08. Two patch releases on the same day suggests fixes are shipped quickly after a problem is found. It also means pulling latest is not a stable target; pinning a version tag in your Compose file is the only way to control when the application changes underneath you.

Where Yamtrack gets awkward: imports, API gaps and the AGPL boundary

The importers are the feature most likely to disappoint on first contact. Importing from Trakt, Simkl, MyAnimeList, AniList or Kitsu means mapping one service's model onto Yamtrack's, and the two will not line up exactly. The README promises import and periodic automatic imports, but it does not describe field-level fidelity, and I have not run an import to check. If your history includes custom lists, half-star ratings or rewatch counts that the source service stores in its own way, verify the result before you delete anything at the source. Export to CSV and re-import is documented as a round trip, which gives you a way to inspect what survived.

Custom media entries are the documented workaround for anything the supported APIs cannot find. That is a real admission: coverage is not complete, and for obscure print, regional releases or self-published work you will be typing metadata by hand.

The licence is AGPL-3.0. For a self hosted personal instance this changes nothing practical. It matters if you modify Yamtrack and expose it to other users over a network, because the AGPL's network clause is broader than the GPL's. I am not giving legal advice, and the exact scope of your obligations depends on your situation; the point is that this is not a permissive licence you can ignore if you plan to build on the code.

One more limitation that follows from the architecture: this is a Python web application with a database, which means upgrades are migrations. The README does not describe a downgrade path, so a version that changes the schema is effectively one-way unless you have a database backup from before the upgrade.

How it differs from a hosted tracker like Trakt

The obvious comparison is Trakt, which is also one of Yamtrack's import sources. The difference is not features, it is who holds the data and who pays for the server. Trakt is a hosted service with an account, a web interface and an API; you get its uptime and its roadmap decisions, and your history lives in its database. Yamtrack is the opposite arrangement. You supply the machine, the container runtime and the backups, and in exchange the data sits in a SQLite file or a PostgreSQL database that you can copy, query and restore without asking anyone.

That trade has a second edge. A hosted service handles the metadata problem centrally: when a show is renamed or a game gets a new edition, the service updates its records. Yamtrack depends on the APIs it integrates with, and the README's custom media entry feature exists precisely because those APIs do not cover everything. So self hosting does not remove metadata maintenance; it moves it to you.

The media server integrations are where the two approaches converge. Jellyfin, Plex and Emby integration means playback on your own server can mark items watched automatically, which is the same convenience a hosted tracker offers through its own clients. The difference is that the trigger is your media server, not a third-party app.

Upgrade cost and what to check before you commit

Running Yamtrack has two recurring costs. The first is the upgrade itself: pulling a new image and restarting the container, with any database migration that implies. Given the release pattern of two patches on one day, you will face this choice often. The second is metadata drift, where an entry stops matching its source and needs manual correction through the custom entry feature.

Both are manageable if you treat the database as the asset. Back up the SQLite file or the PostgreSQL dump before every version bump, and pin the image tag rather than tracking latest. The README's CSV export gives you a second, application-level backup that survives a schema change, and it is the only documented way to get your data back out in bulk.

What to verify first, in order. Confirm the demo instance behaves the way you expect before deploying anything. Then check that your current service's export format imports cleanly, since that is the migration risk with the least documentation. Then confirm the .ics calendar URL resolves from the client you actually use, and that an Apprise notification reaches one of your channels. If all four pass, the remaining work is routine container operation. If the import step fails, you are looking at manual re-entry, and that is the point at which the breadth of eight media types stops being worth the effort.

Editorial conclusion

Adopt Yamtrack if you want one database for film, television, anime, print and games, and you are willing to run a Django container with either SQLite or PostgreSQL. Do not adopt it if you need a hosted service with no operational work, or if your library is small enough that a single-purpose client already covers it. Before committing, verify two things: that the importers for your current service (Trakt, Simkl, MyAnimeList, AniList or Kitsu) produce the fields you care about, and that the .ics calendar URL and Apprise notification path work from your network.

Official sources

  1. FuzzyGrim/Yamtrack on GitHub
  2. Issues
  3. License: AGPL-3.0
  4. README
  5. Releases
Community notes

Community notes