How to download Vimeo video using Python?

This article is oriented for newbies. I want to learn you a bit how to code things like downloaders from video hosting providers. Of course you could use ready-made libraries to solve that task and that is prefect solution. However, if you prefer to learn how to do it by yourself let’s go under cut and learn how to download Vimeo video using Python!

A bit of back-story

I made code for downloading videos from Vimeo in my last project using Javascript, coz whole project was based on NodeJS. But I think Python is more readable language for learning something. So in some meaning I will code this small tool with you together. In general that doesn’t matter which language to use.

By the way, sometime ago I made post How to protect content against scrapers. Check it out, if you are interested in scraping, Javascript, etc.

So, I could name this article how to download Vimeo video using NodeJS or something else. In general that doesn’t matter.

I’ll split article on logic based part to make reading it more comfort. Let’s go forward.

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 empty project

This part is not related to article theme. In general you need to just create main.py file and use locally installed Python. I am planing to use version 3.10, but I guess my code will be work fine in versions like 3.9, 3.7, etc.

Theory

When you watching video in the browser everything is going automatically. Browser execute page code and starting downloading the video. When there is enough data for showing video you could press play and browser will start playing video.

We need to do the same. I mean find out where is video file URL and then download it.

Getting video ID

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

Our first goal to take ID of the video. Those numbers in the end of video URL is video ID. So let’s scrape them to separate variable.

# set target video url
target_video_url = 'https://vimeo.com/712159936'

# remove slash from the end of the url
if target_video_url[-1] == '/':
    target_video_url = target_video_url[:-1]

# get video id from url
video_id = target_video_url.split('/')[-1]

# check the result
print(video_id)

Let me explain a bit. To get video ID we used split function. This function make array from string by splitting it by some char. To be sure where isn’t slash in the end of URL I added additional check. If we remove that check and use split function then result will be different.

Getting project JSON config

What is next step? I’ll show you a bit. Open Vimeo website and then open web inspector in your browser. I am using Safari so for me it’s Option + CMD + I shortcut. After go to Network tab and chose XHR/Fetch or similar. This tab showing all request which browser sends for this page. So now reload the page and get the results.

You should see there request named “config”. This is what we are looking for.

Information about video config request

The server respond with JSON data. And that JSON data contains real URL for video file. Do you know what that means? I want to say, if we get real video URL then we could easy download it. Thats why we need to get project config to download Vimeo video using Python.

If you open Headers tab (might be different in your browser) for this request, you could see which request type (GET) and which URL we need.

Target url to download Vimeo video using Python

Let’s write code for downloading Vimeo video config. I would like to use requests library. You could install it with pip via command: pip install requests.

# set video config url
video_config_url = 'https://player.vimeo.com/video/' + video_id + '/config'

# send get request to get video json config
video_config_response = requests.get(video_config_url)

# generate obj from json
video_config_json = video_config_response.json()

# check the result
print(video_config_json)

I run this code and got following result. Looks like everything is works OK.

Code running result

Download Vimeo video using Python

We are interested in field video_config_json['request']['files']['progressive']. It contains some URL for different quality.

Target field inside video config dictionary

Let’s ignore quality choosing for now and just download first available one.

# make variable for video config
video_config = video_config_json['request']['files']['progressive'][0]

# get video url
video_url = video_config['url']

# prepare file name for that video
video_name = video_id + '_' + video_config['quality'] + '.mp4'

# download video
video_response = requests.get(video_url)

# open file and write content there
video_file = open(video_name, 'wb')
video_file.write(video_response.content)
video_file.close()

# print result
print('downloaded: ' + video_name)

It works! You can check it by yourself.

Choosing quality

Okay, but what if I need specific quality of the video? Let’s make quality selection. For example, let’s say we need Vimeo video with height near 480px. Usually you can hear “video with 480p quality”. Maybe you saw, there is fields width and height. So you can just compare videos quality and select required one. However, what if there isn’t required quality?

Let’s make code for selection video with closest height of our goal.

# target video height
target_video_height = 480

# video config
target_video_config = None

# check all video find the closest one
for video_config in video_config_json['request']['files']['progressive']:
    
    # skip first video 
    if (target_video_config is None):
        target_video_config = video_config
        continue
        
    # get video height
    video_height = video_config['height']

    # check video height
    video_height_diff = abs(target_video_height - video_height)
    target_video_height_diff = abs(target_video_height - target_video_config['height'])
    
    # check video height diff
    if video_height_diff < target_video_height_diff:
        target_video_config = video_config

Maybe code looks long, however it pretty simple. We are going in the loop for each video config. If target video config is None then we just set target_video_config to current video config. So first iteration is always the same.

In next loop iteration we calculate difference in pixels between target video height and our results. The function abs used for make number always positive.

If current video diff less than target, current become target.

After the loop ends we get the closest video height to our target.

Conclusions

After whole code was ready I made refactoring. You could download whole code from my GitHub.

As you can see the task is pretty easy, but if you still have questions let me know.

Also, please, let me know if you see any errors in my code or text. English is not my native language, so I could do a lot of typos, mistakes, etc.

Don’t forget to write a thankful comment if my post help you to learn something ­čÖé

Leave a Reply

Your email address will not be published.