How to Download Movies from Your Plex Server

Plex Media Server includes the ability to download a movie from your Plex server locally so it can be played offline. There are a few issues with this feature: the download functionality doesn't work all the time, and the downloaded movie files can only be played within a Plex client.

The script provided in this post will download all movies from your Plex server so you can play them locally in any media player.

How to Download Movies from Your Plex Server

The Python script to download movie posters

While it may not be a good idea to download all movies from a Plex server, especially if you have a very large movie library, or especially if you don't own/manage the server, there is still the option of doing so.

If you would like to download all movies from your Plex server, you can use the following script.

import os
import requests
import xml.etree.ElementTree as ET
import shutil

plex_url = os.environ.get('PLEX_URL')
plex_token = os.environ.get('PLEX_TOKEN')
library = {library_id}
root_path = {download_path}

def get_all_media(id):
    """
    Gets all media for a library.

    Keyword arguments:
    id -- the id of the library
    """    
    response = requests.get('{0}/library/sections/{1}/all?X-Plex-Token={2}'.format(plex_url, library, plex_token))
    if response.ok:
        root = ET.fromstring(response.content)
        return root
    else:
        return None

def get_media_dir(video_tag):
    """
    Finds the full path to the media item, without the name of the
    media file.

    Keyword arguments:
    video_tag -- the video tag returned by the Plex API
    """
    media_tag = video_tag.find('Media')
    if media_tag is None:
        return None
    
    part_tag = media_tag.find('Part')
    if part_tag is None:
        return None
    
    file_path = part_tag.get('file')
    if file_path:
        return os.path.split(file_path)[-1]
    else:
        return None

def get_movie_url(video_tag):
    """
    Gets the URL of the movie.

    Keyword arguments:
    video_tag -- the video tag returned by the Plex API
    """
    media_tag = video_tag.find('Media')
    if media_tag is None:
        return None
    
    part_tag = media_tag.find('Part')
    if part_tag is None:
        return None
    
    movie_key = part_tag.get('key')
    if movie_key:
        return '{0}{1}?download=1&X-Plex-Token={2}'.format(plex_url, movie_key, plex_token)
    else:
        return

def download_movie(movie_url, path):
    """
    Downloads the movie from the URL to the specified path.

    Keyword arguments:
    movie_url -- the url of the movie to be downloaded
    path -- the path of the movie
    """
    response = requests.get(movie_url, stream=True)
    if response.status_code == 200:
        with open(path, 'wb') as f:
            response.raw.decode_content = True
            shutil.copyfileobj(response.raw, f)
    else:
        print("Couldn't download movie. Status code: {0}".format(response.status_code))

root = get_all_media(library)
for video_tag in root.findall('Video'):    
    path = get_media_dir(video_tag)
    if not path:
        print('The path to the media was not found.')
        continue

    movie_url = get_movie_url(video_tag)
    if movie_url:
        download_movie(movie_url, os.path.join(root_path, path))

How to use the script

To use the script, you will need to do the following:

  1. Install Python.
  2. After Python is installed, run the following pip command to install the dependencies:
    pip install requests
  3. Copy the above script and save it as a Python file, for example: download_posters.py
  4. Edit the script to replace {library_id} with the movies library ID from your Plex server.
  5. Replace {download_path} with the path where you would like the movies to be downloaded.
  6. Create an environment variable called PLEX_URL and set it to the URL of your Plex server. For example: http://localhost:32400.
  7. Create an environment variable called PLEX_TOKEN and set it to your Plex token.

What does the script do?

The above script will make multiple calls to the Plex API to perform the following steps:

  1. It gets all the movie files by calling the Get All Movies API command. This is done in the get_all_media function.
  2. Once all the movies have been retrieved, it will loop through all the movies and then call the get_media_dir function to get the path of each movie. This path is used to store the downloaded movie.
  3. Next, the get_movie_url function is called to get the URL API Command to download the movie. This URL is the Download Media File endpoint.
  4. Once the URL for the movie is known, the download_movie function will then download and save the movie. The file name of the movie will be the original name used on the server.

A few notes about the script

Before running the script, there are a few things to keep in mind:

  1. Since this will download all movies, it will take a long time for very large movie libraries.
  2. The Plex token that is used will need to be for a user ID that has the Allow Downloads restriction enabled on their account.
  3. The user associated with the Plex token will only be able to download movies that they can access from a Plex client.

This script is an easy way of making local copies of all your movies that are on your Plex server. It may not be feasible to do, however, if you have a very large movie library, or if you are using a server that you don't manage.

Photo of Paul Salmon
Started managing a Plex server in November 2014 and has been sharing his experience and what he has learned on Plexopedia. He is exploring and documenting the Plex API to help automate tasks for Plex to reduce the management effort of his server.

Dialogue & Discussion

Subscribe
Display