Click here to see your recently viewed pages and most viewed pages.
Hide

JavaScript Code Samples

The following code samples, which use the Google APIs Client Library for JavaScript, are available for the YouTube Data API. You can download these code samples from the javascript folder of the YouTube APIs code sample repository on GitHub.

Authorizing requests

  • JavaScript (auth.js)

    The auth.js script demonstrates how to use the Google APIs Client Library for JavaScript to provide API access and authorize user requests. All of the subsequent samples on this page use this script to authorize their requests.

    For requests that do not require authentication, you could also use the key query parameter to specify an API key rather than using OAuth 2.0.

    Note: You need to update the client ID in the auth.js file. You can obtain your own client ID by registering your application in the Google Developers Console.

    // The client ID is obtained from the Google Developers Console
    // at https://console.developers.google.com/.
    // If you run this code from a server other than http://localhost,
    // you need to register your own client ID.
    var OAUTH2_CLIENT_ID = '__YOUR_CLIENT_ID__';
    var OAUTH2_SCOPES = [
      'https://www.googleapis.com/auth/youtube'
    ];
    
    // Upon loading, the Google APIs JS client automatically invokes this callback.
    googleApiClientReady = function() {
      gapi.auth.init(function() {
        window.setTimeout(checkAuth, 1);
      });
    }
    
    // Attempt the immediate OAuth 2.0 client flow as soon as the page loads.
    // If the currently logged-in Google Account has previously authorized
    // the client specified as the OAUTH2_CLIENT_ID, then the authorization
    // succeeds with no user intervention. Otherwise, it fails and the
    // user interface that prompts for authorization needs to display.
    function checkAuth() {
      gapi.auth.authorize({
        client_id: OAUTH2_CLIENT_ID,
        scope: OAUTH2_SCOPES,
        immediate: true
      }, handleAuthResult);
    }
    
    // Handle the result of a gapi.auth.authorize() call.
    function handleAuthResult(authResult) {
      if (authResult && !authResult.error) {
        // Authorization was successful. Hide authorization prompts and show
        // content that should be visible after authorization succeeds.
        $('.pre-auth').hide();
        $('.post-auth').show();
        loadAPIClientInterfaces();
      } else {
        // Make the #login-link clickable. Attempt a non-immediate OAuth 2.0
        // client flow. The current function is called when that flow completes.
        $('#login-link').click(function() {
          gapi.auth.authorize({
            client_id: OAUTH2_CLIENT_ID,
            scope: OAUTH2_SCOPES,
            immediate: false
            }, handleAuthResult);
        });
      }
    }
    
    // Load the client interfaces for the YouTube Analytics and Data APIs, which
    // are required to use the Google APIs JS client. More info is available at
    // http://code.google.com/p/google-api-javascript-client/wiki/GettingStarted#Loading_the_Client
    function loadAPIClientInterfaces() {
      gapi.client.load('youtube', 'v3', function() {
        handleAPILoaded();
      });
    }

My uploaded videos

