Code, articles, tips, ideas, rants, et cetera

January 20, 2010

Retrieve Title, Description and Thumbnail of a YouTube Video Using JavaScript and AJAX

The YouTube Data API allows an application to interact with YouTube and perform a variety of operations; such as searching for videos, retrieve video information and upload a video on behalf of a user. The API also provides programmatic access to the video and user information stored on YouTube. Majority of data access operations are read-only and therefore do not require the YouTube API developer key.

The API is based on the Google Data Protocol which means that the data can be retrieved in ATOM/JSON format. The following example demonstrates how we can retrieve video information of a YouTube video (e.g. title, description, thumbnail, duration, author, views and rating) using the YouTube Data API, JavaScript, JSON and AJAX.

Retrieving the Video Feed

To retrieve video information from YouTube, use the following url:

http://gdata.youtube.com/feeds/api/videos/gzDS-Kfd5XQ?v=2&alt=json-in-script&callback=youtubeFeedCallback
  • gzDS-Kfd5XQ is the video id.
  • v=2 instructs the server to use version 2 of the API to handle this request.
  • alt=json-in-script instructs the server to send the data in JSON format wrapped inside a call to the callback function; this method is used to avoid crossdomain restrictions imposed by modern browsers.
  • callback=youtubeFeedCallback is the name of the callback function that will handle the JSON data.
  • prettyprint=true is an optional parameter that instructs the server to format the results for readability.

The above URL generates the following output (pretty printed for your convenience):

