How To Search Videos on Vimeo Hosting Service

Marcello La Rocca
Aug. 12 2014, 11:27AM EDT

In our series on video APIs, we have so far examined YouTube and Dailymotion. In this post we provide a step-by-step guide to using the Vimeo API.

In some ways, Vimeo can be considered a niche product: It forbids the upload of any content not uniquely created by its users, and thus excludes commercial video, videogame trailers, and the like. However, at the time this article was written, the site registered hundreds of millions of unique visitors every month (approximately 10% of YouTube’s monthly traffic) and had more than 20 million registered users. Indeed, Vimeo was actually launched before YouTube, and it was the first service to support HD playback.

Three APIs at the price of one

We’ll start our journey at the Vimeo developers home page.

As you can see, there are several entries in the menu, and a few different APIs. As with the other video-sharing services we have explored, there is a Data API and a Player API. However, there are two versions of the Vimeo Data API. (Both look the same but are very different.)

  • The Vimeo Data API (version 2) uses OAuth (v1) and offers different response formats (XML, JSON, JSONP, PHP) and two subsets:
    • A Simple API that can be used, without authentication, to obtain information about public videos, users, groups, channels, albums and activity. You might expect to be able to query the video database using the Simple API, but you can’t. You can only retrieve information about videos created by specific users; if you need to perform searches, you must authenticate. This setup makes it easier to keep traffic and quotas under control: If you make too many requests in a brief amount of time, in fact, your developer account will be suspended. Responses by the Simple API are also limited to a maximum of 20 items. If you need to retrieve more items, you must authenticate.
    • The Advanced API allows users to perform every other operation without restrictions, after authenticating.
  • The Vimeo New API (version 3) uses OAuth 2 and returns results in JSON format. The main difference between this version of the API and version 2 is that this version is a RESTful API.

To clarify the difference between the two Vimeo APIs consider the search for videos about NASA:

Documentation on the Vimeo developers website includes the complete list of endpoints (i.e., methods) for Data API v2 and API v3; for the old API, a playground is also available to test any method with the parameters you are actually going to use. (See, for example, the videos.search method.)

However, if you are expecting anything like the DailyMotion explorer, you will be greatly disappointed. This tool is not as easy to use, nor as useful, as DailyMotion’s. For example, to use OAuth you’ll need to pass the authentication parameters in the headers, so you can’t just build the URL you need (as you can with DailyMotion) and be ready to go. Maybe this is also why, instead of returning a clear URL that would help you understand how the interface works, Vimeo’s playground tool just prints the (escaped) GET request. No drama--except, maybe, for novices--but it is an unnecessary complication nonetheless.

Authentication

Whether you use Data API v2 or v3, the first thing you will need is to register and then create one or more applications. Once you have registered, browse to the Apps Center-- you can follow the “My Apps” link in the developers home page.

Users can create as many new apps as they need and access any existing apps. Users are discouraged from using the same app profile for different pages/applications. For each profile, users will find a page containing three tabs with the information and the parameters needed to properly perform authentication:
 

As mentioned, in this article we will focus on OAuth 2 authentication; in particular, we will need the unauthenticated authorization header (see image, above).
The new API allows for two authentication workflows for applications, depending on how people will interact with Vimeo user accounts:

  • Single-user applications => Unauthorized authentication
    This workflow is best suited for applications that do not need to access individual users’ private data or just need to access a single user’s data (app owners). Authentication can be performed without involving users at all, exclusively on the server side. It is possible to use the authorization header provided for the app (a sort of Developer KEY), but in this case the scope of the application can only be one of "public", "private" and "upload". Otherwise, the unauthenticated access token can be generated dynamically for each request using the client identifier and client secret. (We’ll show you exactly how to do that in the next section.)
  • Multiuser applications => Authentication requests
    This workflow is the best choice when an application allows registered Vimeo users to interact with their accounts, so that each user will need authentication. This protocol is a bit more complicated because it requires the active involvement of users: Users will have to log into their accounts; client traffic will be first redirected to the Vimeo authentication service, and then back to your application, which will therefore have to manage this extra step. (This kind of request goes beyond our example needs, so we won’t examine it in depth for the moment.)

At this point, it should be easy to set everything up for a request, right? Well, almost.

If you are using PHP, there is an official library for Advanced API (v2); if you are using languages such as Python, Ruby or C++, there are a few unofficial libraries, as well.

For version 3, there are not one but three official libraries: for PHP, Python and Nodejs. Since we developed our example using Python, we should be in good shape, right? Well, again, almost.

The python-vimeo library is well-crafted: All you need to do is create an object (as shown in the self-explaining examples that go with the library), pass to its constructor your client_id and client_secret, and then call the methods you need.