The code samples below are for an application that lists videos uploaded to the authorized user's channel. The code assumes that the JavaScript and CSS files are in the same directory as the HTML page.

  • JavaScript (my_uploads.js)

    The JavaScript code below performs the following functions:

    1. It retrieves the playlist ID for videos uploaded to the user's channel using the API's channels.list method.
    2. It passes that ID to the playlistItems.list method to retrieve the videos in that list.
    3. It displays the list of videos.
    4. It constructs next and previous page buttons and sets their visibility based on the information in the API response.

    As noted in the Authorizing requests section, you need to update the client ID in the auth.js file to run this code.

    // Define some variables used to remember state.
    var playlistId, nextPageToken, prevPageToken;
    
    // After the API loads, call a function to get the uploads playlist ID.
    function handleAPILoaded() {
      requestUserUploadsPlaylistId();
    }
    
    // Call the Data API to retrieve the playlist ID that uniquely identifies the
    // list of videos uploaded to the currently authenticated user's channel.
    function requestUserUploadsPlaylistId() {
      // See https://developers.google.com/youtube/v3/docs/channels/list
      var request = gapi.client.youtube.channels.list({
        mine: true,
        part: 'contentDetails'
      });
      request.execute(function(response) {
        playlistId = response.result.items[0].contentDetails.relatedPlaylists.uploads;
        requestVideoPlaylist(playlistId);
      });
    }
    
    // Retrieve the list of videos in the specified playlist.
    function requestVideoPlaylist(playlistId, pageToken) {
      $('#video-container').html('');
      var requestOptions = {
        playlistId: playlistId,
        part: 'snippet',
        maxResults: 10
      };
      if (pageToken) {
        requestOptions.pageToken = pageToken;
      }
      var request = gapi.client.youtube.playlistItems.list(requestOptions);
      request.execute(function(response) {
        // Only show pagination buttons if there is a pagination token for the
        // next or previous page of results.
        nextPageToken = response.result.nextPageToken;
        var nextVis = nextPageToken ? 'visible' : 'hidden';
        $('#next-button').css('visibility', nextVis);
        prevPageToken = response.result.prevPageToken
        var prevVis = prevPageToken ? 'visible' : 'hidden';
        $('#prev-button').css('visibility', prevVis);
    
        var playlistItems = response.result.items;
        if (playlistItems) {
          $.each(playlistItems, function(index, item) {
            displayResult(item.snippet);
          });
        } else {
          $('#video-container').html('Sorry you have no uploaded videos');
        }
      });
    }
    
    // Create a listing for a video.
    function displayResult(videoSnippet) {
      var title = videoSnippet.title;
      var videoId = videoSnippet.resourceId.videoId;
      $('#video-container').append('<p>' + title + ' - ' + videoId + '</p>');
    }
    
    // Retrieve the next page of videos in the playlist.
    function nextPage() {
      requestVideoPlaylist(playlistId, nextPageToken);
    }
    
    // Retrieve the previous page of videos in the playlist.
    function previousPage() {
      requestVideoPlaylist(playlistId, prevPageToken);
    }
  • HTML (my_uploads.html)

    The HTML page below uses JQuery, the auth.js and my_uploads.js JavaScript files shown above, and a CSS file to display the list of uploaded videos.

    <!doctype html>
    <html>
      <head>
        <title>My Uploads</title>
        <link rel="stylesheet" type="text/css" href="my_uploads.css">
      </head>
      <body>
        <div id="login-container" class="pre-auth">
          This application requires access to your YouTube account.
          Please <a href="#" id="login-link">authorize</a> to continue.
        </div>
        <div id="video-container"></div>
        <div class="button-container">
          <button id="prev-button" class="paging-button" onclick="previousPage();">Previous Page</button>
          <button id="next-button" class="paging-button" onclick="nextPage();">Next Page</button>
        </div>
        <script src="//ajax.googleapis.com/ajax/libs/jquery/1.8.2/jquery.min.js"></script>
        <script type="text/javascript" src="auth.js"></script>
        <script type="text/javascript" src="my_uploads.js"></script>
        <script src="https://apis.google.com/js/client.js?onload=googleApiClientReady"></script>
      </body>
    </html>
  • CSS (my_uploads.css)

    This sample app also uses the following CSS:

    .paging-button {
      visibility: hidden;
    }
    
    .button-container {
      clear: both;
    }

Create a playlist

