Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?
Sync Plex playlists to shared users.
#!/usr/bin/env python
# -*- coding: utf-8 -*-
#
# Description: Sync Plex playlists to shared users.
# Author: /u/SwiftPanda16
# Requires: plexapi, requests, xmltodict
import requests
import xmltodict
from plexapi.server import PlexServer
### EDIT SETTINGS ###
PLEX_URL = 'http://localhost:32400'
PLEX_TOKEN = 'xxxxxxxxxx'
PLAYLISTS = ['Playlist 1', 'Playlist 2', 'Playlist 3'] # List of playlists to sync
USERS = ['User 1', 'User 2', 'User 3'] # List of users to sync the playlists to
## CODE BELOW ##
def fetch_plex_api(path='', method='GET', plextv=False, **kwargs):
"""Fetches data from the Plex API"""
url = 'https://plex.tv' if plextv else PLEX_URL.rstrip('/')
headers = {'X-Plex-Token': PLEX_TOKEN,
'Accept': 'application/json'}
params = {}
if kwargs:
params.update(kwargs)
try:
if method.upper() == 'GET':
r = requests.get(url + path,
headers=headers, params=params, verify=False)
elif method.upper() == 'POST':
r = requests.post(url + path,
headers=headers, params=params, verify=False)
elif method.upper() == 'PUT':
r = requests.put(url + path,
headers=headers, params=params, verify=False)
elif method.upper() == 'DELETE':
r = requests.delete(url + path,
headers=headers, params=params, verify=False)
else:
print("Invalid request method provided: {method}".format(method=method))
return
if r and len(r.content):
if 'application/json' in r.headers['Content-Type']:
return r.json()
elif 'application/xml' in r.headers['Content-Type']:
return xmltodict.parse(r.content)
else:
return r.content
else:
return r.content
except Exception as e:
print("Error fetching from Plex API: {err}".format(err=e))
def get_user_tokens(server_id):
api_users = fetch_plex_api('/api/users', plextv=True)
api_shared_servers = fetch_plex_api('/api/servers/{server_id}/shared_servers'.format(server_id=server_id), plextv=True)
user_ids = {user['@id']: user.get('@username', user.get('@title')) for user in api_users['MediaContainer']['User']}
users = {user_ids[user['@userID']]: user['@accessToken'] for user in api_shared_servers['MediaContainer']['SharedServer']}
return users
def main():
"""Main script"""
plex = PlexServer(PLEX_URL, PLEX_TOKEN)
plex_users = get_user_tokens(plex.machineIdentifier)
plex_playlists = {playlist.title: playlist.items() for playlist in plex.playlists()}
for playlist in PLAYLISTS:
playlist_items = plex_playlists.get(playlist)
if not playlist_items:
print("Playlist '{playlist}' not found on the server. Skipping.".format(playlist=playlist))
continue
print("Cloning the '{title}' playlist...".format(title=playlist))
for user in USERS:
user_token = plex_users.get(user)
if not user_token:
print("...User '{user}' not found in shared users. Skipping.".format(user=user))
continue
user_plex = PlexServer(PLEX_URL, user_token)
# Delete the old playlist
try:
user_playlist = user_plex.playlist(playlist)
user_playlist.delete()
except:
pass
# Create a new playlist
user_plex.createPlaylist(playlist, playlist_items)
print("...Created playlist for '{user}'.".format(user=user))
return
if __name__ == "__main__":
main()
print("Done.")
@martinconroy
Copy link

martinconroy commented Jan 12, 2018

Hi,
I'm getting the below error when running this script now. Any ideas why?

image

@AngellusMortis
Copy link

AngellusMortis commented Jun 6, 2018

@johma74 Try using Python 3. I do not see any issues with playlists with Unicode in them on Python 3.

Python 2 is outdated (with support being dropped in less than 2 years) and does not support Unicode as well as Python 3 does.

@pbrink231
Copy link

pbrink231 commented Aug 6, 2018

@JonnyWong16
I want to thank you for this. Got me going on how to put in what I wanted to do. Along with your other script.
https://github.com/pbrink231/plex_top_playlists

@BinsonBuzz
Copy link

BinsonBuzz commented Aug 20, 2018

Sorry if this is a dumb question but I'm not coding literate. I get this error:

Traceback (most recent call last):
File "/tmp/user.scripts/tmpScripts/plex - sync playlists/script", line 9, in 