youtubeFeedCallback({
 "version": "1.0",
 "encoding": "UTF-8",
 "entry": {
  "xmlns": "http://www.w3.org/2005/Atom",
  "xmlns$media": "http://search.yahoo.com/mrss/",
  "xmlns$gd": "http://schemas.google.com/g/2005",
  "xmlns$yt": "http://gdata.youtube.com/schemas/2007",
  "gd$etag": "W/\"Dk8BQn47eCp7I2A9WhJQEU0.\"",
  "id": {
   "$t": "tag:youtube.com,2008:video:gzDS-Kfd5XQ"
  },
  "published": {
   "$t": "2008-08-06T18:56:56.000Z"
  },
  "updated": {
   "$t": "2012-07-24T04:40:53.000Z"
  },
  "category": [
   {
    "scheme": "http://schemas.google.com/g/2005#kind",
    "term": "http://gdata.youtube.com/schemas/2007#video"
   },
   {
    "scheme": "http://gdata.youtube.com/schemas/2007/categories.cat",
    "term": "Entertainment",
    "label": "Entertainment"
   },
   {
    "scheme": "http://gdata.youtube.com/schemas/2007/keywords.cat",
    "term": "sesame"
   },
   {
    "scheme": "http://gdata.youtube.com/schemas/2007/keywords.cat",
    "term": "street"
   },
   {
    "scheme": "http://gdata.youtube.com/schemas/2007/keywords.cat",
    "term": "celebrity"
   },
   {
    "scheme": "http://gdata.youtube.com/schemas/2007/keywords.cat",
    "term": "ray"
   },
   {
    "scheme": "http://gdata.youtube.com/schemas/2007/keywords.cat",
    "term": "charles"
   },
   {
    "scheme": "http://gdata.youtube.com/schemas/2007/keywords.cat",
    "term": "ernie"
   },
   {
    "scheme": "http://gdata.youtube.com/schemas/2007/keywords.cat",
    "term": "bert"
   },
   {
    "scheme": "http://gdata.youtube.com/schemas/2007/keywords.cat",
    "term": "muppet"
   },
   {
    "scheme": "http://gdata.youtube.com/schemas/2007/keywords.cat",
    "term": "instruments"
   },
   {
    "scheme": "http://gdata.youtube.com/schemas/2007/keywords.cat",
    "term": "guitar"
   },
   {
    "scheme": "http://gdata.youtube.com/schemas/2007/keywords.cat",
    "term": "drums"
   },
   {
    "scheme": "http://gdata.youtube.com/schemas/2007/keywords.cat",
    "term": "piano"
   }
  ],
  "title": {
   "$t": "Sesame Street: Ray Charles Sings \"I Got A Song\"  With Bert & Ernie"
  },
  "content": {
   "type": "application/x-shockwave-flash",
   "src": "http://www.youtube.com/v/gzDS-Kfd5XQ?version=3&f=videos&app=youtube_gdata"
  },
  "link": [
   {
    "rel": "alternate",
    "type": "text/html",
    "href": "http://www.youtube.com/watch?v=gzDS-Kfd5XQ&feature=youtube_gdata"
   },
   {
    "rel": "http://gdata.youtube.com/schemas/2007#video.related",
    "type": "application/atom+xml",
    "href": "http://gdata.youtube.com/feeds/api/videos/gzDS-Kfd5XQ/related?v=2"
   },
   {
    "rel": "http://gdata.youtube.com/schemas/2007#mobile",
    "type": "text/html",
    "href": "http://m.youtube.com/details?v=gzDS-Kfd5XQ"
   },
   {
    "rel": "http://gdata.youtube.com/schemas/2007#uploader",
    "type": "application/atom+xml",
    "href": "http://gdata.youtube.com/feeds/api/users/oookXUzPciGrEZEXmh4Jjg?v=2"
   },
   {
    "rel": "self",
    "type": "application/atom+xml",
    "href": "http://gdata.youtube.com/feeds/api/videos/gzDS-Kfd5XQ?v=2"
   }
  ],
  "author": [
   {
    "name": {
     "$t": "SesameStreet"
    },
    "uri": {
     "$t": "http://gdata.youtube.com/feeds/api/users/SesameStreet"
    },
    "yt$userId": {
     "$t": "oookXUzPciGrEZEXmh4Jjg"
    }
   }
  ],
  "yt$accessControl": [
   {
    "action": "comment",
    "permission": "allowed"
   },
   {
    "action": "commentVote",
    "permission": "allowed"
   },
   {
    "action": "videoRespond",
    "permission": "denied"
   },
   {
    "action": "rate",
    "permission": "allowed"
   },
   {
    "action": "embed",
    "permission": "allowed"
   },
   {
    "action": "list",
    "permission": "allowed"
   },
   {
    "action": "autoPlay",
    "permission": "allowed"
   },
   {
    "action": "syndicate",
    "permission": "allowed"
   }
  ],
  "gd$comments": {
   "gd$feedLink": {
    "rel": "http://gdata.youtube.com/schemas/2007#comments",
    "href": "http://gdata.youtube.com/feeds/api/videos/gzDS-Kfd5XQ/comments?v=2",
    "countHint": 311
   }
  },
  "yt$location": {
   "$t": "undefined"
  },
  "media$group": {
   "media$category": [
    {
     "$t": "Entertainment",
     "label": "Entertainment",
     "scheme": "http://gdata.youtube.com/schemas/2007/categories.cat"
    }
   ],
   "media$content": [
    {
     "url": "http://www.youtube.com/v/gzDS-Kfd5XQ?version=3&f=videos&app=youtube_gdata",
     "type": "application/x-shockwave-flash",
     "medium": "video",
     "isDefault": "true",
     "expression": "full",
     "duration": 129,
     "yt$format": 5
    },
    {
     "url": "rtsp://v5.cache2.c.youtube.com/CiILENy73wIaGQl05d2n-NIwgxMYDSANFEgGUgZ2aWRlb3MM/0/0/0/video.3gp",
     "type": "video/3gpp",
     "medium": "video",
     "expression": "full",
     "duration": 129,
     "yt$format": 1
    },
    {
     "url": "rtsp://v7.cache7.c.youtube.com/CiILENy73wIaGQl05d2n-NIwgxMYESARFEgGUgZ2aWRlb3MM/0/0/0/video.3gp",
     "type": "video/3gpp",
     "medium": "video",
     "expression": "full",
     "duration": 129,
     "yt$format": 6
    }
   ],
   "media$credit": [
    {
     "$t": "sesamestreet",
     "role": "uploader",
     "scheme": "urn:youtube",
     "yt$display": "SesameStreet",
     "yt$type": "partner"
    }
   ],
   "media$description": {
    "$t": "For more videos and games check out our new website at http://www.sesamestreet.org \r\n\r\nIn this video, Bert and Ernie perform with Ray Charles. \r\n\r\nSesame Street is a production of Sesame Workshop, a nonprofit educational organization which also produces Pinky Dinky Doo, The Electric Company, and other programs for children around the world.",
    "type": "plain"
   },
   "media$keywords": {
    "$t": "sesame, street, celebrity, ray, charles, ernie, bert, muppet, instruments, guitar, drums, piano"
   },
   "media$license": {
    "$t": "youtube",
    "type": "text/html",
    "href": "http://www.youtube.com/t/terms"
   },
   "media$player": {
    "url": "http://www.youtube.com/watch?v=gzDS-Kfd5XQ&feature=youtube_gdata_player"
   },
   "media$thumbnail": [
    {
     "url": "http://i.ytimg.com/vi/gzDS-Kfd5XQ/default.jpg",
     "height": 90,
     "width": 120,
     "time": "00:01:04.500",
     "yt$name": "default"
    },
    {
     "url": "http://i.ytimg.com/vi/gzDS-Kfd5XQ/mqdefault.jpg",
     "height": 180,
     "width": 320,
     "yt$name": "mqdefault"
    },
    {
     "url": "http://i.ytimg.com/vi/gzDS-Kfd5XQ/hqdefault.jpg",
     "height": 360,
     "width": 480,
     "yt$name": "hqdefault"
    },
    {
     "url": "http://i.ytimg.com/vi/gzDS-Kfd5XQ/1.jpg",
     "height": 90,
     "width": 120,
     "time": "00:00:32.250",
     "yt$name": "start"
    },
    {
     "url": "http://i.ytimg.com/vi/gzDS-Kfd5XQ/2.jpg",
     "height": 90,
     "width": 120,
     "time": "00:01:04.500",
     "yt$name": "middle"
    },
    {
     "url": "http://i.ytimg.com/vi/gzDS-Kfd5XQ/3.jpg",
     "height": 90,
     "width": 120,
     "time": "00:01:36.750",
     "yt$name": "end"
    }
   ],
   "media$title": {
    "$t": "Sesame Street: Ray Charles Sings \"I Got A Song\"  With Bert & Ernie",
    "type": "plain"
   },
   "yt$duration": {
    "seconds": "129"
   },
   "yt$uploaded": {
    "$t": "2008-08-06T18:56:56.000Z"
   },
   "yt$uploaderId": {
    "$t": "UCoookXUzPciGrEZEXmh4Jjg"
   },
   "yt$videoid": {
    "$t": "gzDS-Kfd5XQ"
   }
  },
  "gd$rating": {
   "average": 4.9510703,
   "max": 5,
   "min": 1,
   "numRaters": 981,
   "rel": "http://schemas.google.com/g/2005#overall"
  },
  "yt$statistics": {
   "favoriteCount": "2183",
   "viewCount": "756330"
  },
  "yt$rating": {
   "numDislikes": "12",
   "numLikes": "969"
  }
 }
}
);

JavaScript Example

Given the above information, retrieving and displaying the video information via JavaScript is fairly straight-forward, as shown in the example below:

<script type="text/javascript">
  function youtubeFeedCallback(data) {
    var s = '';
    s += '<img src="' + data.entry.media$group.media$thumbnail[0].url + '" width="' + data.entry.media$group.media$thumbnail[0].width + '" height="' + data.entry.media$group.media$thumbnail[0].height + '" alt="' + data.entry.media$group.media$thumbnail[0].yt$name + '" align="right"/>';
    s += '<b>Title:</b> ' + data.entry.title.$t + '<br/>';
    s += '<b>Author:</b> ' + data.entry.author[0].name.$t + '<br/>';
    s += '<b>Published:</b> ' + new Date(data.entry.published.$t).toLocaleDateString() + '<br/>';
    s += '<b>Duration:</b> ' + Math.floor(data.entry.media$group.yt$duration.seconds / 60) + ':' + (data.entry.media$group.yt$duration.seconds % 60) + ' (' + data.entry.media$group.yt$duration.seconds + ' seconds)<br/>';
    if (data.entry.gd$rating) {
      s += '<b>Rating:</b> ' + data.entry.gd$rating.average.toFixed(1) + ' out of ' + data.entry.gd$rating.max + ' (' + data.entry.gd$rating.numRaters + ' ratings)<br/>';
    }
    s += '<b>Statistics:</b> ' + data.entry.yt$statistics.favoriteCount + ' favorite(s); ' + data.entry.yt$statistics.viewCount + ' view(s)<br/>';
    s += '<br/>' + data.entry.media$group.media$description.$t.replace(/\n/g, '<br/>') + '<br/>';
    s += '<br/><a href="' + data.entry.media$group.media$player.url + '" target="_blank">Watch on YouTube</a>';
    document.write(s);
  }