The code samples below are for an application that enables a user to create a private playlist and add videos to it. (You could, of course, modify the code so that it creates a publicly visible playlist or so that it checks a form value to determine whether the playlist is public or private.)

  • JavaScript (playlist_updates.js)

    The JavaScript code below performs the following functions:

    1. It enables the user to create a private playlist and then displays information about the newly created playlist.
    2. It enables the user to add a video to the playlist and displays the API response from that operation. Note that the JavaScript code supports the ability to specify the position where the video should start and stop playing, but the HTML below does not provide a way to specify those values.

    Again, you need to update the client ID in the auth.js file to run this code.

    // Define some variables used to remember state.
    var playlistId, channelId;
    
    // After the API loads, call a function to enable the playlist creation form.
    function handleAPILoaded() {
      enableForm();
    }
    
    // Enable the form for creating a playlist.
    function enableForm() {
      $('#playlist-button').attr('disabled', false);
    }
    
    // Create a private playlist.
    function createPlaylist() {
      var request = gapi.client.youtube.playlists.insert({
        part: 'snippet,status',
        resource: {
          snippet: {
            title: 'Test Playlist',
            description: 'A private playlist created with the YouTube API'
          },
          status: {
            privacyStatus: 'private'
          }
        }
      });
      request.execute(function(response) {
        var result = response.result;
        if (result) {
          playlistId = result.id;
          $('#playlist-id').val(playlistId);
          $('#playlist-title').html(result.snippet.title);
          $('#playlist-description').html(result.snippet.description);
        } else {
          $('#status').html('Could not create playlist');
        }
      });
    }
    
    // Add a video ID specified in the form to the playlist.
    function addVideoToPlaylist() {
      addToPlaylist($('#video-id').val());
    }
    
    // Add a video to a playlist. The "startPos" and "endPos" values let you
    // start and stop the video at specific times when the video is played as
    // part of the playlist. However, these values are not set in this example.
    function addToPlaylist(id, startPos, endPos) {
      var details = {
        videoId: id,
        kind: 'youtube#video'
      }
      if (startPos != undefined) {
        details['startAt'] = startPos;
      }
      if (endPos != undefined) {
        details['endAt'] = endPos;
      }
      var request = gapi.client.youtube.playlistItems.insert({
        part: 'snippet',
        resource: {
          snippet: {
            playlistId: playlistId,
            resourceId: details
          }
        }
      });
      request.execute(function(response) {
        $('#status').html('<pre>' + JSON.stringify(response.result) + '</pre>');
      });
    }
  • HTML (playlist_updates.html)

    The HTML page below uses JQuery, along with the auth.js and playlist_updates.js JavaScript files shown above.

    <!doctype html>
    <html>
      <head>
        <title>Playlist Updates</title>
      </head>
      <body>
        <div id="login-container" class="pre-auth">This application requires access to your YouTube account.
          Please <a href="#" id="login-link">authorize</a> to continue.
        </div>
        <div id="buttons">
          <button id="playlist-button" disabled onclick="createPlaylist()">Create a new Private Playlist</button>
          <br>
          <label>Current Playlist Id: <input id="playlist-id" value='' type="text"/></label>
          <br>
          <label>Video Id: <input id="video-id" value='GZG9G5txtaE' type="text"/></label><button onclick="addVideoToPlaylist()">Add to current playlist</button>
        </div>
        <h3>Playlist: <span id="playlist-title"></span></h3>
        <p id="playlist-description"></p>
        <div id="playlist-container">
          <span id="status">No Videos</span>
        </div>
        <script src="//ajax.googleapis.com/ajax/libs/jquery/1.8.2/jquery.min.js"></script>
        <script src="auth.js"></script>
        <script src="playlist_updates.js"></script>
        <script src="https://apis.google.com/js/client.js?onload=googleApiClientReady"></script>
      </body>
    </html>

Search by keyword

