Have you ever wanted to build your own YouTube video downloader using python? A tool where you just paste a video link, select the resolution, and click download? In this blog, we will explore how to create a YouTube Video Downloader and Info Fetcher using Python, Flask, and the PyTube library.

This project is great for beginners who are learning Python and want to build a real-world application. The application allows users to input a YouTube video URL and either fetch its details like title, views, and description or download it in a selected resolution.
Source Code: Download YouTube Videos Using Python
from flask import Flask, request, jsonify from pytube import YouTube import re app = Flask(__name__) def download_video(url, resolution): try: yt = YouTube(url) stream = yt.streams.filter(progressive=True, file_extension='mp4', resolution=resolution).first() if stream: stream.download() return True, None else: return False, "Video with the specified resolution not found." except Exception as e: return False, str(e) def get_video_info(url): try: yt = YouTube(url) stream = yt.streams.first() video_info = { "title": yt.title, "author": yt.author, "length": yt.length, "views": yt.views, "description": yt.description, "publish_date": yt.publish_date, } return video_info, None except Exception as e: return None, str(e) def is_valid_youtube_url(url): pattern = r"^(https?://)?(www\.)?youtube\.com/watch\?v=[\w-]+(&\S*)?$" return re.match(pattern, url) is not None @app.route('/download/<resolution>', methods=['POST']) def download_by_resolution(resolution): data = request.get_json() url = data.get('url') if not url: return jsonify({"error": "Missing 'url' parameter in the request body."}), 400 if not is_valid_youtube_url(url): return jsonify({"error": "Invalid YouTube URL."}), 400 success, error_message = download_video(url, resolution) if success: return jsonify({"message": f"Video with resolution {resolution} downloaded successfully."}), 200 else: return jsonify({"error": error_message}), 500 @app.route('/video_info', methods=['POST']) def video_info(): data = request.get_json() url = data.get('url') if not url: return jsonify({"error": "Missing 'url' parameter in the request body."}), 400 if not is_valid_youtube_url(url): return jsonify({"error": "Invalid YouTube URL."}), 400 video_info, error_message = get_video_info(url) if video_info: return jsonify(video_info), 200 else: return jsonify({"error": error_message}), 500 if __name__ == '__main__': app.run(debug=True)
Let’s break down the code and understand how it works.
Setting Up the Flask App
At the very top, the code imports some necessary modules:
pythonCopyEditfrom flask import Flask, request, jsonify
from pytube import YouTube
import re
flask
is the web framework we are using to create routes (endpoints) that interact with the user.pytube
is a lightweight library to download YouTube videos and fetch metadata.re
is used for regular expression matching to check if a YouTube URL is valid.
The line app = Flask(__name__)
initializes the Flask application.
Downloading a YouTube Video
One of the main features of this app is downloading a video. The download_video
function takes in a video URL and a resolution (like “720p” or “360p”) and downloads the video if available.
pythonCopyEditdef download_video(url, resolution):
try:
yt = YouTube(url)
stream = yt.streams.filter(progressive=True, file_extension='mp4', resolution=resolution).first()
if stream:
stream.download()
return True, None
else:
return False, "Video with the specified resolution not found."
except Exception as e:
return False, str(e)
Here’s what’s happening in simple words:
- The YouTube object is created from the given URL.
- It filters for progressive streams, which include both video and audio.
- If the resolution exists, it downloads the video.
- If the resolution is not found or something else goes wrong, an error message is returned.
Fetching Video Information
Another useful feature is to fetch the video’s metadata like title, views, description, etc. This is done using the get_video_info
function.
pythonCopyEditdef get_video_info(url):
try:
yt = YouTube(url)
stream = yt.streams.first()
video_info = {
"title": yt.title,
"author": yt.author,
"length": yt.length,
"views": yt.views,
"description": yt.description,
"publish_date": yt.publish_date,
}
return video_info, None
except Exception as e:
return None, str(e)
This function:
- Creates a YouTube object from the URL.
- Retrieves video details such as title, author, duration (in seconds), view count, description, and publish date.
- If any issue arises, it returns an error message.
This feature is helpful when you want to preview details before downloading a video.
Validating the YouTube URL
To make sure the input is a proper YouTube video link, a validation function is created:
pythonCopyEditdef is_valid_youtube_url(url):
pattern = r"^(https?://)?(www\.)?youtube\.com/watch\?v=[\w-]+(&\S*)?$"
return re.match(pattern, url) is not None
This uses a regular expression pattern to check whether the URL provided is a valid YouTube video link. If it doesn’t match the pattern, the API will reject the request.
Flask API Routes
This app provides two main routes (also called endpoints):
1. /download/<resolution>
– POST method
This route is used to download a video in the given resolution.
pythonCopyEdit@app.route('/download/<resolution>', methods=['POST'])
def download_by_resolution(resolution):
It expects a JSON body with the YouTube URL:
jsonCopyEdit{
"url": "https://www.youtube.com/watch?v=abc123"
}
Inside the function:
- It checks if the URL is present.
- Then it checks whether the URL is valid.
- If both checks pass, it tries to download the video with the requested resolution.
- If successful, it returns a success message; otherwise, it returns an error.
2. /video_info
– POST method
This route is used to fetch details about the video.
pythonCopyEdit@app.route('/video_info', methods=['POST'])
def video_info():
It also expects a JSON body with the YouTube URL.
The function:
- Validates the presence and format of the URL.
- Uses the
get_video_info
function to fetch the data. - Returns all the video information as a JSON response.
Running the App
Finally, this line ensures that the Flask server starts when you run the script:
pythonCopyEditif __name__ == '__main__':
app.run(debug=True)
Setting debug=True
is helpful during development as it gives detailed error messages and reloads the server when the code changes.
Output Example
For /video_info
:
jsonCopyEdit{
"title": "Python Tutorial",
"author": "CodeWithHarry",
"length": 360,
"views": 1500000,
"description": "Learn Python basics...",
"publish_date": "2022-05-01"
}
For /download/720p
:
jsonCopyEdit{
"message": "Video with resolution 720p downloaded successfully."
}
Or if resolution is not found:
jsonCopyEdit{
"error": "Video with the specified resolution not found."
}
How to Test It
You can test this application using tools like:
- Postman – to send POST requests with a JSON body.
- Curl – from the terminal.
- You can also create a frontend in HTML or React to make it a full-fledged web tool.
Final Thoughts
This Flask-based YouTube downloader project is a simple but powerful demonstration of how Python can be used to interact with APIs and external services like YouTube. It’s lightweight, functional, and beginner-friendly. For more python projects, visit here.
This kind of project gives you hands-on experience with Flask, REST APIs, error handling, and regular expressions – all valuable skills for web developers and backend engineers.
Source Code of Github: Code