</script>
<script type="text/javascript" src="http://gdata.youtube.com/feeds/api/videos/gzDS-Kfd5XQ?v=2&amp;alt=json-in-script&amp;callback=youtubeFeedCallback"></script>

Output

AJAX Example

The following demo fetches the video information via AJAX. It uses jQuery.getScript function to retrieve the data asynchronously. View the page source to inspect the code.

Enter YouTube Video ID or URL in the text box below

Video information will appear here.

References

106 comments:

  1. Thanks for this information. This is what i was just looking for.

    ReplyDelete
  2. Very helpfull ,. keep it up (c:
    here's a related atrickle from google (c:
    http://code.google.com/intl/da-DK/apis/youtube/2.0/developers_guide_json.html

    ReplyDelete
  3. Greaaatttt, i finally found this :-) God Loves U much...

    ReplyDelete
  4. How about a way to combine this code with the multiple video code?
    I only really need it to show the title.

    ReplyDelete
  5. Hi! :)

    Is it possible to get the video info with a url like this?

    http://www.youtube.com/cp/vjVQa1PpcFMKjVcvw8sE-l0GwdKhCaxqR7TWJ2zrPoI=&autoplay=1

    Thanks!

    ReplyDelete
  6. Umm, this does not look like a video url; looks more like a playlist url to me. Having said that, I think it is possible to query YouTupe playlist information via YouTube Data API.

    ReplyDelete
  7. Hello, THis is the exact thing I am after, except with Dojo instead of jQuery. I have tried everything I know, but I cant work it out. I keep getting a "405 methond not allowed"

    Any ideas?

    Thanks

    My code:
    dojo.xhrGet( {
    url: "http://gdata.youtube.com/feeds/api/videos/21OH0wlkfbc?v=2&alt=json-in-script&callback=youtubeFetchDataCallback",
    handleAs: "text",
    mimetype: "text",
    timeout: 5000,
    load: function(response, ioArgs) {
    alert('worked');
    //then run youtubeFethchdataCallback(response);
    return response;
    },
    error: function(response, ioArgs) {
    alert(response.toString());
    console.log(response, ioArgs);
    return response;
    },
    });

    ReplyDelete
  8. @Anonymous: I know nothing about Dojo. However, upon Googling "Dojo and JSONP" I found an article that says that you should use dojo.io.script.get() method for "cross-site data access", which seems to be your problem.

    I've assembled a little demo here:
    http://jsbin.com/iqozi3

    ReplyDelete
  9. fantastic worked great, thank you.

    I am impressed. EXECT what i was after, THANK YOU.

    ReplyDelete
  10. This is great, but can you tell us a simple way to pull in a playlist instead of a single video? Also, to to pull in the 0.jpg version of the thumbnail (the full size version) instead of the small version. Any help would be appreciated, thank you!

    ReplyDelete
  11. @A.B. have a look at the data returned by this url. Inside the "media$thumbnail" section you'll find links for all thumbnails, including hqdefault.jpg (http://i.ytimg.com/vi/21OH0wlkfbc/hqdefault.jpg, 480x360px).

    Secondly, YouTube GData API gives you access to almost everything:

    * Playlist: Movie Trailers 2010

    * User: SonyPictures

    * Video Search: upcoming movie trailers (reverse chronological order)

    ReplyDelete
  12. hi salman,
    this s really great one... i tried to connect youtube api to bring this all. but u did dis easily. i have question. so retrieve statistics of a video. for example views 10,999.

    ReplyDelete
  13. i couldnt retrieve ratings, statistics of a video. how to retrieve it?

    ReplyDelete
  14. Salman,
    I am a complete newbie to javascript & jQuery... I snagged the file at http://docs.google.com/leaf?id=0B9Fl2cYM2p_-YzIwMmU5MGUtMjY5Zi00MWJlLTk1ZjAtYzljNjNlODY2OTc5&hl=en

    Now, I would like to add the video details below the video and playlist in another div. But given my very limited abilities w/js, I have no clue as to how to make it happen...
    Could you please help?

    ReplyDelete
  15. @Open World and Anonymous: the example above shows you how to retrieve basic statistics including rating and view count. However THE DEMO DOES NOT SEEM TO BE WORKING AT THE MOMENT. I see this error message in the feed for the video id hard-coded in the demo:

    This video is not available in your region.

    On YouTube.com I get this message when trying to watch the same video:

    This video contains content from Sony Music Entertainment, who has blocked it in your country on copyright grounds. Sorry about that.

    Drat. Nevertheless, try another YouTube video in the demo above, for example:

    http://www.youtube.com/watch?v=InZNBcJTmWs

    Or enter the video id:

    InZNBcJTmWs

    ReplyDelete
  16. @Bonnie: sorry mate, customizing the script can take a little time, some thing I seem to lack at the moment :( Nevertheless, I can give you a hint: inside the file you downloaded, you'll find a function called ytplayer_play(). Modify it something along these lines:

    function ytplayer_play( )
    {
      var o = document.getElementById( 'ytplayer_object' );
      if ( o )
      {
        o.loadVideoById( ytplayer_playlist[ ytplayer_playitem ] );
        //----//INJECT THIS\\----
        $.getJSON(
          'http://gdata.youtube.com/feeds/api/videos/'
            + encodeURIComponent(ytplayer_playlist[ytplayer_playitem])
            + '?v=2&alt=json-in-script&callback=?',
          function (json) {
            $("#insert_id_of_details_div_here").html(
              "Title: " + json.entry["title"].$t + "<br>" +
              "Rating: " + json.entry["gd$rating"].average
            );
            // more help available at:
            // http://911-need-code-help.blogspot.com/2010/01/retrieve-youtube-video-title.html
        });
        //----\\INJECT THIS//----
      }
    }

    ReplyDelete
  17. Thank you man! It works fine!

    ReplyDelete
  18. You are the man - thanks.

    ReplyDelete
  19. @Salman:
    I finally was able to get back to this... However the code you said to inject does not display the description in my div... Yes, I did replace the:
    #insert_id_of_details_div_here
    with my div's id.
    Any ideas? I am a complete noob at this stuff and will try to look this over more, but not sure if I can come up with anything and could really use the help.
    Thanks!

    ReplyDelete
  20. @Bonnie: from the description you give, it is hard to guess what went wrong. Best way I could help you is that you help me first by pasting whatever you've done so far at http://jsfiddle.net. I plan to stop using google docs and use jsfiddle for all kind of support.

    The jsfiddle.net home page is a "create fiddle" page with four sections: HTML, CSS, JavaScript and Output. Fill in the first three boxes with what you've done so far -- keep in mind that whatever you past there will be public so do not enter any confidential or personal information there. I'll fix the code for you.

    ReplyDelete
  21. @salman
    Okay, I hope I've done this right... The fiddle is at:
    http://jsfiddle.net/scottcrew/bwzpD/

    ReplyDelete
  22. @Bonnie: the update available at:
    http://jsfiddle.net/salman/bwzpD/11/

    The actual problem was subtle: you failed to add the # symbol where I asked you to specify the id of target div. Anyway I've also re-arranged the code a little bit.

    Note that the demo MAY OR MAY NOT work on jsFiddle for some reason. So just copy all components (HTML, CSS, JavaScript) into your page, make sure you include jQuery and swfobject in the head section of your page and test.

    ReplyDelete
  23. Okay, so it is working... Now I am trying to figure out how to get the display to show Title, The youTube user that posted the video (with a link?), The date published, number of views, and the video's decription.
    I was looking at some of the stuff above for displaying some of that, but everything I seemed to try didn't work... The only thing that did work was "author", but it displayed as Undefined. BTW, I am using the json function...
    Do you have any examples of these things being used in conjunction with json?
    I am, also, going to be looking at applying CSS styles to these elements, so if you have any suggestions I appreciate it.

    ReplyDelete
  24. @Bonnie: an updated version of code is available here:

    http://jsfiddle.net/salman/bwzpD/12/

    I just edited one line; it now displays rating, author name and author url. Rest is left as an exercise :)

    ReplyDelete
  25. Hi Salman,
    Thank you for the great examples.

    I was just wondering, if it's possible to manipulate url ID in the script src = " " tag, for example:

    src = "http://gdata.youtube.com/feeds/api/videos/GdZn7k5rZLQ?v=2&alt=json-in-script&callback=someFunction"

    changes to

    src = "http://gdata.youtube.com/feeds/api/videos/Different ID?v=2&alt=json-in-script&callback=someFunction"

    I've tried:

    var id = the video id;
    document.getElementById("Script ID").src = "http://gdata.youtube.com/feeds/api/videos/" + id + "?v=2&alt=json-in-script&callback=someFunction";

    but it does not work. As I don't have a lot of experience with JavaScript not sure what to try. Searching in internet did not help either.

    Thanks in advance

    ReplyDelete
  26. @zelencho: If you look at the AJAX Example above, you'll notice that it loads the script dynamically. If you're using a framework such as jQuery you can view source this page and copy the jQuery code.

    If you're using pure javascript there are multiple ways to load a <script> tag dynamically.

    The example code you posted above looks OK to me. I cannot guess why it is not working; so I suggest that you use a JavaScript debugging tool. In FireFox you have FireBug extension, or just CTRL+SHIFT+J to open FireFox's native console. Likewise for Google chrome. In IE8+ pres F12. The JavaScript errors should be logged in the console (scripts tab). I'll see if I can setup a demo for you.

    ReplyDelete
  27. Salman, thanks. I'm brand new to this, but it seems every test video I've loaded doesn't work above. I checked and made sure the setting was open to the public. Any ideas? I'd love to use it... VideoID: 5BECModyFzE

    JB

    ReplyDelete
  28. @JB: I checked the feed for your video:

    http://gdata.youtube.com/feeds/api/videos/5BECModyFzE?v=2&alt=json-in-script&callback=youtubeFetchDataCallback&prettyprint=true

    and compared it with this one:

    http://gdata.youtube.com/feeds/api/videos/gzDS-Kfd5XQ?v=2&alt=json-in-script&callback=youtubeFetchDataCallback&prettyprint=true

    It seems like the feed for your video does not contain "gd$rating" field hence the script fails. I now realize that I cannot always trust YouTube Data API and therefore my script needs few common sense validations. So:

    1) You can check if ratings for the particular video are disabled. I have never uploaded a video on YouTube myself :) and so I am not sure what options are there.

    2) I'll revise the script in some time... in the fairly distant future. In the mean time, if you have little JavaScript (or any other c style language) knowledge, just make few little changes like this (lines to add are in bold):

    if (typeof data.entry[ "gd$rating" ] != "undefined") {
    s += '<b>Rating:</b> ' + new Number( data.entry[ "gd$rating" ].average ).toFixed( 1 ) + ' out of ' + data.entry[ "gd$rating" ].max + '; ' + data.entry[ "gd$rating" ].numRaters + ' rating(s)' + '<br/>';
    }

    Likewise for all problematic fields.

    ReplyDelete
  29. I've been looking for a solution like this all day... works perfectly. Much thanks!

    ReplyDelete
  30. Hello,

    I am trying to dynamically embed youtube videos on my site. Here is how I am using PHP code to get the video title

    $entry = simplexml_load_file($url, "SimpleXMLElement", LIBXML_NOWARNING)) {
    $youtube_title = $entry->title;
    }

    Some youtube movies however are NOT embeddable. I have read that yt:format=5 states that the movie is embeddable. Therefore my question is how do I check via PHP the yt:format tag and know whether the video is embeddable or not?

    Could you please help me with that

    ReplyDelete
  31. @banaszlo: have a look at these URLs:

    1) Embedding allowed (JSONC and XML/ATOM feeds)
    http://gdata.youtube.com/feeds/api/videos/gzDS-Kfd5XQ?v=2&alt=jsonc&callback=youtubeFeedCallback&prettyprint=true
    http://gdata.youtube.com/feeds/api/videos/gzDS-Kfd5XQ?v=2&alt=atom&prettyprint=true

    2) Embedding disallowed (JSONC and XML/ATOM feeds)
    http://gdata.youtube.com/feeds/api/videos/u8uYeHy10ZY?v=2&alt=jsonc&callback=youtubeFeedCallback&prettyprint=true
    http://gdata.youtube.com/feeds/api/videos/u8uYeHy10ZY?v=2&alt=atom&prettyprint=true

    In JSONP version you can use the property called <your_json_object>.data.accessControl.embed. Likewise in the XML version you can check the tag called yt:accessControl with attribute action=embed (have a look at the permission attribute).

    ReplyDelete
  32. Thank you a lot!!! Very helpful code.

    ReplyDelete
  33. Wow, this is a nice tip on how to use youtube and ajax. Will try and play with the code and see if I can adapt it.

    Nice work.
    Helen Neely

    ReplyDelete
  34. Hello Salman,

    The code worked perfectly well!
    Thank you.

    But I have a problem, I am not able to echo each retrieved value from the above script using php inside a form value tab

    $title="";

    if I echo $title outside the form value tab it works perfectly fine, while inside the value tab I get the javascript code itself rather than the value needed!

    I did many research and realized it is because javascript is at run-time while php at server side.

    I couldn't solve it using php session variables also and am not familiar with cookies.

    Can you please suggest an easier approach to solve my issue.

    One more thing, if I insert the $title values to the database it also saves as the javascript itself rather than the output of it.

    PLEASE HELP, Ive been drowning for the past 3-4 days with it

    Much appreciated

    Bob

    ReplyDelete
  35. @BOB: it is difficult for me to understand what you are trying to do. I assume that you want to retrieve the feed via PHP on the server side (and store it in database) instead of JavaScript on client side.

    If this is the case then you need to do things differently. A one line code is required to retrieve the data, additional lines to do something with that data:

    <?php
    $json = json_decode(file_get_contents("http://gdata.youtube.com/feeds/api/videos/gzDS-Kfd5XQ?v=2&alt=jsonc"));
    echo 'Title: ' . $json->data->title;

    Easy huh?

    ReplyDelete
  36. SALMAAAAAAAAAAAAN U ARE KING :)

    THANK YOU FOR MAKING MY DAY!

    GOD BLES U!

    (I used JSON before to solve it, but what I didnt cater is the fact that I am using PHP4 and that I needed to add the json.php with some function for it to work)

    Thank you again!

    ReplyDelete
  37. Hello.

    I need help. I'm trying to make a simple webpage on my Webs.com website that will display the Likes and Dislikes for "Friday" by Rebecca Black (Video ID = kfVsfOSbJY0). But I can't seem to get the script to get the data from here. I've tried loading the script with $.getScript("...") AND with the script tag using src="..." (replacing the dots with this URL)

    I've even tried using Google Chrome's Inspector console to try to display the variable set to the Likes count in an alert box. Any suggestions?

    Thanks in advance.
    ~YoshiOG1

    P.S. Click here to go to the webpage that I'm using to test the code.

    ReplyDelete
  38. @Yoshi: your comment was sent to spam by Blogger... very naughty of him. I've recovered your comment and in case you haven't figured it out, here is the trick:

    //$.getJSON example:

    $.getJSON("http://gdata.youtube.com/feeds/api/videos/kfVsfOSbJY0?v=2&alt=json-in-script&callback=?", function (d) {
    console.log(d);
    alert(d.entry["yt$rating"]["numLikes"] + " likes, " + d.entry["yt$rating"]["numDislikes"] + " dislikes");
    });

    //$.getScript example:

    function youtubeFeedCallbackNew(d) {
    console.log(d);
    alert(d.entry["yt$rating"]["numLikes"] + " likes, " + d.entry["yt$rating"]["numDislikes"] + " dislikes");
    });
    $.getScript("http://gdata.youtube.com/feeds/api/videos/kfVsfOSbJY0?v=2&alt=json-in-script&callback=youtubeFeedCallbackNew");

    People don't seem to like the song, hmmmmmm! This code will run in the console right away provided jQuery is loaded.

    ReplyDelete
  39. Thank you Salman! That is exactly what I've been looking for :-)))

    ReplyDelete
  40. hi salman arshad, i wonder if you could show an example at jsfiddle by displaying a video's description inside a div?

    i know it is just the same as title and others but when the description contains links, it will look different, like kinda screwed up where the http is after the whole www.SOMETHING.com

    ReplyDelete
  41. @jeff: The description is returned as plain text. You'll have to convert links into clickable ones manually using JavaScript. There are couple of scripts out there that can convert sub-strings such as www. and http:// into <a> tags.

    ReplyDelete
  42. Thank you for this script!
    I'm not too keen on javascript... What do I need to change to get the date in another language?

    ReplyDelete
  43. @anonymous: the data returned is in JSON format, any language that supports parsing JSON should be able to parse the dates into its native format.

    You can specify the format returned by the server by specifying "alt=atom", "alt=rss" etc. You can also omit the "callback=" parameter to get raw JSON or XML.

    ReplyDelete
  44. Hi,

    How can we just return valid JSON without a function wrapper. I just want pure JSON response, not a JavaScript wrapper. Please post an example, thanks.

    Regards,
    Mark

    ReplyDelete
  45. @Mark: remove the callback= parameter to get raw JSON. Raw JSON is useless in Browser+JavaScript applications because of same-origin-policy but useful if you want to fetch JSON through a server side script.

    ReplyDelete
  46. Thanks for the quick reply. I am not using Javavript :)

    Btw, the JSON alt value does not return anything without a wrapper. The JS wrapper is there on all JSON results, a bug in YT I think.

    One other issue is the statistics are all wrong. All of the videos I query have a view count of "1" when there are actually much more.

    Am I using the correct feed for user statistics. I only want to gather stats.

    Thanks!

    ReplyDelete
  47. @Mark: change alt=json-in-script to alt=json plus drop the callback parameter:

    http://gdata.youtube.com/feeds/api/videos/gzDS-Kfd5XQ?v=2&alt=json

    You can also use JSONC -- a compact version of the JSON feed:

    http://gdata.youtube.com/feeds/api/videos/gzDS-Kfd5XQ?v=2&alt=jsonc

    The difference between JSON and JSONC versions of YouTube feeds is that that JSON version tends to match the ATOM version of the feed whereas JSONC version omits all duplicate (redundant) data; therefore it has a very small download size.

    Other formats of the same feed:

    http://gdata.youtube.com/feeds/api/videos/gzDS-Kfd5XQ?v=2&alt=atom

    http://gdata.youtube.com/feeds/api/videos/gzDS-Kfd5XQ?v=2&alt=rss

    ReplyDelete
  48. cant this bo**sh*t be 'converted' in PHP :D??
    Couse i cant use the values :|
    document.write delete everithing on page...
    I always hated javascript... (you try a lot to make something to work and it still sucks...or not work)

    ReplyDelete
  49. @Bad Boy: you need 1 line of PHP code to grab the feed data:

    $json = json_decode(file_get_contents(
    "http://gdata.youtube.com/feeds/api/videos/gzDS-Kfd5XQ?v=2&alt=json"
    ));

    You need a dozen lines of code to display this information :)

    You can use JavaScript too. document.write WILL clear the document if it is called after the document is loaded. Instead you should use DOM manipulation function (createElement, getElementById, appendChild etc) or a JavaScript framework such as jQuery to display the data (view-source this page).

    ReplyDelete
  50. Wow realy nice was lookig long for something like this.

    The only thing i should like could it be easy changed instead of a playlist to a search query where you can fill in a keyword as example:
    http://gdata.youtube.com/feeds/api/videos?q='+keyword+'

    ReplyDelete
  51. Hi Salman,

    Many thanks! looks real nice and usefull.

    I only miss a link to a player.
    Can you help with how to put a link by the search results with a player or popup player so you can play the movie.

    And do you have any idea when i use the search form with a standard value how to get the results on page load for the first time.
    As example i now use on your form.

    So when i integrated it then must show the results for the first time for movies.
    But i need to click on search button first.

    I dont know if its easy but if you have any idea i am very happy to hear.
    Many thanks,
    Leo

    ReplyDelete
  52. Hello Salman,
    Thanks this looks real nice exactly what i was looking for. Am sorry to ask but theres one last thing. Can i limit the max results somewhere to 9?

    Regards,
    Leo

    ReplyDelete
  53. @leo: it is as simple as adding the &max-results=9 parameter in the request URL. Do not forget to look at the API query parameters reference I mentioned in my post. The updated fiddle is http://jsfiddle.net/salman/GMx24/9/

    ReplyDelete
  54. Hi Salman, thanks for your great help.
    Leo

    ReplyDelete
  55. Hi,
    Can you please help me. I am using java as platform and ii want to fetch uploader name, Description etc. Please help me out.

    ReplyDelete
  56. Hi Salman,

    Thanks for sharing your code and all the support. I think I've discovered a bug. When pulling up videos that do not have any ratings, the script fails. Try inputting this video ID: pGS2BtMrEeI

    Any suggestions?

    Thanks!

    Dave

    ReplyDelete
  57. @Vidushi: I am not familiar with Java; I can only suggest that you find a Java library capable of parsing JSON and use it to parse the following example URL:

    http://gdata.youtube.com/feeds/api/videos/gzDS-Kfd5XQ?v=2&alt=jsonc

    If reading RSS/XML via Java is an option then use this URL:

    http://gdata.youtube.com/feeds/api/videos/gzDS-Kfd5XQ?v=2&alt=rss

    ReplyDelete
  58. @Dave: I am very much aware of this bug but too lazy to fix it :) For some videos, certain fields might be absent from the JSON feed. For example the video you mentioned does not have any likes or rating hence the yt$rating and gd$rating fields are missing. Fields can also be turned off explicitly by the uploader (e.g. rating or comments can be disabled).

    For the video id you mentioned, my code blindly attempts to read data.entry.gd$rating.average which causes a JavaScript error. The fix is to check for the presence of (every) field before using it. You can use the typeof operator:

    if (typeof data.entry["gd$rating"] != 'undefined') {
      document.writeln('<b>Rating:</b> ' + new Number(data.entry["gd$rating"].average).toFixed(1) + ' out of ' + data.entry["gd$rating"].max + '; ' + data.entry["gd$rating"].numRaters + ' rating(s)' + '<br/>');
    }
    else {
      document.writeln('<b>Rating:</b> not available<br/>');
    }

    Another (lame) workaround is to use a couple of try...catch statements:

    try {
      document.writeln('<b>Rating:</b> ' + new Number(data.entry["gd$rating"].average).toFixed(1) + ' out of ' + data.entry["gd$rating"].max + '; ' + data.entry["gd$rating"].numRaters + ' rating(s)' + '<br/>');
    }
    catch (e) {
      document.writeln('<b>Rating:</b> not available<br/>');
    }

    ReplyDelete
  59. Hi!And Thanks!

    Does it's possible to get the embeded link fronm a video using the "yt$videoid" and the url of the thumbnail?

    I would like to export all of those data in table.Do you know a simple way to do this?

    Sorry for my writing, I'm french...

    Many thanks,

    Nico

    ReplyDelete
  60. @nico: if you look carefully at the feed content (example) you will find:

    a) video link at data.entry.link[0].href
    b) raw swf URL at data.entry.content.src

    You should be able to find additional interesting information just by looking at the feed content. Hope this helps.

    PS: I suggest not to store URLs in database. YouTube API changes from time to time and every now and then they introduce new features that often require adding query string parameters to URLs. Storing video Ids should be sufficient. You can build URLs using the video Id, e.g.:

    - http://youtu.be/gzDS-Kfd5XQ (new, shorter link)
    - http://youtu.be/gzDS-Kfd5XQ?hd=1 (new, shorter link with hd option)
    - http://www.youtube.com/embed/gzDS-Kfd5XQ (iframe embed)

    ReplyDelete
  61. This comment has been removed by a blog administrator.

    ReplyDelete
  62. @anonymous: thanks for pointing that out :) There is a CC-BY logo on every article on my blog; however, I can not enforce the "BY" part :(

    ReplyDelete
  63. Could u pls explain where and how this script youtubeFeedCallback( data ) is called up from? if its like ordinary javascript call from a html control's click event what value should be passed for argument "pass" (youtubeFeedCallback( data )). Please explain about data.

    ReplyDelete
    Replies
    1. youtubeFeedCallback is called by magic! Here is how it works:

      Suppose there is a web service that willingly makes its data available in JSON format for ANY website. Since browsers adhere to same origin policy, the web service chooses to make its JSON data available as JavaScript:

      1) You define a function that accepts a single parameter, the JSON data, in your document.

      2) You add a script tag with src attribute set to the web service's URL.

      3) You specify your callback function's name (e.g. myCallback) in the query string.

      4) The web service sends a plain JavaScript file (Content-type: text/javascript) with a content similar to this:

      myCallback({"foo": "bar"});

      The {"foo": "bar"} is the JSON data as a JavaScript object literal.

      5) The browser executes the JavaScript (no surprise) which in turn executes the myCallback function. The first parameter is the JSON data.

      Hope this helps.

      Delete
    2. how to extract the description of a video from youtube using php?

      if possible with the formatting of line breaks.

      want to extract plain text it will save to txt with php.

      thank you

      Delete
    3. Doesn't get much simpler than this:

      <?php
      $json = json_decode(file_get_contents('http://gdata.youtube.com/feeds/api/videos/gzDS-Kfd5XQ?v=2&alt=jsonc'));
      file_put_contents('gzDS-Kfd5XQ-description.txt', $json->data->description);

      Delete
    4. magic is awesome. i could understand the logic behind this. your post is very useful.Thanks very much.

      Delete
  64. Can u pls tell me, how to use your above code with multiple utube video Ids? Because in my project i want to retrieve utube video info for more than 10 video ids at a time and display all those in a web page.

    ReplyDelete
    Replies
    1. Sorry, I couldn't find a way to do it. You'll probably have to send separate request for each video id.

      Delete
    2. Hello Salman, your same code is working to retrieve utube video info for multiple ids at a time just by adding more script tags as you want. The trick here is that the same function youtubeFeedCallback( data ) is being reused multiple times automatically. Simply i just tested. But working well. Your code was really useful. Thanks.

      Delete
  65. Hi Salman,

    It is a very good article, m impressed, but i have a question can you please solve this,
    i am using the same code, but if youtube is blocked by admin then callback function not executes, in this case need to display any prior information to client, is there any possibility to execute any timeout/failed response function in this script?

    Regards,
    Timmy

    ReplyDelete
    Replies
    1. I am not sure if there is a cross-browser way of checking if a script tag failed to load. A quick and dirty solution is to use window.setTimeout to fire an error handler. You can then cancel the timeout on success. I've set up a demo for checking script tag load errors here:

      http://jsfiddle.net/salman/RAhuA/

      Delete
  66. is there any way to pass my own arguments to the function youtubefeedcallback along with json data like "function youtubeFeedCallback(data,arg1,arg2) {..... }" ?

    ReplyDelete
    Replies
    1. Not directly. You can dynamically create a function that calls the actual callback function. Arguments passed to the outer function are accessible in the inner function. Here is an example:

      function loadYoutubeData(videoid, arg1, arg2) {
        var callbackName = "youtubeFeedCallback_" + Math.random().toString().replace(/\D/g, "");
        window[callbackName] = function(data) {
          // you have access to data + arg1 and arg2
          alert("data: " + data.entry.title.$t + "\narg1: " + arg1 + "\narg2: " + arg2);
        };
        var script = document.createElement("script");
        script.src = "http://gdata.youtube.com/feeds/api/videos/" + videoid + "?v=2&alt=json-in-script&callback=" + callbackName;
        document.head.appendChild(script);
      }
      loadYoutubeData("gzDS-Kfd5XQ", 1, 111);
      loadYoutubeData("SyoA4LXQco4", 2, 222);
      loadYoutubeData("6l6PPvUhR4c", 3, 333);
      loadYoutubeData("T0Jqdjbed40", 4, 444);

      Delete
  67. Can you please tell me, how can i get the you tube video id again(which i have passed in script type="text/javascript" src="http://gdata.youtube.com/feeds/api/videos/gzDS-Kfd5XQ?v=2&alt=json-in-script&callback=youtubeFeedCallback") along with img,Title,author,duration etc inside the youtubefeedcallback(data) function itself.

    ReplyDelete
    Replies
    1. The current api returns video ids inside <json data>.entry.media$group.yt$videoid.$t

      This also works for feeds that return multiple videos e.g. http://gdata.youtube.com/feeds/api/videos/?q=vevo&v=2&alt=json-in-script&callback=youtubeFeedCallback -> <json data>.feed.entry[0...24].media$group.yt$videoid.$t

      Delete
  68. This doesn't work for me in Firefox 15 on Vista. Not even the example at the top of this page works.

    Also When I enter the URL (http://gdata.youtube.com/feeds/api/videos/gzDS-Kfd5XQ?v=2&alt=json-in-script&callback=youtubeFeedCallback) I get an error: Unknown authorization header Error 401

    Works ok in Chrome.

    ReplyDelete
    Replies
    1. I checked the script and Google data feed in Firefox 15 on Windows 7; everything seems to be working. I am surprised to see the authorization error, the script does not use authorization.

      Delete
  69. nice its super
    hey can u plzz gv code for getting list of youtube videos links on keyword search using asp.net

    ReplyDelete
    Replies
    1. Sorry I am not into ASP.Net. Converting the example in ASP.Net should be fairly straight forward anyway, you can use XmlDocument class to load the XML version of the feed (remove the callback= parameter from the url and either set alt=rss or alt=atom or remove alt= parameter altogether).

      Delete
  70. Hi.. Thanks for sharing.
    Helps a lot.

    I have one question How to get video link to directly embed into my web page.
    or
    How to get its id?
    var id = data.entry.id.$t ;
    It gives "tag:youtube.com,2008:video:XXXXX".
    What I need only XXXX.
    Thanks in advance.

    ReplyDelete
    Replies
    1. You can get the video links from the link array:

      data.feed.entry[i].link

      Grab the link that has rel=alternate; it contains the link to watch the video online.

      If you want use data.feed.id.$t, use regular expression matching, or this simple code:

      data.feed.entry[i].id.$t.split(":").slice(-1)

      Delete
  71. hi,

    is there any parameter that can make suggested videos disappear and YouTube logo too, using YouTube data API,am using this format for my mobile app in Appcelerator titanium to access a YouTube Video channel, really am struggling with this.

    thanks for any help.

    ReplyDelete
  72. Hi,
    I'm using the code from Your Article: "Embed Multiple YouTube Videos in Your Web Applications"
    How can i get the Video ID from there, to automatically manipulate the URL for the description?
    So that this URL will automatically update, if anyone click on an other video (the Video is loading in the player, but with manipulate description URL i have some problems):

    script type="text/javascript" src="http://gdata.youtube.com/feeds/api/videos/VIDEO-ID?v=2&alt=json-in-script&callback=youtubeFeedCallback"></script


    I don't know much about JavaScript, only a little html.
    PS: sorry for my bad english, i'm german

    Thanks,
    Kris

    ReplyDelete
    Replies
    1. I am not sure what you are trying to do. The jsFiddle links in the comments section (such as http://jsfiddle.net/salman/bwzpD/11/) might be useful.

      Delete
    2. Thanks :-)
      Now I've got the code from the site.
      But is it possible, to show the description of the first Video on first load of the site ?
      Every time, when I load the site (and don't chose an other video) the description shows only: Loading video information...

      Exactly as on the site http://jsfiddle.net/salman/bwzpD/11/
      (bottom, right; yellow background and the description shows: Loading video information...)

      After I chose an other video on the site, the description will be displayed correctly.

      Thanks,
      Kris

      Delete
    3. Thanks a lot :-)
      Now it works exactly as i want.

      Delete
  73. Salman, I use a javascript rotator to choose random videos from a set list.
    I want to be able to grab the title of the pre-set video and write it to a css id

    I tried to do something to maybe put a script inside a script :/ I have really no idea


    var videos = [
    'UrxcrZU070E',
    '8Lpaz2xTvuU',
    '6SVuAi-cVBU',
    'FlMh-5ONU3o',
    '-CzBYn7iRSI'
    ];

    var index=Math.floor(Math.random() * videos.length);
    var html='[div class="video"][iframe width="1" height="1" src="http://www.youtube.com/embed/' + videos[index] + '?version=3&autoplay=1&loop=1" frameborder="0" allowfullscreen][/iframe][/div]';
    document.write(html);

    *had to edit it kinda so blogspot would accept it < & > are sometimes [ or ], but you'll notice it
    It's just the div and iframe stuff

    ReplyDelete
    Replies
    1. You can ditch document.write and use DOM functions instead. HTML:

      <iframe id="videoframe"></iframe>
      <div id="videotitle"></div>

      JavaScript:

      var videos = [
      'UrxcrZU070E',
      '8Lpaz2xTvuU',
      '6SVuAi-cVBU',
      'FlMh-5ONU3o',
      '-CzBYn7iRSI'
      ];
      var index = Math.floor(Math.random() * videos.length);
      // load video
      document.getElementById("videoframe").src = "http://www.youtube.com/embed/" + videos[index];
      // load video feed
      var script = document.createElement("script");
      script.src = "http://gdata.youtube.com/feeds/api/videos/" + videos[index] + "?v=2&alt=json-in-script&callback=youtubeFeedCallback";
      document.getElementsByTagName("head")[0].appendChild(script);
      // define this function only once
      function youtubeFeedCallback(data) {
      document.getElementById("videotitle").innerHTML = data.entry.title.$t;
      }

      Delete
    2. The code for the video title worked perfecty, but the youtube video would not be played.

      Delete
    3. There is a typo in my example; I did not copy the video URL properly. On this line, enter complete URL of the embed URL:

      document.getElementById("videoframe").src = "http://www.youtube.com/embed/" + videos[index] + "?version=3&autoplay=1&loop=1";

      Not tested though, if you still get problems, look at the browsers debugger/error console.

      Delete
  74. Hi Salman,

    Thank for the great code.
    I have modified the code for wordpress and used the javascript version; instead of using a form i just added to the var videoid.
    I have managed to pull all the information fine; however when i add a new post and insert the youtube video id into my custom field which prints the result to the var videoid it only shows the latest video.

    If i have a list of 10 posts all with video id's it only populates the latest post with the video meta. Why is this?

    EG:

    function youtubeDataCallback(data) {
    var postimg = '';
    $('#yt_postimg').html(postimg);

    var title = '' + data.entry.title.$t + '';
    $('#yt_title').html(title);

    var description = '' + data.entry.media$group.media$description.$t.replace(/\n/g, '
    ') + '';
    $('#yt_description').html(description);

    var published = ' + new Date(data.entry.published.$t).toLocaleDateString() + ';
    $('#yt_published').html(published);

    var views = ' + data.entry.yt$statistics.viewCount + ' ;
    $('#yt_views').html(views);
    }

    $(document).ready(function() {
    $('#youtubeDataQuery')
    var videoid = "";
    var m;
    $.getScript('http://gdata.youtube.com/feeds/api/videos/' + encodeURIComponent(videoid) + '?v=2&alt=json-in-script&callback=youtubeDataCallback');
    });


    As i mentioned each wordpress post has a custom field (the video id) which is saved. But on the post list the script above only gives details for the latest post and not all of them; where all of them do have different video id's.

    Please help if you can :)

    ReplyDelete
    Replies
    1. Seems like you are creating divs with same ids and/or your callback function updates only one specific div. Remember that element ids must be unique.

      I see that you're using jQuery; in which case the code and solution becomes much simpler. Assuming that you're using HTML5 in your blog, you can simply add one or more divs like this in your post:

      <div class="youtube-data" data-videoid="gzDS-Kfd5XQ"></div>

      The add the following code (check next comment in few minutes) somewhere in your page. The code must be placed exactly once in a page so do not attempt to add it in your individual posts, rather, try adding it in the blog template or include is using an external file.

      Delete
  75. hi all i test your AJAX example putting this youtube URL :
    http://www.youtube.com/watch?v=wz9VyggeSbA

    but nothing run, no informations on the video? can you tell me why?

    thanks you :)

    ReplyDelete
    Replies
    1. The video URL worked with the script. May be the video is not available in your country (the script does not check for errors).

      Delete
  76. Nice article,
    can you please provide an information on how to retrieve thumbnail along with time duration on it, like how the thumbnail shown on youtube..
    Thanks..

    ReplyDelete
    Replies
    1. The length/duration information is present in the feed. Place this information inside a div/span and position it over the thumbnail image, using CSS.

      Delete
  77. Finally, Thanks for the great information

    ReplyDelete

Comment moderation is enabled. Approved comments are usually published (or answered) within 48 hours.
Note: Click the "load more..." button if necessary to see all comments.