The only problem is that this library relies on Tornado client, and in particular on  _ctypes, and, unfortunately, this is one of the C modules that isn’t supported by Google App Engine for Python 2.7. (See the complete list of supported modules here.)

So, if you are using a different Python framework, you are almost good to go. Otherwise, on GAE you’ll have to sort out the details.

Exacerbating the issue is the fact that support on Vimeo is just not that great. I wasn’t able to find a single complete example of the whole process, from authentication to request, and forums don’t help much, either.  API support on Vimeo’s forum was discontinued a year ago. There are other channels listed on the help page, but  it’s hard to find specific answers.

Workflow to call an API method

We will now walk step by step through the single-user application workflow:
 

You can either use the authenticated header on your app page (Step  1b - the header can also be built using the access token on the same page) …
 

… or you can use the unauthenticated header provided to obtain a dynamic access token (step 1b- you can also build the header using client identifier and client secret provided on the same page, after encoding them base64).
 

Step 1a is preferable when you need a particular scope, like create, since, as mentioned, only public, private and upload scopes are available for the static token. To show every single step, we start with our cid (Client Identifier) and secret, encode them base64, and then combine them to create the same unauthenticated header shown above:

def get_access_token(self, cid, secret, api_url='https://api.vimeo.com/oauth/authorize/client'):
 
    encoded = base64.b64encode("%s:%s" % (cid, secret)) 
    payload = {
                "grant_type": "client_credentials",
                "scope": "public create"
            }
    headers = {
                "Accept": "application/vnd.vimeo.*+json; version=3.0",
                "Authorization": "basic %s" % encoded
              }
     response = urlfetch.fetch(api_url,
                          method="POST",
                          headers=headers,
                          payload=urlencode(payload),
                          )
    if response.status_code != 200:
        raise ValueError(response.status_code)
    else:
        return json_loads(response.content)
 
As you might have noticed, we need to:

  • Use the HTTP POST method;
  • Pass two headers:
    • “Accept”, will clarify that we are seeking authorization for API version 3 and seek JSON results.
    • “Authorization” contains the access token created from Client Identifier and Client Secret.
  • The payload—that is, the body of the request—must contain a grant_type parameter with value “client_credentials” (see here); it can also contain a scope parameter with a space-separated list of valid scopes. And don’t forget to properly encode the payload before passing it to urlfetch.

The response from Vimeo (held in the content field of the object returned by urlfetch), will contain three fields:
{
       "access_token": "ACCESS_TOKEN",
       "scope": "public create",
       "token_type": "bearer"
}

We are mainly interested in the access_token field, as we will need to pass it in the header of our requests to the Vimeo API’s methods. VIMEO_OAUTH_HEADERS = {
                      'Accept': 'application/vnd.vimeo.*+json;version=3.0',
                      'Authorization': ('bearer %s' %

                       self.get_access_token(cid=CLIENT_ID, secret=CLIENT_SECRET)['access_token'])

                    }

url = 'https://api.vimeo.com/videos?’ + '&'.join(["%s=%s" % (k, str(v)) for k,v in search_params.items()])

search_response = urlfetch.fetch(url, method="GET", headers=VIMEO_OAUTH_HEADERS)

if search_response.status_code == 200:
         search_response = json_loads(search_response.content)
 
Here, we prepare the header for the second step. It basically differs only for the “Authorization” field, which is going to contain the access token generated during the previous step.

All we need to do at this point is build the URL for the API method we need to call, and fetch it passing that header.

The response returned by Vimeo will have the following structure. (Some parts are omitted to improve readability.):
 

We are going to use the “data” field to build our response, since it contains the list of items retrieved; at the top level of the JSON response, however, we can also find a few more useful fields:

  • total - The total number of results matching our query (in this case, just 4)
  • page - The current page number (results are paginated in the same way that DailyMotion does it)
  • per_page - The number of items per page
  • paging - A collection of useful links to navigate through the results pages. For example, you wouldn’t need to generate the URL for the next page of results; you could just use search_response.paging.next.

Putting everything together

The logic of our vimeo.py module will largely follow the structure used for the dailymotion.py module, taking into account the OAuth workflow and a few other differences:

  • Videos can’t be filtered by country: therefore, this option could either not be provided for Vimeo or the filter could just be ignored;
  • The sorting parameters are pretty different, in comparison to YouTube and DailyMotion (and even to Vimeo API v2). There is no complete list of valid parameters in the documentation, but, basically, results can be sorted according to any of the fields in the response;
  • As with DailyMotion, you can’t pass the query parameter when calling the related method to retrieve related videos. You will probably need to take extra care implementing this feature: Always use documentation as a reference, but version 3 of the API has been recently released, so it's still undergoing some improvement, both to the implementation of the library itself and to documentation.

You can find the gist with all the updated modules here, and, as always, the final result is available online.

 

Marcello La Rocca

Comments