The code samples below are for an application that executes a YouTube search for a specified query and then displays the API result.

  • JavaScript (search.js)

    The JavaScript code below executes a YouTube search for the specified query term and then populates a DOM element with the API response. Again, you need to update the client ID in the auth.js file to run this code.

    // After the API loads, call a function to enable the search box.
    function handleAPILoaded() {
      $('#search-button').attr('disabled', false);
    }
    
    // Search for a specified string.
    function search() {
      var q = $('#query').val();
      var request = gapi.client.youtube.search.list({
        q: q,
        part: 'snippet'
      });
    
      request.execute(function(response) {
        var str = JSON.stringify(response.result);
        $('#search-container').html('<pre>' + str + '</pre>');
      });
    }
  • HTML (search.html)

    The HTML page below uses JQuery, along with the auth.js and search.js JavaScript files shown above, to display the list of search results.

    <!doctype html>
    <html>
      <head>
        <title>Search</title>
      </head>
      <body>
        <div id="buttons">
          <label> <input id="query" value='cats' type="text"/><button id="search-button" disabled onclick="search()">Search</button></label>
        </div>
        <div id="search-container">
        </div>
        <script src="//ajax.googleapis.com/ajax/libs/jquery/1.8.2/jquery.min.js"></script>
        <script src="auth.js"></script>
        <script src="search.js"></script>
        <script src="https://apis.google.com/js/client.js?onload=googleApiClientReady"></script>
      </body>
    </html>

Upload video

