Making A YouTube Video Downloader With Python’s Flask and pytube3 Libraries

I decided to attempt making a YouTube video downloader on the fly tonight after watching a stream where the creator questioned how to download YouTube videos. The easiest answer is to google sites like y2mate that work for downloading videos. But then I thought, I wonder if I can make something!

Boredom, my curiosity and some googling turned up the pytube3 library, “A lightweight, dependency-free Python 3 library (and command-line utility) for downloading YouTube Videos.” Lo and behold, 3 hours of experimentation later, I made a video downloader with Python. 😃

You-Tubular Tools

I used pytube3 with Flask and pythonanywhere to accomplish the task. I was pleasantly surprised at how it came together and simply worked! I’m really not that familiar with Flask either. Here’s how to make a primitive YouTube video downloader.

Install the pytube library in the pythonanywhere bash console with pip

pip3.8 install --user pytube3 --upgrade

If you’re not using pythonanywhere, install Flask (it’s already included in pythonanywhere)

python -m pip install flask

from flask import Flask, request, send_file
from pytube import YouTube
import logging
import sys

"""
Flask YouTube Video Downloader - Python Marketer
https://pythonmarketer.com/2020/10/07/making-a-youtube-video-downloader-with-pythons-flask-and-pytube3-libraries/
"""
logging.basicConfig(stream=sys.stderr, level=logging.DEBUG)
app = Flask(__name__)

@app.route("/")
def youtube_downloader():
    """Render HTML form to accept YouTube URL."""
    html_page = f"""<html><head>
                    <Title>YouTube Downloader</Title></head>
                    <body><h2>Enter URL to download YouTube Vids!</h2>
                    <div class="form">
                    <form action="/download_video" method="post">
                    <input type="text" name="URL">
                    <input type="submit" value="Submit">
                    </form></div><br><br>
                    </body></html>"""
    return html_page

@app.route("/download_video", methods=["GET","POST"])
def download_video():
    """
    First pytube downloads the file locally in pythonanywhere:
    /home/your_username/video_name.mp4

    Then use Flask's send_file() to download the video 
    to the user's Downloads folder. 
    """
    try:
        youtube_url = request.form["URL"]
        local_download_path = YouTube(youtube_url).streams[0].download()
        fname = local_download_path.split("//")[-1]
        return send_file(fname, as_attachment=True)
    except:
        logging.exception("Failed download")
        return "Video download failed!"

Minimum Viable Prototype Achieved

It works for many videos I tried. It occasionally had trouble downloading certain videos. I tested it successfully on videos of up to 10 minutes. Maybe it works more consistently if the file size is smaller? Or there is a bug on certain types of videos? For me, some videos of only a few minutes failed, so your results may vary. The videos that failed returned errors like KeyError: 'cipher' and KeyError: 'url'.

You can test out my YouTube video downloader here. Here’s my video of Kid Cudi performing at the University of Illinois if you want something to test. (After two failed attempts, it worked and downloaded on the third try. )

Honorable Mentions

youtube-dl: Command-line program to download videos from YouTube.com and other video sites

YoutubeDownload: GUI and CLI for downloading YouTube video/audio