import requests

ImportError: No module named requests

Where is the script supposed to be importing requests from?

Thanks

@krowvin
Copy link

krowvin commented Oct 16, 2018

@seanvree

I keep getting this error:
users = {user_ids[user['@userid']]: user['@accesstoken'] for user in api_shared_servers['MediaContainer']['SharedServer']}
KeyError: u'10033576'

Any ideas?

Sean, I was having the same issue.

I was able to look into it and I figured it out partially. If I print out each user(Put the code below on line 72) with this snippet:

x=0
for user in api_shared_servers['MediaContainer']['SharedServer']:
    print x, user
    x+=1

I can see that one of my usersthe admin account has no (u'@username', u''), (u'@email', u''), and the @userid ends up not being found for that user. ~~I am not sure where this user exists/came from as I do NOT have the guest account enabled.~~If you print out the object on line 69 user_ids, you can see the guest account. This is a really old Plex database that I have transferred around for several years. So it's possible it was left there. Edit: I'm not sure if it's intended by the plexapi library to not return the admin user. Doing the fix I have below lets you sync your admin playlist to someone else, but if they make an update you can't add your name to the list to have it sync to you. So their additions get overwritten.

I'm able to hotfix it, by changing the list to start from 1, instead of 0. (My mystery userThe admin is at index 0, I think). So I would use the code above to confirm yours is at 0 too. Then change line 70 to this:
users = {user_ids[user['@userID']]: user['@accessToken'] for user in api_shared_servers['MediaContainer']['SharedServer'][1:]}

This will only keep working if that user at index 0 remains as my mystery useradmin account.

Edit: Whelp, found out that mystery user is my account. Not sure why it shows up as not having a username or email.

@krowvin
Copy link

krowvin commented Oct 16, 2018

ImportError: No module named requests

Where is the script supposed to be importing requests from?

Thanks

Hey there, @BinsonBuzz!
If you are on windows, open a command prompt and try typing
python -m pip install requests

If you are on linux/unix you can try this:
pip install requests

edit: You asked where from, requests is not part of the standard library.

Pip is a popular package management system for python that you can use to help you download the requests library.

@lineber
Copy link

lineber commented Dec 24, 2018

Doesn't work for me. I get the same error that other's have reported:

/usr/lib/python2.7/site-packages/urllib3/connectionpool.py:847: InsecureRequestWarning: Unverified HTTPS request is being made. Adding certificate verification is strongly advised. See: https://urllib3.readthedocs.io/en/latest/advanced-usage.html#ssl-warnings
InsecureRequestWarning)
/usr/lib/python2.7/site-packages/urllib3/connectionpool.py:847: InsecureRequestWarning: Unverified HTTPS request is being made. Adding certificate verification is strongly advised. See: https://urllib3.readthedocs.io/en/latest/advanced-usage.html#ssl-warnings
InsecureRequestWarning)
Traceback (most recent call last):
File "./sync_playlists_to_all_users.py", line 108, in
main()
File "./sync_playlists_to_all_users.py", line 74, in main
plex_users = get_user_tokens(plex.machineIdentifier)
File "./sync_playlists_to_all_users.py", line 67, in get_user_tokens
user_ids = {user['@id']: user.get('@username', user.get('@title')) for user in api_users['MediaContainer']['User']}
TypeError: string indices must be integers, not str

@lineber
Copy link

lineber commented Dec 25, 2018

I think I figured it out. The message was because for some reason this script will only transfer the playlists from the main account (server owner) to all user accounts. Playlist from the user accounts dont get shared.

 PLEX_TOKEN = 'xxxxxxxxxxxxx' # main account
 # PLEX_TOKEN = 'yyyyyyyyyyyyy' # user account

I switched back and forth a few times and don't understand why it doesn't work from the regular users.
When running the plexapi playlist example it works no matter who is the user:

for playlist in plex.playlists():
    print(playlist.title)

@nauip
Copy link

nauip commented Mar 25, 2019

I have a crazy huge MCU Chronological playlist that includes movies, TV episodes and shorts. The script only copied the movie items in the playlists, unfortunately.

@bwittgen
Copy link

bwittgen commented Aug 4, 2019

Every time this script is run it is duplicating the old playlists and not deleting the old ones for me. Anyone else?

@codylegger
Copy link

codylegger commented Sep 14, 2019

Has anyone found a way to copy other users playlist to the main admin account on the server? One of my users has made an epic playlist that I want to copy to my account so that I can distribute with the rest of the family.

@codylegger
Copy link

codylegger commented Sep 14, 2019

Also, is it possible to copy the text in the description field to all users?

@tdixler
Copy link

tdixler commented May 24, 2020

Does this allow you to sync audio playlists between users in Plex or only video playlists?

@murat3
Copy link

murat3 commented Dec 2, 2020

@timothymiller
Copy link

timothymiller commented Jan 11, 2021

@brettwatson77
Copy link

brettwatson77 commented Apr 30, 2021

I had this working on my Mac..

I moved my Plex server to a new Mac

I updated the token but now I get this error

Warning (from warnings module):
File "/Library/Frameworks/Python.framework/Versions/3.9/lib/python3.9/site-packages/urllib3/connectionpool.py", line 1013
warnings.warn(
InsecureRequestWarning: Unverified HTTPS request is being made to host 'plex.tv'. Adding certificate verification is strongly advised. See: https://urllib3.readthedocs.io/en/latest/advanced-usage.html#ssl-warnings

Warning (from warnings module):
File "/Library/Frameworks/Python.framework/Versions/3.9/lib/python3.9/site-packages/urllib3/connectionpool.py", line 1013
warnings.warn(
InsecureRequestWarning: Unverified HTTPS request is being made to host 'plex.tv'. Adding certificate verification is strongly advised. See: https://urllib3.readthedocs.io/en/latest/advanced-usage.html#ssl-warnings
Traceback (most recent call last):
File "/Users/brettwatson/Desktop/sync_playlists_to_all_users.py", line 113, in
main()
File "/Users/brettwatson/Desktop/sync_playlists_to_all_users.py", line 80, in main
PLAYLISTS = [x.title for x in plex.playlists()]
File "/Users/brettwatson/Desktop/sync_playlists_to_all_users.py", line 80, in
PLAYLISTS = [x.title for x in plex.playlists()]
AttributeError: 'Tag' object has no attribute 'title'

any ideas?

@brettwatson77
Copy link

brettwatson77 commented May 1, 2021

I worked it out the new plexapi kills the script revert to the older plexapi and it works

@shinedou
Copy link

shinedou commented Sep 16, 2021

I worked it out the new plexapi kills the script revert to the older plexapi and it works

@brettwatson77 What version of plexapi did you have to revert to?

@brettwatson77
Copy link

brettwatson77 commented Sep 16, 2021

@majorgear
Copy link

majorgear commented Nov 16, 2021

I had to revert to # PlexAPI Settings PROJECT = 'PlexAPI' VERSION = ‘4.1.2' And then the script worked again.. It its still working for me with this version of the Plex api Has the script been updated to work with the new plex api? B

On 17 Sep 2021, at 8:47 am, shinedou @.***> wrote: @shinedou commented on this gist. I worked it out the new plexapi kills the script revert to the older plexapi and it works What version of plexapi did you have to revert to? — You are receiving this because you commented. Reply to this email directly, view it on GitHub https://gist.github.com/2607abf0e3431b6f133861bbe1bb694e#gistcomment-3895839, or unsubscribe https://github.com/notifications/unsubscribe-auth/ARMFWJVBYKZTLCZGJNZLBJ3UCJXZXANCNFSM4H5X6J5A. Triage notifications on the go with GitHub Mobile for iOS https://apps.apple.com/app/apple-store/id1477376905?ct=notification-email&mt=8&pt=524675 or Android https://play.google.com/store/apps/details?id=com.github.android&referrer=utm_campaign%3Dnotification-email%26utm_medium%3Demail%26utm_source%3Dgithub.

I switched to 4.1.2 , still doesn't work

Is the what the settings should look like?
PLEX_URL = 'http://localhost:32400'
PLEX_TOKEN = 'removed'
PLAYLISTS = [ 'Treadmill'] # List of playlists to sync
USERS = [ 'john.smith' ] # List of users to sync the playlists to

john.smith is a managed user, token is for the Admin account.

Environment
Python = v3.9.7

pip freeze output:
charset-normalizer==2.0.7
idna==3.3
PlexAPI==4.1.2
requests==2.26.0
urllib3==1.26.7
XML2Dict==0.2.2
xmltodict==0.12.0

Error message
Traceback (most recent call last): File "/Users/jgooch/repos/sync_playlists/sync_playlists.py", line 112, in <module> main() File "/Users/jgooch/repos/sync_playlists/sync_playlists.py", line 78, in main plex_users = get_user_tokens(plex.machineIdentifier) File "/Users/jgooch/repos/sync_playlists/sync_playlists.py", line 72, in get_user_tokens users = {user_ids[user['@userID']]: user['@accessToken'] for user in api_shared_servers['MediaContainer']['SharedServer']} File "/Users/jgooch/repos/sync_playlists/sync_playlists.py", line 72, in <dictcomp> users = {user_ids[user['@userID']]: user['@accessToken'] for user in api_shared_servers['MediaContainer']['SharedServer']} TypeError: string indices must be integers

@snickers2k
Copy link

snickers2k commented Nov 16, 2021

syncing playlists is already possible in plex - officially (but of course, plex style, only for the admin).

vote here to get "better playlists", like having the "sharing power" for all users.

unsubscribed.

@majorgear
Copy link

majorgear commented Nov 17, 2021

I had to revert to # PlexAPI Settings PROJECT = 'PlexAPI' VERSION = ‘4.1.2' And then the script worked again.. It its still working for me with this version of the Plex api Has the script been updated to work with the new plex api? B

On 17 Sep 2021, at 8:47 am, shinedou @.***> wrote: @shinedou commented on this gist. I worked it out the new plexapi kills the script revert to the older plexapi and it works What version of plexapi did you have to revert to? — You are receiving this because you commented. Reply to this email directly, view it on GitHub https://gist.github.com/2607abf0e3431b6f133861bbe1bb694e#gistcomment-3895839, or unsubscribe https://github.com/notifications/unsubscribe-auth/ARMFWJVBYKZTLCZGJNZLBJ3UCJXZXANCNFSM4H5X6J5A. Triage notifications on the go with GitHub Mobile for iOS https://apps.apple.com/app/apple-store/id1477376905?ct=notification-email&mt=8&pt=524675 or Android https://play.google.com/store/apps/details?id=com.github.android&referrer=utm_campaign%3Dnotification-email%26utm_medium%3Demail%26utm_source%3Dgithub.

I downgraded my plexapi package , but nothing changed.

Did you need to do anything else? Do you perhaps have to tell the plex server with API version you are using for it to cooperate?

@majorgear
Copy link

majorgear commented Nov 20, 2021

I rewrote it just enough to copy playlists to other users. Give me a couple of days to clean my version and I'll share the github link.
The main part is the Playlist objects copytouser function. https://python-plexapi.readthedocs.io/en/latest/modules/playlist.html

@DeathByDentures
Copy link

DeathByDentures commented Dec 8, 2021

@majorgear any luck getting that updated script finished up? I had this working for years, but stopped using playlists, so I stopped using the script. Fast forward to now, I want to sync up a little x-mas playlist but plex has updated it's api and my version no longer works.

I am at a loss on how to fix this one. I see what you are directing us to in the plexdocs but I'm just too newbie to python to figure it out. I tried a few variations, but find myself unable to get my playlists to sync.

The script will run and it will act like it syncs, but nothing ever shows up on the user accounts.

@brettwatson77
Copy link

brettwatson77 commented Dec 8, 2021

@meisnate12
Copy link

meisnate12 commented Dec 22, 2021

if youre using the newest version of PlexAPI you probably need to change user_plex.createPlaylist(playlist, playlist_items) to user_plex.createPlaylist(playlist, items=playlist_items) the items need to be specified as they no longer just the second argument

@mikelauskas
Copy link

mikelauskas commented Jan 12, 2022

@meisnate12 that would be great if you updated your github repo. I'm really interested in using your library to share my playlists with my managed users.
THX

@juan11perez
Copy link

juan11perez commented Apr 28, 2022

@meisnate12
Thank you for the tip. With that correction the script worked perfect for me.

@meisnate12
Copy link

meisnate12 commented Apr 28, 2022

@meisnate12 that would be great if you updated your github repo. I'm really interested in using your library to share my playlists with my managed users. THX

not really sure what any of my repos have to do with this file.

@meisnate12
Copy link

meisnate12 commented Apr 28, 2022

@meisnate12 Thank you for the tip. With that correction the script worked perfect for me.

no problem glad it worked for you

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment