How to download Vimeo video using JavaScript?

Some time ago I made the same article but with Python. You could find it here. Some guys asked me to make similar post, but with JavaScript and NodeJS. So, today I’ll teach you how to download Vimeo video using JavaScript. Article is oriented for beginners. Welcome under cut.

Attention!

I made this post and this code for learning purpose. I don’t recommend it for commercial use. I’m not responsible for any damage caused by this code. Please, don’t lawlessly use this code and avoid any kind of illegal activities.

Setup project template

I have NodeJS on my MacBook, if you doesn’t please install first. Installing NodeJS is out of scope for this post, but if you need some help feel free to ask any questions here or in my Twitter. My NodeJS version is 18.0.0.

Next step is creating empty directory and initializing npm there. I use terminal commands for that.

# create directory
mkdir download-vimeo-video-javascript

# go inside
cd download-vimeo-video-javascript

# init npm
npm init -y

Those commands create project directory and initialized it with default package.json file. By default index.js is the main file, but I prefer for those kind of app use app.js.

Also, to use ES6 imports we need to change package type by putting “type”: “module” option. I usually do it to be able use “import” instead of “require”.

And will be great to have npm command to run our application.

Honestly, this is doesn’t matter for current article, but I am showing you what I always do. So, let’s edit package.json file.

{
  "name": "download-vimeo-video-javascript",
  "version": "1.0.0",
  "type": "module",
  "description": "",
  "main": "app.js",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1",
    "start": "node app.js"
  },
  "keywords": [],
  "author": "",
  "license": "ISC"
}

Now we need to create file app.js in the same directory and start coding. Finally!

Basic code

Let’s make basic code for our app.js file.

'use strict';


const main = async () => {
    
    console.log('Hello World');
}

const promise = main();

promise.then(() => {
    console.log('Program finished!');
});

promise.catch((err) => {
    console.log('Program finished with error!');
    console.log(err);
});

Let me explain why we make those code.

First line tells NodeJS we want to use strict mode. Strict mode is out of scope of this article too. I use it by default, because it disallow you to do some not safe things and also it shows error which doesn’t appear in no strict mode.

Next block is initialization async function and put it inside variable name. I prefer to have ability to use async/await constructions. You can put await only inside asynchronous functions. Thats why I create main. Inside function we have console.log call with hello world just for tests purposes. We will remove it later.

Below main function initialization I put call of it and promise with then and catch handler. If you want to know more about promises let me know. I could make article about that.

Let’s test our program. Run following command.

npn run start

My result is on screenshot bellow.

hello world nodejs example

Looks like everything is working. Let’s move to downloading video now.

Theory

If you watch any video from Vimeo your browser download it in the background. So, we can do the same, but we need to know video URL. If we have video URL there isn’t a problem to download it.

I have investigate before and I know where is it. When you visit Vimeo page your browser send one more request with video ID to Vimeo servers and it get JSON object with information about the video. There is video URL too.

Getting Vimeo video ID

Let’s take some video for example. I took this one absolutely randomly in previous article. It’s looks strange, but we don’t need to care about content.

Our first goal to take ID of the video. Video ID is those numbers in the end of video URL.

    // input video url
    let inputVideoUrl = 'https://vimeo.com/712159936/';

    // check is there ending slash and remove it
    if (inputVideoUrl.slice(-1) === '/') {
        inputVideoUrl = inputVideoUrl.slice(0, -1);
    }

    // get video id from url
    const videoId = inputVideoUrl.split('/').pop();
    
    console.log(videoId);

Maybe you want some additional explanation.

At first I check is there ending slash inside input url. This is required, because I want to split string by “/” char and get last element or result array (video ID). So, ending slash could interfere to do that.

Okay, we have video ID, what is next?

Getting project JSON config from Vimeo

In my previous article how to download Video video using Python I show screenshots from browser inspect. They illustrate how browser send additional request to Vimeo servers and get project JSON config. Let me put them here.

request to vimeo video
request result to vimeo video

As you can see a browser sends request to some Vimeo URL and get JSON configuration of the video. You can’t see this on screenshots, but for a request the browser uses host player.vimeo.com.

Time to make the same.

At first lets import https module. For that just add import on the top of the file import https from 'https'; I like to use async/await contraction so let’s use promises to get our JSON with https module.

    // video json config url
    const videoJsonConfigUrl = `https://player.vimeo.com/video/${videoId}/config`;

    // get video json config
    const videoConfig = await new Promise((resolve, reject) => {

        https.get(videoJsonConfigUrl, (res) => {

            let result = '';

            res.on('data', data => {
                result += data;
            });

            res.on('error', err => {
                reject(err);
            });

            res.on('end', () => {
                resolve(JSON.parse(result));
            });

        });
    });

    console.log(videoConfig);

Here I put await and create new promise. Main code for getting video is inside the promise. I put data in result string chunk by chunk and resolve it when end event emitted. If some error happens then my code call reject.

I put result on screenshot.

getting video url from Vimeo

What is the next step?

Download Vimeo video using JavaScript

Each video has different video quality. Each quality item has its own URL. There is field videoConfig.request.files.progressive. It is an array of objects. Each object represents video quality item. And of course, each object has its own URL.

how to download vimeo video using javascript - quality items

Let’s ignore quality choosing for now and just download first available one. At first we need to import module fs. Add this line in the top of tile import fs from 'fs';

Now we can implement downloading and finally get that video from Vimeo.

    // video quality items
    const videoQualityItems = videoConfig.request.files.progressive;

    // select file url
    const targetItem = videoQualityItems[0];
    const targetVideoFileUlr = targetItem.url;
    const localPath = `./${videoId}-${targetItem.quality}.mp4`;

    // download it
    await new Promise((resolve, reject) => {

            https.get(targetVideoFileUlr, (res) => {

                const file = fs.createWriteStream(localPath);

                res.pipe(file);

                res.on('error', err => {
                    reject(err);
                });

                res.on('end', () => {
                    resolve();
                });

            });
    });

I used almost the same way to download video, except adding pipe from input https stream to output file write stream. This allow us to download huge file without taking care about memory.

Looks like everything works as excepted.

result of video downloading

Choosing quality of video

Now, let’s say we want to choose quality of the video. For example, let’s take the best one. I use reduce method of array for that.

    // selecting the best video quality based on height and width
    // you could also add FPS multiplication to get the best quality based on FPS too
    const targetItem = videoQualityItems.reduce((prev, curr) => {
        return prev.width * prev.height > curr.width * curr.height ? prev : curr;
    });

Logic here is very simple. Best quality = bigger amount of pixels. You could also FPS multiplication to get the best quality based on FPS too.

Conclusions

In general downloading video from Vimeo using JavaScript is pretty simple. I hope my article was usefull for you. If you have any questions, any suggestions, or criticism, please ask them bellow in commends or write me in direct on Twitter.

I put all code in my GitHub repository in case you need to check full version.

Leave a Reply

Your email address will not be published.