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. The example pictured above is a clip from a popular tv show. S.W.A.G. 😆

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