I’ve been working a lot with embedded videos in websites, and there have been some cases where, rather than actually display the video, I want to display a thumbnail image, and then have a link to the video, or a lightbox for viewing the real thing.

So I’ve wanted to somehow find out if there’s a URL or API call that gives me a static image for a video – specifically from YouTube (I will have to investigate other services at a later date).

This is possible in two ways: a quick and easy, but cheating way with potentially unpredictable results, and a proper way.

This article summarises research I’ve done and is heavily based on information I’ve found from around the web, but hopefully pulls that all together for you with some PHP functions to boot!

The Quick and Dirty Way

First of all, here’s a nice time-lapse video of clouds over my garden in Swindon that I’ll use an example.

YouTube automatically generates a number of still images representing each video.

Now, this is a bit of a hack, but it works. The simplest way to get to these is to plug the video ID – the seemingly random string of numbers and letters in the YouTube URL – into one of a number of URLs:

  • http://i.ytimg.com/vi/VIDEO-ID/0.jpg
  • http://i.ytimg.com/vi/VIDEO-ID/1.jpg
  • http://i.ytimg.com/vi/VIDEO-ID/2.jpg
  • http://i.ytimg.com/vi/VIDEO-ID/3.jpg

In these URL’s, 0.jpg represents a full-size image of the video:

The URL’s ending in 1.jpg, 2.jpg and 3.jpg are three thumbnails from different points in the video:

One of the three thumbnails will have been selected by the video’s author as the default image for that video. You can get to this thumbnail at:

  • http://i.ytimg.com/vi/VIDEO-ID/default.jpg

The default thumbnail for my video is shown below.

You can get bigger versions of the default by using:

  • http://i.ytimg.com/vi/VIDEO-ID/hqdefault.jpg
  • http://i.ytimg.com/vi/VIDEO-ID/maxresdefault.jpg

Viewing the samples is left as an exercise for the reader (the sample video IS is U4M3U9GYvCo)

However, as I said above, this is a hack and could be an unreliable method. So, there is a “proper way” too!

The Proper Way

The problem with this method is that those URL’s aren’t really “official”. In theory YouTube could stop their use at any time, or change the URL’s to something different.

The Proper Way is to query the YouTube Data API to get the information about the video, and then grab the appropriate URL from that.  You can get the data about a video from the API by going to:

  • https://gdata.youtube.com/feeds/api/videos/VIDEO-ID?v=2

Of course, you’ll need to replace VIDEO-ID here with your video ID again.

Here’s a link to the data for my sample video – this has a “pretty print” option set too, so you can read it nicely:

You’ll see in here some XML entities like this:

<media:thumbnail url='http://i.ytimg.com/vi/U4M3U9GYvCo/default.jpg' height='90' width='120' time='00:00:15.500' yt:name='default'/>
<media:thumbnail url='http://i.ytimg.com/vi/U4M3U9GYvCo/mqdefault.jpg' height='180' width='320' yt:name='mqdefault'/>
<media:thumbnail url='http://i.ytimg.com/vi/U4M3U9GYvCo/hqdefault.jpg' height='360' width='480' yt:name='hqdefault'/>
<media:thumbnail url='http://i.ytimg.com/vi/U4M3U9GYvCo/1.jpg' height='90' width='120' time='00:00:07.750' yt:name='start'/>
<media:thumbnail url='http://i.ytimg.com/vi/U4M3U9GYvCo/2.jpg' height='90' width='120' time='00:00:15.500' yt:name='middle'/>
<media:thumbnail url='http://i.ytimg.com/vi/U4M3U9GYvCo/3.jpg' height='90' width='120' time='00:00:23.250' yt:name='end'/>

You’ll note that these are the same URL’s that we’ve already seen! But these are the official, up-to-date versions that will always (in theory) be correct.

The “Proper Method” then is to query the data API, grab the official thumbnail URL from the returned data, and use that.

Using the “Quick and Dirty” method in WordPress

I’ve used this technique in a WordPress theme. The theme has a custom post type that has a meta-data field for specifying an embedded piece of multimedia that is related to, or represents the post.

I added an action hook which intercepts this piece of meta-data and does all it can to grab the YouTube video ID, generate a static image URL, and then store that as another piece of meta-data.  Here’s the code from my functions.php – I know, it is also a bit quick and dirty and could use some validation. But it’s a good starting point for you.

// This action attempts to generate a YouTube thumbnail URL from the provided YouTube URL.
add_action( 'updated_post_meta', 'mytheme_generate_youtube_url', 10, 4);
add_action( 'added_post_meta', 'mytheme_generate_youtube_url', 10, 4);
function mytheme_generate_youtube_url( $meta_id, $object_id, $meta_key, $meta_value ) {
	if ($meta_key == '_mytheme_embed_url') {
		if (strlen($meta_value) > 7 ) { // Eliminates default 'http://'
			if (preg_match( '/youtube.com/', $meta_value )) {
				if (preg_match ('/\/embed\/(.*)/', $meta_value, $vid_matches )) {
					$vid_tmp = $vid_matches[1];
					$vid_tmp = explode('?', $vid_tmp);
					$vid = $vid_tmp[0];
				} else {
					$url_query = parse_url( $meta_value, PHP_URL_QUERY );
					parse_str( $url_query, $params );
					$vid = $params['v'];
			} elseif (preg_match( '/youtu.be/', $meta_value )) {
				$vid = ltrim( parse_url( $meta_value, PHP_URL_PATH ), '/');
			if ($vid) {
				$img_url = sprintf('http://i.ytimg.com/vi/%s/hqdefault.jpg', $vid);
				update_post_meta( $object_id, '_mytheme_video_img_url', $img_url );

This code attempts to cover all the different YouTube URL’s, but I won’t guarantee that I’ve got them all. I reckon this captures the following variants:

  • http://www.youtube.com/watch?v=U4M3U9GYvCo
  • http://youtu.be/U4M3U9GYvCo
  • http://www.youtube.com/embed/U4M3U9GYvCo

Of course, I’ll do this the “proper way” sometime, but the project I was doing this on didn’t have time for me to code up the XML API querying. If you want to do this yourself I’ll happily promote your code!

I sense there may be a WordPress plugin in here too, but I’m not sure exactly what it does yet. Let me know if you have ideas.

Like I said, this is mostly my own collation of things I found elsewhere so here are my sources – with thanks!