How do you 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. 😃
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
import logging import sys from pytube import YouTube from flask import Flask, request, send_file """ 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"] download_path = YouTube(youtube_url).streams.download() fname = download_path.split("//")[-1] return send_file(fname, as_attachment=True) except: logging.exception("Failed download") return "Video download failed!"
Minimum Viable Prototype Achieved
This is more of a proof of concept than workable solution. 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
youtube-dl: Command-line program to download videos from YouTube.com and other video sites
YoutubeDownload: GUI and CLI for downloading YouTube video/audio