How to Create a Simple YouTube Download Program with a Progress Indicator in Python 3 with pytube

Python 3, pytube, os in Windows 10

Some of my friends live in an area that really struggles to get decent internet speeds in the afternoons and evenings. So much so that they can barely watch a YouTube video at 144p some days, and that is not particularly useful if they are trying to watch a video with code or some technical specs on the screen.

They really needed to download the videos, but really did not trust the programs available online to download videos for me without spamming them with advertising or adding some malicious malware to their beloved computers.

Fortunately, someone developed a Python 3 library to do just that – pytube.  In an earlier post I dive into some of the main aspects pytube:

How do I download YouTube videos with Python 3 using Pytube?

In this post, I am going to show you a quick app that can be run in the Python shell to download videos that features a progress indicator (not quite a progress bar).

I’ve intentionally kept the program fairly limited so you can focus on the important parts. I’ll show you the code and an example of what it looks like when it is running first and then give you the breakdown where you can focus on what you need to know and ignore the rest.

The Code

The Program Running



First, we grab the YouTube module from the pytube library in line 9. We will also need the os library to work with file locations (line 10).

Before we run the start function, that erh…starts the program, we will create a global variable for file_size that will change later once we have the data (line 54-55).


The start function does the main work of running the program. On line 25 we inform the user where the file will be saved to. The curly brackets “{}” are a placeholder for whatever goes in the .format(something).  In our case, it is the file_path function that will find the user’s file path to their Downloads folder.

Lines 27-29 gather the YouTube URL (we hope) prints it out for the user’s reference and then informs the user why they are waiting so long.

Lines 32-36 asks pytube to try and find the YouTube URL. It also does something special. on_progress_callback allows us to create a callback function, in our case progress_check, that will give us some values to create our progress indicator.

We use try and except here to cover a whole variety of sins. But essentially, if the user puts in a URL that does not point to a YouTube video or just any old gibberish then the exception will be called and the whole process with start() again. The exception might also be called if the user does not have an internet connection or even sometimes when YouTube gets sick of you running test programs and blocks you for a little while – it happened.

Next, we are evaluating the possible video types that YouTube can provide (I covered this in an earlier post here). I filter out all the possible video types by progressive and with an mp4 file extension. We take the first one of these options which will be the one with the best resolution.

I can use the video variable that we created in line 33 to also grab the title of the video with the um…video.title method in line 42. We then go on to print the title and inform the user that we are getting the file for download.

On line 46-47 it’s time to update the file_size of the video that we selected by using the .filesize method once we have decided on our video back in video_type.

Finally, we get around to what we came here to do, download the video in line 49. While the video is downloading, callbacks will be made to help us update our progress indicator.

We then start all over again by calling the start() function on line 52.



This function will take four parameters from pytube on_progress_callback method:

  • stream: the stream we chose. In our case the best resolution for an mp4 video.
  • chunk: the different packets of data that are downloading.
  • file_handle: the location the file will go in.
  • remaining: how many bytes remaining.

This is all gathered automatically by pytube and we don’t have to put any values in here.

For our purposes, we are going to only use the remaining value. On line 15 we get the percentage of what has been downloaded by subtracting the file_size by the remaining bytes, dividing it by the file_size and then multiplying it by 100.

This will result in a number will a large tail of decimals. We really don’t need that so I did some snazzy format work to only show the percentage as a whole number (line 16).

progress_check will then be called as the file downloads.


In the file_path function we look for the user’s home directory on line 20 and then join that to the Downloads so we can form the path to the user’s download file. Like this:

Create and Publish Google Workspace Add-ons with Apps Script Course 300px


There is a lot more on this in an earlier post:

How to Check a Users Home Directory for a Folder – Python 3


This is a very basic example. There is no option to change the download file location or to change to another file format. We could also add the option to download audio-only or download a whole playlist with the help of pytube.

Want to learn how to automate your daily admin at work with Python? Udemy has some great Python automation courses that will help you learn how to automate your tasks so you can focus on what really matters.

Got a more specific problem you need help with, but don’t have the time to develop the skills? Fiverr’s your best bet to find a skilled professional to solve your problem quickly and cheaply. *

*The above affiliate links have been carefully researched to get you to what you specifically need. If you decide to click on one of these links it will cost you just the same as going to the site. If you decide to sign up, I just get a little pocket money to help pay for the costs of running this website.



One thought on “How to Create a Simple YouTube Download Program with a Progress Indicator in Python 3 with pytube”

  1. Hello, I just copied this code and it is not working now.
    There is an error in function
    progress_Check(stream = None, chunk = None, file_handle = None, remaining = None)

    and that’s on this line:

    percent = (100*(file_size-remaining))/file_size

    TypeError: unsupported operand type(s) for -: ‘int’ and ‘NoneType’

    file_size is set and it is an int, but remaining always remains the same (or without a value) and it gets default value – None. How to solve or just bypass it?

    Thank you in advance.

Comments are closed.

%d bloggers like this: