Automate FB Video Download with Python

Aug 26, 2020

If you are a regular user of Facebook you might often come across videos which you wish to download. Or you might wish to share the video with your friends outside Facebook directly rather than sending them the Facebook video URL. Well as a Pythoneer you can easily convert your wish into a real world utility web app to automate facebook video download with Python. Yes, we won’t just create a tool to download a facebook video from its URL but create a fully functional but minimalistic web app to allow yourself or anyone to easily download a video by just entering its URL. Let’s see how!

A standalone module to download facebook videos from given URL

Just a few days ago on r/python an entrepreneuring Pythoneer shared their module to automatically download a Facebook video from a given URL. So we will use this handy module and call it from our web app when a user asks to download the video for a given Facebook URL. The repository for this module can be found here.

Creating the web app to automate

HTML

The HTML for this super simple web app is literally 5 lines:

<h1>Download videos straight up from Facebook</h1>
<input type="text" size="64" id="fbUrl"
    placeholder="https://www.facebook.com/McLaren.Racing/videos/10155088130291413" />
<button onclick="dl()">Download!</button>
<p id="status"></p>

We add the HTML mentioned above inside the body tag. Basically we have created a heading and then a text input field for the user to enter the video URL to download, and a button to call a function when the user clicks it.

Javascript

On the front-end of the app basically there are two actions to perform. One, when the user enters a URL to download the video from, we send the video URL to server to start its download. Second, we keep polling the server periodically asking about the status of the downloaded video. If the video has been downloaded we change our display on the front end showing the user the download button to watch and downlaod the video. If the video fails to download due to some reason, eg the URL being invalid, then the error infomormation is displayed instead.

<script>
    const SERVER_URL = "/fb/api";
    const statusEle = document.getElementById("status");
    let handle;

    function dl() {
        let url = document.getElementById("fbUrl").value;
        console.log(">>URL: " + url);
        if (!url) {
            alert("Please enter a URL!");
            return;
        }
        fetch(SERVER_URL + "/dl",
        {
            method: "POST",
            headers: {
            'Content-Type': 'application/json',
            },
            body: JSON.stringify({url: url})
        })
        .then(resp => resp.json())
        .then(data => {
            console.log(data);
            if (data.success) {
                statusEle.textContent = "Starting...";
            } else {
                statusEle.textContent = "Oops. Something went wrong :(";
            }
        })
        .catch(err => {
            console.log(err);
            statusEle.textContent = "Unable to talk to server :(";
        });

        handle = setInterval(poll, 1000, url);
    }

    function poll(url) {
        fetch(SERVER_URL + "/result",
        {
            method: "POST",
            headers: {
            'Content-Type': 'application/json',
            },
            body: JSON.stringify({url: url})
        }).then(r => r.json())
        .then(data => {
            if (data.failed) {
                statusEle.textContent = "Failed to download the video -- is the URL valid?";
                clearInterval(handle);
                return;
            }
            if (!data.done)
                return;
            statusEle.innerHTML = "Downloaded! Here's the <a href='" + data.url + "'>video</a>."
            clearInterval(handle);
        });
    }
</script>

Server-side: API service

On the server side the API is pretty small. We need two endpoints for the two kinds of calls that the front end is making. The first one, which begins download, simply takes in the user-given URL and adds it to a queue for the worker to process.

The second endpoint responsible for providing the download status of a URL does just that by querying the results collection. The results collection is updated by the worker as the URL is processed for download.

Apart from this the worker picks the unprocessed tasks from the queue, uses the facebook video downloader module mentioned above to download the video, and then updates the result collection and marks the URL as processed.

And that’s all you need to get this web app up and running! Do let me know if you have any questions or feedback!

If you liked my work you can show your support by buying me a few cups of coffee!