This project adds a two-way-sync between trakt.tv and Plex Media Server. It requires a trakt.tv account but no Plex premium and no Trakt VIP subscriptions, unlike the Plex app provided by Trakt.
Originally created by @Taxel, now maintained by contributors.
Note: The PyTrakt API keys are not stored securely, so if you do not want to have a file containing those on your harddrive, you can not use this project.
Looking for a way to contribute?
The script is known to work with Python 3.9-3.13 versions.
Installation with pipx.
pipx install PlexTraktSync
or, to install specific version:
pipx install PlexTraktSync==0.15.2 --force
and to upgrade:
plextraktsync self-update
which just calls pipx
with:
pipx upgrade PlexTraktSync
to run:
plextraktsync sync
NOTE: pipx
install will use OS specific paths for Config, Logs, Cache, see
platformdirs documentation for details or check output of info command.
You can setup docker compose file like this:
version: "2"
services:
plextraktsync:
image: ghcr.io/taxel/plextraktsync
command: sync
container_name: plextraktsync
restart: on-failure:2
volumes:
- ./config:/app/config
environment:
- PUID=1000
- PGID=1000
- TZ=Europe/Tallinn
You can use specific version 0.25.16
:
image: ghcr.io/taxel/plextraktsync:0.25.16
or latest 0.25.x version:
image: ghcr.io/taxel/plextraktsync:0.25
Note: main
is development version and reporting bugs against development versions are not supported.
To run sync:
docker compose run --rm plextraktsync sync
The container will stop after the sync is completed. Read Setup section to run it automatically at set intervals.
This is to install development version to test if pull request would fix some problem.
See contributing guide how to install code from pull request.
NOTE: This installation method is not supported. It's documented solely by user contribution.
.zip
release from https://github.com/Taxel/PlexTraktSync/tagssetup.bat
to install requirements and create optional shortcuts and
routines (requires Windows 7sp1 - 11).NOTE: This installation method is not supported. It's documented solely by user contribution.
Option 1 for container creation: Create a manual Unraid container of PlexTraktSync:
ghcr.io/taxel/plextraktsync:latest
(or whatever tag you want).-it
for interactive mode.plextraktsync
to start the credential process described above.Option 2 for container creation: Utilize the "Community Apps" Unraid Plugin.
Once installed (or if already installed):
Schedule (cron) the container to start at given intervals to process the sync
Once installed (or if already installed):
#!/bin/bash
# Check if the container is running
if [ "$(docker ps -q -f name=PlexTraktSync)" ]; then
echo "PlexTraktSync container is already running."
else
echo "PlexTraktSync container is not running. Starting it now..."
docker start PlexTraktSync
fi
# Run the sync command inside the container
docker exec PlexTraktSync plextraktsync sync
NOTE: This installation method is not supported. You will not get support if you use this installation method.
Installing from GitHub is considered developer mode, and it's documented in CONTRIBUTING.md.
You will need to create a Trakt API app if you do not already have one:
urn:ietf:wg:oauth:2.0:oob
as the redirect urlRun plextraktsync login
, the script will ask for missing credentials
Note To setup the credentials in the Docker Container, refer to the Run the Docker Container section
At first run you will be asked to setup Trakt and Plex access.
Follow the instructions, your credentials and API keys will be stored in
.env
and .pytrakt.json
files. Plex URL and token is stored in servers.yml
.
If you have 2 Factor Authentication enabled on Plex, input the code when prompted. If you don't have 2FA enabled, just leave the prompt blank and press Enter.
Cronjobs can be optionally used on Linux or macOS to run the script at set intervals.
For example, to run this script in a cronjob every two hours:
$ crontab -e
0 */2 * * * $HOME/.local/bin/plextraktsync sync
which plextraktsync
command to locate your system's plextraktsync executable file and update it accordingly.Instead of cron, a docker scheduler like Ofelia can also be used to run the script at set intervals.
A docker compose example with a 6h interval:
version: "2"
services:
scheduler:
image: mcuadros/ofelia:latest
container_name: scheduler
depends_on:
- plextraktsync
command: daemon --docker
volumes:
- /var/run/docker.sock:/var/run/docker.sock:ro
labels:
ofelia.job-run.plextraktsync.schedule: "@every 6h"
ofelia.job-run.plextraktsync.container: "plextraktsync"
plextraktsync:
image: ghcr.io/taxel/plextraktsync:latest
container_name: plextraktsync
command: sync
volumes:
- ./config:/app/config
To disable parts of the functionality of this software, look no further than
config.yml
. At first run, the script will create config.yml
based on
config.default.yml
. If you want to customize settings before first run (eg.
you don't want full sync) you can copy and edit config.yml
before launching
the script. Here, in the sync section, you can disable the following things
by setting them from true
to false
in a text editor:
The first execution of the script will (depending on your PMS library size) take a long time. After that, movie details and Trakt lists are cached, so it should run a lot quicker the second time. This does mean, however, that Trakt lists are not updated dynamically (which is fine for lists like "2018 Academy Award Nominees" but might not be ideal for lists that are updated often). Here are the execution times on my Plex server: First run - 1228 seconds, second run - 111 seconds
You can view sync progress in the plextraktsync.log
file which will be
created.
You can use --edit
or --locate
flags to config
command to open config
file in editor or in file browser.
By default, all libraries are processed. You can disable libraries by name by
changing excluded-libraries
in config.yml
.
You can also set excluded-libraries
per server in servers.yml
:
servers:
Example1:
token: ~
urls:
- http://localhost:32400
config:
excluded-libraries:
- "Family Movies"
Additionally, you can list only libraries to be processed, in this case global
excluded-libraries
will not be used for this server.
servers:
Example1:
token: ~
urls:
- http://localhost:32400
config:
libraries:
- "Movies"
- "TV Shows"
you can see the final list of libraries with info command:
$ plextraktsync --server=Example1 info
Enabled 2 libraries in Plex Server:
- 1: Movies
- 2: TV Shows
If you want to specify your config per server you can do so inside of
servers.yml
. Within the config
part of the server configuration you can
specify how that specific server should work.
servers:
Example1:
token: ~
urls:
- http://localhost:32400
config:
sync:
plex_to_trakt:
collection: true
trakt_to_plex:
liked_lists: false
Using sync
in a server config overrides the global sync-config in
config.yml
.
This can also be used to have different configs between different libraries. To be able to do this you specify the number of servers you need (most likely equal to the number of different config setups you need). For example:
servers:
Example1:
token: ~
urls:
- http://localhost:32400
config:
libraries:
- "Movies"
sync:
plex_to_trakt:
ratings: true
watched_status: true
trakt_to_plex:
ratings: true
watched_status: true
Example2:
token: ~
urls:
- http://localhost:32400
config:
libraries:
- "TV Shows"
sync:
plex_to_trakt:
ratings: true
watched_status: false
trakt_to_plex:
ratings: true
watched_status: false
The above config would make it so that the "Movies" library syncs both ratings
and watched status, while the "TV Shows" library only syncs ratings. To then
run the sync you need to specify --server Example1
or --server Example2
to
run the sync for that specific server.
Running the sync command without --server
will use default server from .env
If you want to run these jobs using ofelia
, you can do so by running
something similar to this in your docker-compose.yml
:
services:
plextraktsync:
image: ghcr.io/taxel/plextraktsync
command: sync
container_name: plextraktsync
profiles: ["schedule"]
volumes:
- /configs/mediarr/plextraktsync:/app/config
environment:
- PUID=1000
- PGID=1000
depends_on:
- plex
scheduler:
image: mcuadros/ofelia:latest
container_name: scheduler
command: daemon --docker
restart: unless-stopped
volumes:
- /var/run/docker.sock:/var/run/docker.sock:ro
labels:
ofelia.job-run.plextraktsync.schedule: "0 6,18 * * *"
ofelia.job-run.plextraktsync.container: "plextraktsync"
ofelia.job-run.plextraktsync.command: "--server 'Example1' sync"
ofelia.job-run.plextraktsync2.schedule: "0 12,0 * * *"
ofelia.job-run.plextraktsync2.container: "plextraktsync"
ofelia.job-run.plextraktsync2.command: "--server 'Example2' sync"
If you are running only one PlexTraktSync container, you need to make sure that the two jobs Ofelia jobs don't run at the same time. Ofelia skips scheduling a new job run if the previous job is still running.
Depending on how long it takes for the job to run on your server you might have to keep the schedule of the two jobs seperated with a few minutes or a few hours. If you have two different PlexTraktSync containers in your docker compose, you can run them at the same time.
The above config means that a job is running every 6 hours, alternating between
the two "servers". The PlexTraktSync container also has a docker compose
profile called "schedule" which means that it won't run automatically when you
run for example docker compose up
.
The logging level by default is INFO
. This can be changed to DEBUG by editing
the "debug" variable in config.yml
to true
.
By default the logs will append, if you wish to maintain the log of only your
last run then edit the "append" variable in config.yml
to false
.
Run plextraktsync --help
to see available commands.
Run plextraktsync COMMAND --help
to see help for COMMAND
.
$ plextraktsync --help
Usage: plextraktsync [OPTIONS] COMMAND [ARGS]...
Plex-Trakt-Sync is a two-way-sync between trakt.tv and Plex Media Server
Options:
--version Print version and exit
--no-cache Disable cache in for Trakt HTTP requests
--no-progressbar Disable progressbar
--batch-delay INTEGER Time in seconds between each collection batch submit
to Trakt [default: 5]
--server NAME Plex Server name from servers.yml
--help Show this message and exit.
Commands:
bug-report Create a pre-populated GitHub issue with information...
cache Manage and analyze Requests Cache.
clear-collections Clear Movies and Shows collections in Trakt
config Print user config for debugging and bug reports.
download Downloads movie or subtitles to a local directory
imdb-import Import IMDB ratings from CSV file.
info Print application and environment version info
inspect Inspect details of an object
login Log in to Plex and Trakt if needed
plex-login Log in to Plex Account to obtain Access Token.
self-update Update PlexTraktSync to the latest version using pipx
sync Perform sync between Plex and Trakt
trakt-login Log in to Trakt Account to obtain Access Token.
unmatched List media that has no match in Trakt or Plex
watch Listen to events from Plex
watched-shows Print a table of watched shows
You can contribute yourself missing documentation.
The sync
subcommand supports --sync=shows
and --sync=movies
options,
so you can sync only specific library types.
Or only watchlist: --sync=watchlist
.
➔ plextraktsync sync --help
Usage: plextraktsync sync [OPTIONS]
Perform sync between Plex and Trakt
Options:
--sync [all|movies|shows|watchlist]
Specify what to sync [default: all]
--help Show this message and exit.
You can use unmatched
command to scan your library and display unmatched
movies.
Support for unmatched shows is not yet implemented.
plextraktsync unmatched
The info command can be used to print package versions, account information, locations of Cache, Config and Logs directories
$ plextraktsync info
PlexTraktSync Version: 0.16.0
Python Version: 3.10.0 (default, Oct 6 2021, 01:11:32) [Clang 13.0.0 (clang-1300.0.29.3)]
Plex API Version: 4.7.2
Trakt API Version: 3.2.1
Cache Dir: /Users/glen/Library/Caches/PlexTraktSync
Config Dir: /Users/glen/Library/Application Support/PlexTraktSync
Log Dir: /Users/glen/Library/Logs/PlexTraktSync
Plex username: nobody
Trakt username: nobody
Plex Server version: 1.24.3.5033-757abe6b4, updated at: 2021-02-21 17:00:00
Server has 2 libraries: ['Movies', 'TV Shows']
Inspect command is used to get info about Plex Media Server items, which is useful when debugging problems and reporting issues.
123
plextraktsync inspect 123
plextraktsync inspect "https://app.plex.tv/desktop/#!/server/53aff62c4bb6027c1ada814d417e83ccdf4d5045/details?key=/library/metadata/123"
To avoid problems with various shells, put the value in double quotes.
You can use the watch
command to listen to events from Plex Media Server
and scrobble plays.
What is scrobbling?
Scrobbling simply means automatically tracking what you’re watching. Instead of checking in from your phone of the website, this command runs in the background and automatically scrobbles back to Trakt while you enjoy watching your media - Plex [email protected]
To restrict scrobbling to your user only (recommended), set the following
in your config.yml
:
watch:
username_filter: true
To run watch
command:
plextraktsync watch
or
docker compose run --rm plextraktsync watch
or add command: watch
to docker compose file, and docker compose up -d plextraktsync
to start the container detached:
version: "2"
services:
plextraktsync:
image: ghcr.io/taxel/plextraktsync
volumes:
- ./config:/app/config
command: watch
Create a systemd unit so that it scrobbles automatically in the background:
[Unit]
Description=PlexTraktSync watch daemon
After=network-online.target
[Service]
ExecStart=plextraktsync watch
Restart=on-failure
RestartSec=10
User=user
Group=user
[Install]
WantedBy=multi-user.target
Note, depending on your install method you may need to set your ExecStart command as follows:
ExecStart=/path/to/plextraktsync/plextraktsync.sh watch
Following that you will need to enable the service:
sudo systemctl daemon-reload
sudo systemctl start PlexTraktSync.service
sudo systemctl enable PlexTraktSync.service
You can also run as systemd user service.
This walkthough allows to use different servers with the same configuration.
This assumes plextraktsync
is installed with pipx
for your user.
# [email protected]
[Unit]
Description=PlexTraktSync watch daemon
After=network-online.target
[Service]
ExecSearchPath=%h/.local/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
ExecStart=plextraktsync watch --server=%i
Restart=on-failure
RestartSec=10
[Install]
WantedBy=default.target
Install the service template file:
root
: /etc/xdg/systemd/user/[email protected]
for all users~/.config/systemd/user/[email protected]
for your user onlyNext, you need to reload systemd:
root
: sudo systemctl daemon-reload
systemctl --user daemon-reload
Now create instances based on server names from servers.yml
, in this example SERVER_NAME
.
systemctl --user start "plextraktsync@SERVER_NAME.service"
systemctl --user status "plextraktsync@SERVER_NAME.service"
for complete logs, you can use journalctl
(add -f
to follow logs):
journalctl --user -u "plextraktsync@SERVER_NAME.service"
If all works, enable it for auto-start on host reboot
systemctl --user enable "plextraktsync@SERVER_NAME.service"
For systemd --user session to start without having to log in you need to enable systemd-linger:
loginctl enable-linger
Plex Movie
and Plex TV Series
metadata agents improves
script compatibility (for matching or for watchlist).
It is recommended to migrate to the new Plex TV Series agent.Check your Plex episodes ordering compared to Trakt ordering. If episodes are in a different order, it should not be a problem because they are identified with ids. But if a season or an episode is missing on Trakt (and tmdb) it can't be synced. You can fix it by adding the missing episodes or edit metadata (eg. missing tvdb or imdb ids) on tmdb or report a metadata issue on Trakt (answers). It's free for anyone to sign up and edit info at tmdb. Trakt will update from tmdb data.
Make sure you use good practices about Plex agent and files organization as stated above. Check if episodes are not missing on Trakt as explained in previous answer, and check if external ids are populated on tmdb.
Season 0 folder must only contain episodes belonging to season 0, also named specials. Trailers, deleted scenes, featurettes, interviews,... must be stored in a separate Extra folder (not in season 0) according to Plex rules. Keep in mind that seasons 0 aren't really official so datasources (tmdb, imdb and tvdb) sometimes don't correspond. Check season 0 of shows on trakt.tv to identify those special episodes. Use tmdb as Plex source as much as you can.
The easiest way is to use containers with custom config folder for each user: Multi-User docker-compose.
Yes using docker, check Discussions page.
Check Discussions, maybe someone already asked and found the answer.