The code samples below are for an application that uploads a video to YouTube. The code assumes that the JavaScript and CSS files are in the same directory as the HTML page.

  • JavaScript (upload_video.js)

    The JavaScript code below performs the following functions:

    1. It retrieves the channel name and thumbnail of the authenticated user's channel using the API's channels.list method.
    2. It handles the video upload to YouTube using the resumable upload protocol.
    3. It polls for the uploaded video's upload and processing status using the API's videos.list method by setting the part parameter value to status.
    /*
    Copyright 2015 Google Inc. All Rights Reserved.
    
    Licensed under the Apache License, Version 2.0 (the "License");
    you may not use this file except in compliance with the License.
    You may obtain a copy of the License at
    
      http://www.apache.org/licenses/LICENSE-2.0
    
    Unless required by applicable law or agreed to in writing, software
    distributed under the License is distributed on an "AS IS" BASIS,
    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    See the License for the specific language governing permissions and
    limitations under the License.
    */
    
    var signinCallback = function (result){
      if(result.access_token) {
        var uploadVideo = new UploadVideo();
        uploadVideo.ready(result.access_token);
      }
    };
    
    var STATUS_POLLING_INTERVAL_MILLIS = 60 * 1000; // One minute.
    
    
    /**
     * YouTube video uploader class
     *
     * @constructor
     */
    var UploadVideo = function() {
      /**
       * The array of tags for the new YouTube video.
       *
       * @attribute tags
       * @type Array.<string>
       * @default ['google-cors-upload']
       */
      this.tags = ['youtube-cors-upload'];
    
      /**
       * The numeric YouTube
       * [category id](https://developers.google.com/apis-explorer/#p/youtube/v3/youtube.videoCategories.list?part=snippet®ionCode=us).
       *
       * @attribute categoryId
       * @type number
       * @default 22
       */
      this.categoryId = 22;
    
      /**
       * The id of the new video.
       *
       * @attribute videoId
       * @type string
       * @default ''
       */
      this.videoId = '';
    
      this.uploadStartTime = 0;
    };
    
    
    UploadVideo.prototype.ready = function(accessToken) {
      this.accessToken = accessToken;
      this.gapi = gapi;
      this.authenticated = true;
      this.gapi.client.request({
        path: '/youtube/v3/channels',
        params: {
          part: 'snippet',
          mine: true
        },
        callback: function(response) {
          if (response.error) {
            console.log(response.error.message);
          } else {
            $('#channel-name').text(response.items[0].snippet.title);
            $('#channel-thumbnail').attr('src', response.items[0].snippet.thumbnails.default.url);
    
            $('.pre-sign-in').hide();
            $('.post-sign-in').show();
          }
        }.bind(this)
      });
      $('#button').on("click", this.handleUploadClicked.bind(this));
    };
    
    /**
     * Uploads a video file to YouTube.
     *
     * @method uploadFile
     * @param {object} file File object corresponding to the video to upload.
     */
    UploadVideo.prototype.uploadFile = function(file) {
      var metadata = {
        snippet: {
          title: $('#title').val(),
          description: $('#description').text(),
          tags: this.tags,
          categoryId: this.categoryId
        },
        status: {
          privacyStatus: $('#privacy-status option:selected').text()
        }
      };
      var uploader = new MediaUploader({
        baseUrl: 'https://www.googleapis.com/upload/youtube/v3/videos',
        file: file,
        token: this.accessToken,
        metadata: metadata,
        params: {
          part: Object.keys(metadata).join(',')
        },
        onError: function(data) {
          var message = data;
          // Assuming the error is raised by the YouTube API, data will be
          // a JSON string with error.message set. That may not be the
          // only time onError will be raised, though.
          try {
            var errorResponse = JSON.parse(data);
            message = errorResponse.error.message;
          } finally {
            alert(message);
          }
        }.bind(this),
        onProgress: function(data) {
          var currentTime = Date.now();
          var bytesUploaded = data.loaded;
          var totalBytes = data.total;
          // The times are in millis, so we need to divide by 1000 to get seconds.
          var bytesPerSecond = bytesUploaded / ((currentTime - this.uploadStartTime) / 1000);
          var estimatedSecondsRemaining = (totalBytes - bytesUploaded) / bytesPerSecond;
          var percentageComplete = (bytesUploaded * 100) / totalBytes;
    
          $('#upload-progress').attr({
            value: bytesUploaded,
            max: totalBytes
          });
    
          $('#percent-transferred').text(percentageComplete);
          $('#bytes-transferred').text(bytesUploaded);
          $('#total-bytes').text(totalBytes);
    
          $('.during-upload').show();
        }.bind(this),
        onComplete: function(data) {
          var uploadResponse = JSON.parse(data);
          this.videoId = uploadResponse.id;
          $('#video-id').text(this.videoId);
          $('.post-upload').show();
          this.pollForVideoStatus();
        }.bind(this)
      });
      // This won't correspond to the *exact* start of the upload, but it should be close enough.
      this.uploadStartTime = Date.now();
      uploader.upload();
    };
    
    UploadVideo.prototype.handleUploadClicked = function() {
      $('#button').attr('disabled', true);
      this.uploadFile($('#file').get(0).files[0]);
    };
    
    UploadVideo.prototype.pollForVideoStatus = function() {
      this.gapi.client.request({
        path: '/youtube/v3/videos',
        params: {
          part: 'status,player',
          id: this.videoId
        },
        callback: function(response) {
          if (response.error) {
            // The status polling failed.
            console.log(response.error.message);
            setTimeout(this.pollForVideoStatus.bind(this), STATUS_POLLING_INTERVAL_MILLIS);
          } else {
            var uploadStatus = response.items[0].status.uploadStatus;
            switch (uploadStatus) {
              // This is a non-final status, so we need to poll again.
              case 'uploaded':
                $('#post-upload-status').append('<li>Upload status: ' + uploadStatus + '</li>');
                setTimeout(this.pollForVideoStatus.bind(this), STATUS_POLLING_INTERVAL_MILLIS);
                break;
              // The video was successfully transcoded and is available.
              case 'processed':
                $('#player').append(response.items[0].player.embedHtml);
                $('#post-upload-status').append('<li>Final status.</li>');
                break;
              // All other statuses indicate a permanent transcoding failure.
              default:
                $('#post-upload-status').append('<li>Transcoding failed.</li>');
                break;
            }
          }
        }.bind(this)
      });
    };
  • HTML (upload_video.html)

    The HTML page below uses JQuery, the plusone.js and upload_video.js JavaScript files shown above, and a CSS file to upload a video file to YouTube.

    Note that if you use this code in your own application, you must replace the value of the data-clientid attribute in the code for the Sign-In Button with your project's client ID. The only valid JavaScript origin for the client ID in the sample code is http://localhost. This means that you could test the sample locally, but it would not work in your production application. See https://developers.google.com/youtube/registering_an_application for information about obtaining a client ID.

    <!doctype html>
    <html>
      <head>
        <meta charset="utf-8">
        <title>YouTube API Uploads via CORS</title>
        <link rel="stylesheet" href="upload_video.css">
        <link rel='stylesheet' href='http://fonts.googleapis.com/css?family=Open+Sans' type='text/css'>
      </head>
      <body>
        <span id="signinButton" class="pre-sign-in">
          <!-- IMPORTANT: Replace the value of the <code>data-clientid</code>
               attribute in the following tag with your project's client ID. -->
          <span
            class="g-signin"
            data-callback="signinCallback"
            data-clientid="1034451067661-h7v9fipq91k83log7c47f49l1o257rl4.apps.googleusercontent.com"
            data-cookiepolicy="single_host_origin"
            data-scope="https://www.googleapis.com/auth/youtube.upload https://www.googleapis.com/auth/youtube">
          </span>
        </span>
    
        <div class="post-sign-in">
          <div>
            <img id="channel-thumbnail">
            <span id="channel-name"></span>
          </div>
    
          <div>
            <label for="title">Title:</label>
            <input id="title" type="text" value="Default Title">
          </div>
          <div>
            <label for="description">Description:</label>
            <textarea id="description">Default description</textarea>
          </div>
          <div>
            <label for="privacy-status">Privacy Status:</label>
            <select id="privacy-status">
              <option>public</option>
              <option>unlisted</option>
              <option>private</option>
            </select>
          </div>
    
          <div>
            <input input type="file" id="file" class="button" accept="video/*">
            <button id="button">Upload Video</button>
          <div class="during-upload">
            <p><span id="percent-transferred"></span>% done (<span id="bytes-transferred"></span>/<span id="total-bytes"></span> bytes)</p>
            <progress id="upload-progress" max="1" value="0"></progress>
          </div>
    
          <div class="post-upload">
            <p>Uploaded video with id <span id="video-id"></span>. Polling for status...</p>
            <ul id="post-upload-status"></ul>
            <div id="player"></div>
          </div>
          <p id="disclaimer">By uploading a video, you certify that you own all rights to the content or that you are authorized by the owner to make the content publicly available on YouTube, and that it otherwise complies with the YouTube Terms of Service located at <a href="http://www.youtube.com/t/terms" target="_blank">http://www.youtube.com/t/terms</a></p>
        </div>
    
        <script src="//ajax.googleapis.com/ajax/libs/jquery/1.10.2/jquery.min.js"></script>
        <script src="//apis.google.com/js/client:plusone.js"></script>
        <script src="cors_upload.js"></script>
        <script src="upload_video.js"></script>
      </body>
    </html>
  • CSS (upload_video.css)

    This sample app also uses the following CSS:

    #channel-image {
      width: 2em;
      height: 2em;
      vertical-align: middle;
    }
    
    #channel-name {
      margin-left: 0.2em;
      margin-right: 0.2em;
    }
    
    #disclaimer {
      font-size: 0.75em;
      color: #aeaeae;
      max-width: 350px;
    }
    
    body {
      font-family: "Open Sans", sans-serif;
      font-size: 1.5em;
    }
    
    .post-sign-in {
      display: none;
    }
    
    .during-upload {
      display: none;
    }
    
    .post-upload {
      display: none;
    }
    
    label {
      display: block;
    }
    
    input[type="text"], textarea, progress {
      font-size: 0.75em;
      width: 15em;
      margin-bottom: 1em;
      padding: 0.5em;
      font-family: "Open Sans", sans-serif;
    }
    
    textarea {
      height: 7em;
    }