DEV Community

Cover image for Reddit Video Downloader Using python
Bdevy Team
Bdevy Team

Posted on

Reddit Video Downloader Using python

Hello Folks,
There are many reddit video downloaders available in the github that may seems easy to work on. However, unless you get some paid API, most of them are unusable.
So, I thought why not break the regular way of making a downloader and do something new.
Here you are going to get the easiest code ever to download reddit video.
You need:

  • A Framework (fast/flask), I will show with flask but you can make it in your way.

  • FFMPEG to convert the video and render the final output which will have both audio and video.

Find the Video Link From Reddit URL

If you go to any link with video from reddit and put .json on it you will get this kinda page which has all the data you need

Reddit json preview

From here you can find the video url in the
data["data"]["children"][0]["data"]["secure_media"]["reddit_video"]["fallback_url"]

in this location.

Well this url has the video but no audio, so what reddit does is create a HLSplaylist in m3u8 format to store audio and video both format which is not a proper format to download the video in usable format.

Here comes the ffmpeg part. Using ffmpeg we will be able to convert that into mp4

So here is the full flask code that you need

from flask import Flask, render_template, request, send_file
import requests
import os
import time
import threading
import ffmpeg
from urllib.parse import urlparse, urlunparse

app = Flask(__name__)

def download_video(giveurl):
    parsed_url = urlparse(giveurl)
    parsed_url = parsed_url._replace(path=parsed_url.path + '/')
    url = urlunparse(parsed_url) + ".json"
    headers = {
        "User-agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/99.0.4844.74 Safari/537.36"
    }

    try:
        for retry in range(5):
            try:
                r = requests.get(url, headers=headers, timeout=20)
                r.raise_for_status()
                data = r.json()[0]
                video_url = data["data"]["children"][0]["data"]["secure_media"]["reddit_video"]["fallback_url"]

                title = data["data"]["children"][0]["data"]["title"]
                final_url = "https://v.redd.it/" + video_url.split("/")[3]+'/HLSPlaylist.m3u8'
                output_filename = f"{title}.mp4"

                ffmpeg.input(final_url).output(output_filename, codec="copy").run()

                return output_filename

            except (requests.RequestException, ValueError) as e:
                if retry < 4:
                    time.sleep(2)
                else:
                    return None

    except KeyboardInterrupt:
        return None


@app.route("/", methods=["GET", "POST"])
def index():
    if request.method == "POST":
        giveurl = request.form.get("giveurl")
        if giveurl:
            output_filename = download_video(giveurl)
            if output_filename:
                return render_template("index.html", output_filename=output_filename)
            else:
                return "An error occurred during download."

    return render_template("index.html")


def delete_file_after_delay(file_path, delay_seconds):
    try:
        time.sleep(delay_seconds)
        os.remove(file_path)
    except Exception as e:
        print(f"Error deleting file: {e}")


@app.route("/download/<filename>")
def download(filename):
    file_path = os.path.join(app.root_path, filename)

    delete_thread = threading.Thread(target=delete_file_after_delay, args=(file_path, 300))
    delete_thread.daemon = True  
    delete_thread.start()

    return send_file(file_path, as_attachment=True)


if __name__ == "__main__":
    app.run(debug=True)
Enter fullscreen mode Exit fullscreen mode

And a simple html to show a download form.

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Reddit Video Downloader</title>
    <!-- Bootstrap CSS -->
    <link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/css/bootstrap.min.css" rel="stylesheet">
</head>
<body class="bg-light">

    <div class="container py-5">
        <div class="row justify-content-center">
            <div class="col-md-6">

                <div class="card shadow-lg border-0 rounded-3">
                    <div class="card-body p-4">
                        <h1 class="text-center mb-4 text-primary">Reddit Video Downloader</h1>

                        <form method="post">
                            <div class="mb-3">
                                <label for="giveurl" class="form-label">Enter Reddit Video URL:</label>
                                <input type="text" id="giveurl" name="giveurl" class="form-control" placeholder="Paste Reddit video link here..." required>
                            </div>
                            <div class="d-grid">
                                <button type="submit" class="btn btn-primary btn-lg">Download</button>
                            </div>
                        </form>

                        {% if output_filename %}
                        <div class="alert alert-success mt-4 text-center">
                            ✅ Video downloaded successfully!
                        </div>
                        <div class="d-grid">
                            <a href="{{ url_for('download', filename=output_filename) }}" class="btn btn-success btn-lg">Download Your Video</a>
                        </div>
                        {% endif %}
                    </div>
                </div>

            </div>
        </div>
    </div>

    <!-- Bootstrap JS (optional, for components like modal/tooltips if needed) -->
    <script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/js/bootstrap.bundle.min.js"></script>
</body>
</html>


Enter fullscreen mode Exit fullscreen mode

Here is the github link if you want to just clone and use..

Top comments (0)