Videos: update

Updates a video's metadata. Try it now or see an example.

Quota impact: A call to this method has a quota cost of 50 units in addition to the costs of the specified resource parts.

Request

HTTP request

PUT https://www.googleapis.com/youtube/v3/videos

Authorization

This request requires authorization with at least one of the following scopes (read more about authentication and authorization).

Scope
https://www.googleapis.com/auth/youtubepartner
https://www.googleapis.com/auth/youtube
https://www.googleapis.com/auth/youtube.force-ssl

Parameters

The table below lists the parameters that this query supports. All of the parameters listed are query parameters.

Parameters
Required parameters
part string
The part parameter serves two purposes in this operation. It identifies the properties that the write operation will set as well as the properties that the API response will include.

Note that this method will override the existing values for all of the mutable properties that are contained in any parts that the parameter value specifies. For example, a video's privacy setting is contained in the status part. As such, if your request is updating a private video, and the request's part parameter value includes the status part, the video's privacy setting will be updated to whatever value the request body specifies. If the request body does not specify a value, the existing privacy setting will be removed and the video will revert to the default privacy setting.

In addition, not all parts contain properties that can be set when inserting or updating a video. For example, the statistics object encapsulates statistics that YouTube calculates for a video and does not contain values that you can set or modify. If the parameter value specifies a part that does not contain mutable values, that part will still be included in the API response.

The list below contains the part names that you can include in the parameter value and the quota cost for each part:
  • contentDetails: 2
  • fileDetails: 1
  • id: 0
  • liveStreamingDetails: 2
  • localizations: 2
  • player: 0
  • processingDetails: 1
  • recordingDetails: 2
  • snippet: 2
  • statistics: 2
  • status: 2
  • suggestions: 1
  • topicDetails: 2
Optional parameters
onBehalfOfContentOwner string
This parameter can only be used in a properly authorized request. Note: This parameter is intended exclusively for YouTube content partners.

The onBehalfOfContentOwner parameter indicates that the request's authorization credentials identify a YouTube CMS user who is acting on behalf of the content owner specified in the parameter value. This parameter is intended for YouTube content partners that own and manage many different YouTube channels. It allows content owners to authenticate once and get access to all their video and channel data, without having to provide authentication credentials for each individual channel. The actual CMS account that the user authenticates with must be linked to the specified YouTube content owner.

Request body

Provide a video resource in the request body. For that resource:

  • You must specify a value for these properties:

    • id
    • snippet.title – This property is only required if the request updates the video resource's snippet.
    • snippet.categoryId – This property is only required f the request updates the video resource's snippet.

  • You can set values for these properties:

    • snippet.title
    • snippet.description
    • snippet.tags[]
    • snippet.categoryId
    • snippet.defaultLanguage
    • localizations.(key)
    • localizations.(key).title
    • localizations.(key).description
    • status.embeddable
    • status.license
    • status.publicStatsViewable
    • status.publishAt – If you set a value for this property, you must also set the status.privacyStatus property to private.
    • status.privacyStatus
    • recordingDetails.locationDescription
    • recordingDetails.location.latitude
    • recordingDetails.location.longitude
    • recordingDetails.recordingDate

    If you are submitting an update request, and your request does not specify a value for a property that already has a value, the property's existing value will be deleted.

Response

If successful, this method returns a video resource in the response body.

Examples

Note: The following code samples may not represent all supported programming languages. See the client libraries documentation for a list of supported languages.

Apps Script

This sample finds the active user's uploads, then updates the most recent upload's description by appending a string.
/**
 * This sample finds the active user's uploads, then updates the most recent
 * upload's description by appending a string.
 */
function updateVideo() {
  // 1. Fetch all the channels owned by active user
  var myChannels = YouTube.Channels.list('contentDetails', {mine: true});
  // 2. Iterate through the channels and get the uploads playlist ID
  for (var i = 0; i < myChannels.items.length; i++) {
    var item = myChannels.items[i];
    var uploadsPlaylistId = item.contentDetails.relatedPlaylists.uploads;

    var playlistResponse = YouTube.PlaylistItems.list('snippet', {
      playlistId: uploadsPlaylistId,
      maxResults: 1
    });

    // Get the videoID of the first video in the list
    var video = playlistResponse.items[0];
    var originalDescription = video.snippet.description;
    var updatedDescription = originalDescription + ' Description updated via Google Apps Script';

    video.snippet.description = updatedDescription;

    var resource = {
      snippet: {
        title: video.snippet.title,
        description: updatedDescription,
        categoryId: '22'
      },
      id: video.snippet.resourceId.videoId
    };
    YouTube.Videos.update(resource, 'id,snippet');
  }
}

Java #1

This example uses the Java client library.

/*
 * Copyright (c) 2013 Google Inc.
 *
 * 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.
 */

package com.google.api.services.samples.youtube.cmdline.data;

import com.google.api.client.auth.oauth2.Credential;
import com.google.api.client.googleapis.json.GoogleJsonResponseException;
import com.google.api.services.samples.youtube.cmdline.Auth;
import com.google.api.services.youtube.YouTube;
import com.google.api.services.youtube.model.Video;
import com.google.api.services.youtube.model.VideoListResponse;
import com.google.api.services.youtube.model.VideoSnippet;
import com.google.common.collect.Lists;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.List;

/**
 * Update a video by adding a keyword tag to its metadata. The demo uses the
 * YouTube Data API (v3) and OAuth 2.0 for authorization.
 *
 * @author Ibrahim Ulukaya
 */
public class UpdateVideo {

    /**
     * Define a global instance of a Youtube object, which will be used
     * to make YouTube Data API requests.
     */
    private static YouTube youtube;

    /**
     * Add a keyword tag to a video that the user specifies. Use OAuth 2.0 to
     * authorize the API request.
     *
     * @param args command line args (not used).
     */
    public static void main(String[] args) {

        // This OAuth 2.0 access scope allows for full read/write access to the
        // authenticated user's account.
        List<String> scopes = Lists.newArrayList("https://www.googleapis.com/auth/youtube");

        try {
            // Authorize the request.
            Credential credential = Auth.authorize(scopes, "updatevideo");

            // This object is used to make YouTube Data API requests.
            youtube = new YouTube.Builder(Auth.HTTP_TRANSPORT, Auth.JSON_FACTORY, credential)
                    .setApplicationName("youtube-cmdline-updatevideo-sample").build();

            // Prompt the user to enter the video ID of the video being updated.
            String videoId = getVideoIdFromUser();
            System.out.println("You chose " + videoId + " to update.");

            // Prompt the user to enter a keyword tag to add to the video.
            String tag = getTagFromUser();
            System.out.println("You chose " + tag + " as a tag.");

            // Call the YouTube Data API's youtube.videos.list method to
            // retrieve the resource that represents the specified video.
            YouTube.Videos.List listVideosRequest = youtube.videos().list("snippet").setId(videoId);
            VideoListResponse listResponse = listVideosRequest.execute();

            // Since the API request specified a unique video ID, the API
            // response should return exactly one video. If the response does
            // not contain a video, then the specified video ID was not found.
            List<Video> videoList = listResponse.getItems();
            if (videoList.isEmpty()) {
                System.out.println("Can't find a video with ID: " + videoId);
                return;
            }

            // Extract the snippet from the video resource.
            Video video = videoList.get(0);
            VideoSnippet snippet = video.getSnippet();

            // Preserve any tags already associated with the video. If the
            // video does not have any tags, create a new array. Append the
            // provided tag to the list of tags associated with the video.
            List<String> tags = snippet.getTags();
            if (tags == null) {
                tags = new ArrayList<String>(1);
                snippet.setTags(tags);
            }
            tags.add(tag);

            // Update the video resource by calling the videos.update() method.
            YouTube.Videos.Update updateVideosRequest = youtube.videos().update("snippet", video);
            Video videoResponse = updateVideosRequest.execute();

            // Print information from the updated resource.
            System.out.println("\n================== Returned Video ==================\n");
            System.out.println("  - Title: " + videoResponse.getSnippet().getTitle());
            System.out.println("  - Tags: " + videoResponse.getSnippet().getTags());

        } catch (GoogleJsonResponseException e) {
            System.err.println("GoogleJsonResponseException code: " + e.getDetails().getCode() + " : "
                    + e.getDetails().getMessage());
            e.printStackTrace();
        } catch (IOException e) {
            System.err.println("IOException: " + e.getMessage());
            e.printStackTrace();
        } catch (Throwable t) {
            System.err.println("Throwable: " + t.getMessage());
            t.printStackTrace();
        }
    }

    /*
     * Prompt the user to enter a keyword tag.
     */
    private static String getTagFromUser() throws IOException {

        String keyword = "";

        System.out.print("Please enter a tag for your video: ");
        BufferedReader bReader = new BufferedReader(new InputStreamReader(System.in));
        keyword = bReader.readLine();

        if (keyword.length() < 1) {
            // If the user doesn't enter a tag, use the default value "New Tag."
            keyword = "New Tag";
        }
        return keyword;
    }

    /*
     * Prompt the user to enter a video ID.
     */
    private static String getVideoIdFromUser() throws IOException {

        String videoId = "";

        System.out.print("Please enter a video Id to update: ");
        BufferedReader bReader = new BufferedReader(new InputStreamReader(System.in));
        videoId = bReader.readLine();

        if (videoId.length() < 1) {
            // Exit if the user doesn't provide a value.
            System.out.print("Video Id can't be empty!");
            System.exit(1);
        }

        return videoId;
    }

}

Java #2

The following code sample demonstrates how to use the following API methods to set and retrieve localized metadata for a video:

  • It calls the videos.update method to update the default language of a video's metadata and to add a localized version of this metadata in a selected language.
  • It calls the videos.list method with the hl parameter set to a specific language to retrieve localized metadata in that language.
  • It calls the videos.list method and includes localizations in the part parameter value to retrieve all of the localized metadata for that video.

This example uses the Java client library.

/*
 * Copyright (c) 2015 Google Inc.
 *
 * 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.
 */

package com.google.api.services.samples.youtube.cmdline.data;

import com.google.api.client.auth.oauth2.Credential;
import com.google.api.client.googleapis.json.GoogleJsonResponseException;
import com.google.api.client.util.ArrayMap;
import com.google.api.services.samples.youtube.cmdline.Auth;
import com.google.api.services.youtube.YouTube;
import com.google.api.services.youtube.model.Video;
import com.google.api.services.youtube.model.VideoListResponse;
import com.google.api.services.youtube.model.VideoLocalization;
import com.google.common.collect.Lists;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.List;
import java.util.Map;

/**
 * This sample sets and retrieves localized metadata for a video by:
 *
 * 1. Updating language of the default metadata and setting localized metadata
 *   for a video via "videos.update" method.
 * 2. Getting the localized metadata for a video in a selected language using the
 *   "videos.list" method and setting the "hl" parameter.
 * 3. Listing the localized metadata for a video using the "videos.list" method and
 *   including "localizations" in the "part" parameter.
 *
 * @author Ibrahim Ulukaya
 */
public class VideoLocalizations {

    /**
     * Define a global instance of a YouTube object, which will be used to make
     * YouTube Data API requests.
     */
    private static YouTube youtube;


    /**
     * Set and retrieve localized metadata for a video.
     *
     * @param args command line args (not used).
     */
    public static void main(String[] args) {

        // This OAuth 2.0 access scope allows for full read/write access to the
        // authenticated user's account.
        List<String> scopes = Lists.newArrayList("https://www.googleapis.com/auth/youtube");

        try {
            // Authorize the request.
            Credential credential = Auth.authorize(scopes, "localizations");

            // This object is used to make YouTube Data API requests.
            youtube = new YouTube.Builder(Auth.HTTP_TRANSPORT, Auth.JSON_FACTORY, credential)
                    .setApplicationName("youtube-cmdline-localizations-sample").build();

            // Prompt the user to specify the action of the be achieved.
            String actionString = getActionFromUser();
            System.out.println("You chose " + actionString + ".");
            //Map the user input to the enum values.
            Action action = Action.valueOf(actionString.toUpperCase());

            switch (action) {
                case SET:
                    setVideoLocalization(getId("video"), getDefaultLanguage(),
                            getLanguage(), getMetadata("title"), getMetadata("description"));
                    break;
                case GET:
                    getVideoLocalization(getId("video"), getLanguage());
                    break;
                case LIST:
                    listVideoLocalizations(getId("video"));
                    break;
            }
        } catch (GoogleJsonResponseException e) {
            System.err.println("GoogleJsonResponseException code: " + e.getDetails().getCode()
                    + " : " + e.getDetails().getMessage());
            e.printStackTrace();

        } catch (IOException e) {
            System.err.println("IOException: " + e.getMessage());
            e.printStackTrace();
        } catch (Throwable t) {
            System.err.println("Throwable: " + t.getMessage());
            t.printStackTrace();
        }
    }

    /**
     * Updates a video's default language and sets its localized metadata.
     *
     * @param videoId The id parameter specifies the video ID for the resource
     * that is being updated.
     * @param defaultLanguage The language of the video's default metadata
     * @param language The language of the localized metadata
     * @param title The localized title to be set
     * @param description The localized description to be set
     * @throws IOException
     */
    private static void setVideoLocalization(String videoId, String defaultLanguage,
        String language, String title, String description) throws IOException {
        // Call the YouTube Data API's videos.list method to retrieve videos.
        VideoListResponse videoListResponse = youtube.videos().
            list("snippet,localizations").setId(videoId).execute();

        // Since the API request specified a unique video ID, the API
        // response should return exactly one video. If the response does
        // not contain a video, then the specified video ID was not found.
        List<Video> videoList = videoListResponse.getItems();
        if (videoList.isEmpty()) {
            System.out.println("Can't find a video with ID: " + videoId);
            return;
        }
        Video video = videoList.get(0);

        // Modify video's default language and localizations properties.
        // Ensure that a value is set for the resource's snippet.defaultLanguage property.
        video.getSnippet().setDefaultLanguage(defaultLanguage);

        // Preserve any localizations already associated with the video. If the
        // video does not have any localizations, create a new array. Append the
        // provided localization to the list of localizations associated with the video.
        Map<String, VideoLocalization> localizations = video.getLocalizations();
        if (localizations == null) {
            localizations = new ArrayMap<String, VideoLocalization>();
            video.setLocalizations(localizations);
        }
        VideoLocalization videoLocalization = new VideoLocalization();
        videoLocalization.setTitle(title);
        videoLocalization.setDescription(description);
        localizations.put(language, videoLocalization);

        // Update the video resource by calling the videos.update() method.
        Video videoResponse = youtube.videos().update("snippet,localizations", video)
            .execute();

        // Print information from the API response.
        System.out.println("\n================== Updated Video ==================\n");
        System.out.println("  - ID: " + videoResponse.getId());
        System.out.println("  - Default Language: " +
            videoResponse.getSnippet().getDefaultLanguage());
        System.out.println("  - Title(" + language + "): " +
            videoResponse.getLocalizations().get(language).getTitle());
        System.out.println("  - Description(" + language + "): " +
            videoResponse.getLocalizations().get(language).getDescription());
        System.out.println("\n-------------------------------------------------------------\n");
    }

    /**
     * Returns localized metadata for a video in a selected language.
     * If the localized text is not available in the requested language,
     * this method will return text in the default language.
     *
     * @param videoId The id parameter specifies the video ID for the resource
     * that is being updated.
     * @param language The language of the localized metadata
     * @throws IOException
     */
    private static void getVideoLocalization(String videoId, String language) throws IOException {
        // Call the YouTube Data API's videos.list method to retrieve videos.
        VideoListResponse videoListResponse = youtube.videos().
            list("snippet").setId(videoId).set("hl", language).execute();

        // Since the API request specified a unique video ID, the API
        // response should return exactly one video. If the response does
        // not contain a video, then the specified video ID was not found.
        List<Video> videoList = videoListResponse.getItems();
        if (videoList.isEmpty()) {
            System.out.println("Can't find a video with ID: " + videoId);
            return;
        }
        Video video = videoList.get(0);

        // Print information from the API response.
        System.out.println("\n================== Video ==================\n");
        System.out.println("  - ID: " + video.getId());
        System.out.println("  - Title(" + language + "): " +
            video.getLocalizations().get(language).getTitle());
        System.out.println("  - Description(" + language + "): " +
            video.getLocalizations().get(language).getDescription());
        System.out.println("\n-------------------------------------------------------------\n");
    }

    /**
     * Returns a list of localized metadata for a video.
     *
     * @param videoId The id parameter specifies the video ID for the resource
     * that is being updated.
     * @throws IOException
     */
    private static void listVideoLocalizations(String videoId) throws IOException {
        // Call the YouTube Data API's videos.list method to retrieve videos.
        VideoListResponse videoListResponse = youtube.videos().
            list("snippet,localizations").setId(videoId).execute();

        // Since the API request specified a unique video ID, the API
        // response should return exactly one video. If the response does
        // not contain a video, then the specified video ID was not found.
        List<Video> videoList = videoListResponse.getItems();
        if (videoList.isEmpty()) {
            System.out.println("Can't find a video with ID: " + videoId);
            return;
        }
        Video video = videoList.get(0);
        Map<String, VideoLocalization> localizations = video.getLocalizations();

        // Print information from the API response.
        System.out.println("\n================== Video ==================\n");
        System.out.println("  - ID: " + video.getId());
        for (String language : localizations.keySet()) {
            System.out.println("  - Title(" + language + "): " +
                localizations.get(language).getTitle());
            System.out.println("  - Description(" + language + "): " +
                localizations.get(language).getDescription());
        }
        System.out.println("\n-------------------------------------------------------------\n");
    }

    /*
     * Prompt the user to enter a resource ID. Then return the ID.
     */
    private static String getId(String resource) throws IOException {

        String id = "";

        System.out.print("Please enter a " + resource + " id: ");
        BufferedReader bReader = new BufferedReader(new InputStreamReader(System.in));
        id = bReader.readLine();

        System.out.println("You chose " + id + " for localizations.");
        return id;
    }

    /*
     * Prompt the user to enter the localized metadata. Then return the metadata.
     */
    private static String getMetadata(String type) throws IOException {

        String metadata = "";

        System.out.print("Please enter a localized " + type + ": ");
        BufferedReader bReader = new BufferedReader(new InputStreamReader(System.in));
        metadata = bReader.readLine();

        if (metadata.length() < 1) {
            // If nothing is entered, defaults to type.
          metadata = type + "(localized)";
        }

        System.out.println("You chose " + metadata + " as localized "+ type + ".");
        return metadata;
    }

    /*
     * Prompt the user to enter the language for the resource's default metadata.
     * Then return the language.
     */
    private static String getDefaultLanguage() throws IOException {

        String defaultlanguage = "";

        System.out.print("Please enter the language for the resource's default metadata: ");
        BufferedReader bReader = new BufferedReader(new InputStreamReader(System.in));
        defaultlanguage = bReader.readLine();

        if (defaultlanguage.length() < 1) {
            // If nothing is entered, defaults to "en".
          defaultlanguage = "en";
        }

        System.out.println("You chose " + defaultlanguage +
            " as the language for the resource's default metadata.");
        return defaultlanguage;
    }

    /*
     * Prompt the user to enter a language for the localized metadata. Then return the language.
     */
    private static String getLanguage() throws IOException {

        String language = "";

        System.out.print("Please enter the localized metadata language: ");
        BufferedReader bReader = new BufferedReader(new InputStreamReader(System.in));
        language = bReader.readLine();

        if (language.length() < 1) {
            // If nothing is entered, defaults to "de".
            language = "de";
        }

        System.out.println("You chose " + language + " as the localized metadata language.");
        return language;
    }

    /*
     * Prompt the user to enter an action. Then return the action.
     */
    private static String getActionFromUser() throws IOException {

        String action = "";

        System.out.print("Please choose action to be accomplished: ");
        System.out.print("Options are: 'set', 'get' and 'list' ");
        BufferedReader bReader = new BufferedReader(new InputStreamReader(System.in));
        action = bReader.readLine();

        return action;
    }

    public enum Action {
      SET,
      GET,
      LIST
    }
}

PHP #1

This code sample demonstrates how to add tags into an existing video.

The following code sample calls the API's youtube.videos.list method with id parameter set to videoId to get the video object. Using this video object, the sample gets the list of tags and appends new tags at the end of this list. Finally, the code calls youtube.videos.update method with updated video object to persist these changes on YouTube.

This example uses the PHP client library.

<?php

/**
 * This sample adds new tags to a YouTube video by:
 *
 * 1. Retrieving the video resource by calling the "youtube.videos.list" method
 *    and setting the "id" parameter
 * 2. Appending new tags to the video resource's snippet.tags[] list
 * 3. Updating the video resource by calling the youtube.videos.update method.
 *
 * @author Ibrahim Ulukaya
*/

// Call set_include_path() as needed to point to your client library.
require_once 'Google/Client.php';
require_once 'Google/Service/YouTube.php';
session_start();

/*
 * You can acquire an OAuth 2.0 client ID and client secret from the
 * Google Developers Console <https://console.developers.google.com/>
 * For more information about using OAuth 2.0 to access Google APIs, please see:
 * <https://developers.google.com/youtube/v3/guides/authentication>
 * Please ensure that you have enabled the YouTube Data API for your project.
 */
$OAUTH2_CLIENT_ID = 'REPLACE_ME';
$OAUTH2_CLIENT_SECRET = 'REPLACE_ME';

$client = new Google_Client();
$client->setClientId($OAUTH2_CLIENT_ID);
$client->setClientSecret($OAUTH2_CLIENT_SECRET);
$client->setScopes('https://www.googleapis.com/auth/youtube');
$redirect = filter_var('http://' . $_SERVER['HTTP_HOST'] . $_SERVER['PHP_SELF'],
    FILTER_SANITIZE_URL);
$client->setRedirectUri($redirect);

// Define an object that will be used to make all API requests.
$youtube = new Google_Service_YouTube($client);

if (isset($_GET['code'])) {
  if (strval($_SESSION['state']) !== strval($_GET['state'])) {
    die('The session state did not match.');
  }

  $client->authenticate($_GET['code']);
  $_SESSION['token'] = $client->getAccessToken();
  header('Location: ' . $redirect);
}

if (isset($_SESSION['token'])) {
  $client->setAccessToken($_SESSION['token']);
}

// Check to ensure that the access token was successfully acquired.
if ($client->getAccessToken()) {
  try{

    // REPLACE this value with the video ID of the video being updated.
    $videoId = "VIDEO_ID";

    // Call the API's videos.list method to retrieve the video resource.
    $listResponse = $youtube->videos->listVideos("snippet",
        array('id' => $videoId));

    // If $listResponse is empty, the specified video was not found.
    if (empty($listResponse)) {
      $htmlBody .= sprintf('<h3>Can\'t find a video with video id: %s</h3>', $videoId);
    } else {
      // Since the request specified a video ID, the response only
      // contains one video resource.
      $video = $listResponse[0];
      $videoSnippet = $video['snippet'];
      $tags = $videoSnippet['tags'];

      // Preserve any tags already associated with the video. If the video does
      // not have any tags, create a new list. Replace the values "tag1" and
      // "tag2" with the new tags you want to associate with the video.
      if (is_null($tags)) {
        $tags = array("tag1", "tag2");
      } else {
        array_push($tags, "tag1", "tag2");
      }

      // Set the tags array for the video snippet
      $videoSnippet['tags'] = $tags;

      // Update the video resource by calling the videos.update() method.
      $updateResponse = $youtube->videos->update("snippet", $video);

      $responseTags = $updateResponse['snippet']['tags'];


    $htmlBody .= "<h3>Video Updated</h3><ul>";
    $htmlBody .= sprintf('<li>Tags "%s" and "%s" added for video %s (%s) </li>',
        array_pop($responseTags), array_pop($responseTags),
        $videoId, $video['snippet']['title']);

    $htmlBody .= '</ul>';
  }
    } catch (Google_Service_Exception $e) {
      $htmlBody .= sprintf('<p>A service error occurred: <code>%s</code></p>',
          htmlspecialchars($e->getMessage()));
    } catch (Google_Exception $e) {
      $htmlBody .= sprintf('<p>An client error occurred: <code>%s</code></p>',
          htmlspecialchars($e->getMessage()));
    }

    $_SESSION['token'] = $client->getAccessToken();
    } else {
      // If the user hasn't authorized the app, initiate the OAuth flow
      $state = mt_rand();
      $client->setState($state);
      $_SESSION['state'] = $state;

      $authUrl = $client->createAuthUrl();
      $htmlBody = <<<END
  <h3>Authorization Required</h3>
  <p>You need to <a href="$authUrl">authorize access</a> before proceeding.<p>
END;
    }
    ?>

    <!doctype html>
    <html>
    <head>
    <title>Video Updated</title>
    </head>
    <body>
      <?=$htmlBody?>
    </body>
    </html>

PHP #2

The following code sample displays a web form that uses the API to set and retrieve localized metadata for a video:

  • It calls the videos.update method to update the default language of a video's metadata and to add a localized version of this metadata in a selected language.
  • It calls the videos.list method with the hl parameter set to a specific language to retrieve localized metadata in that language.
  • It calls the videos.list method and includes localizations in the part parameter value to retrieve all of the localized metadata for that video.

This example uses the PHP client library.

<?php

/**
 * This sample sets and retrieves localized metadata for a video by:
 *
 * 1. Updating language of the default metadata and setting localized metadata
 *   for a video via "videos.update" method.
 * 2. Getting the localized metadata for a video in a selected language using the
 *   "videos.list" method and setting the "hl" parameter.
 * 3. Listing the localized metadata for a video using the "videos.list" method and
 *   including "localizations" in the "part" parameter.
 *
 * @author Ibrahim Ulukaya
 */

$htmlBody = <<<END
<form method="GET">
  <div>
    Action:
    <select id="action" name="action">
      <option value="set">Set Localization - Fill in: video ID, default language, language, title and description</option>
      <option value="get">Get Localization- Fill in: video ID, language</option>
      <option value="list">List Localizations - Fill in: video ID, language</option>
    </select>
  </div>
  <br>
  <div>
    Video ID: <input type="text" id="videoId" name="videoId" placeholder="Enter Video ID">
  </div>
  <br>
  <div>
    Default Language: <input type="text" id="defaultLanguage" name="defaultLanguage" placeholder="Enter Default Language (BCP-47 language code)">
  </div>
  <br>
  <div>
    Language: <input type="text" id="language" name="language" placeholder="Enter Local Language (BCP-47 language code)">
  </div>
  <br>
  <div>
    Title: <input type="text" id="title" name="title" placeholder="Enter Title">
  </div>
  <br>
  <div>
    Description: <input type="text" id="description" name="description" placeholder="Enter Description">
  </div>
  <br>
  <input type="submit" value="GO!">
</form>
END;

// Call set_include_path() as needed to point to your client library.
  require_once 'Google/Client.php';
  require_once 'Google/Service/YouTube.php';
  session_start();


/*
 * You can acquire an OAuth 2.0 client ID and client secret from the
 * Google Developers Console <https://console.developers.google.com/>
 * For more information about using OAuth 2.0 to access Google APIs, please see:
 * <https://developers.google.com/youtube/v3/guides/authentication>
 * Please ensure that you have enabled the YouTube Data API for your project.
 */
$OAUTH2_CLIENT_ID = 'REPLACE_ME';
$OAUTH2_CLIENT_SECRET = 'REPLACE_ME';

$action = $_GET['action'];
$videoId = $_GET['videoId'];
$language = $_GET['language'];
$defaultLanguage = $_GET['defaultLanguage'];
$title = $_GET['title'];
$description = $_GET['description'];

$client = new Google_Client();
$client->setClientId($OAUTH2_CLIENT_ID);
$client->setClientSecret($OAUTH2_CLIENT_SECRET);

/*
 * This OAuth 2.0 access scope allows for full read/write access to the
 * authenticated user's account.
 */
$client->setScopes('https://www.googleapis.com/auth/youtube');
$redirect = filter_var('http://' . $_SERVER['HTTP_HOST'] . $_SERVER['PHP_SELF'],
    FILTER_SANITIZE_URL);
$client->setRedirectUri($redirect);

// Define an object that will be used to make all API requests.
$youtube = new Google_Service_YouTube($client);

if (isset($_GET['code'])) {
  if (strval($_SESSION['state']) !== strval($_GET['state'])) {
    die('The session state did not match.');
  }

  $client->authenticate($_GET['code']);
  $_SESSION['token'] = $client->getAccessToken();
  header('Location: ' . $redirect);
}

if (isset($_SESSION['token'])) {
  $client->setAccessToken($_SESSION['token']);
}

// Check to ensure that the access token was successfully acquired.
if ($client->getAccessToken()) {
  // This code executes if the user enters an action in the form
  // and submits the form. Otherwise, the page displays the form above.
  if ($_GET['action']) {
    try {
      switch ($action) {
        case 'set':
          setVideoLocalization($youtube, $videoId, $defaultLanguage,
              $language, $title, $description, $htmlBody);
          break;
        case 'get':
          getVideoLocalization($youtube, $videoId, $language, $htmlBody);
          break;
        case 'list':
          listVideoLocalizations($youtube, $videoId, $htmlBody);
          break;
      }
    } catch (Google_Service_Exception $e) {
      $htmlBody .= sprintf('<p>A service error occurred: <code>%s</code></p>',
          htmlspecialchars($e->getMessage()));
    } catch (Google_Exception $e) {
      $htmlBody .= sprintf('<p>An client error occurred: <code>%s</code></p>',
          htmlspecialchars($e->getMessage()));
    }
  }
  $_SESSION['token'] = $client->getAccessToken();
} else {
  // If the user hasn't authorized the app, initiate the OAuth flow
  $state = mt_rand();
  $client->setState($state);
  $_SESSION['state'] = $state;

  $authUrl = $client->createAuthUrl();
  $htmlBody = <<<END
  <h3>Authorization Required</h3>
  <p>You need to <a href="$authUrl">authorize access</a> before proceeding.<p>
END;
}


/**
 * Updates a video's default language and sets its localized metadata.
 *
 * @param Google_Service_YouTube $youtube YouTube service object.
 * @param string $videoId The id parameter specifies the video ID for the resource
 * that is being updated.
 * @param string $defaultLanguage The language of the video's default metadata
 * @param string $language The language of the localized metadata
 * @param string $title The localized title to be set
 * @param string $description The localized description to be set
 * @param $htmlBody - html body.
 */
function setVideoLocalization(Google_Service_YouTube $youtube, $videoId, $defaultLanguage,
    $language, $title, $description, &$htmlBody) {
  // Call the YouTube Data API's videos.list method to retrieve videos.
  $videos = $youtube->videos->listVideos("snippet,localizations", array(
      'id' => $videoId
  ));

  // If $videos is empty, the specified video was not found.
  if (empty($videos)) {
    $htmlBody .= sprintf('<h3>Can\'t find a video with video id: %s</h3>', $videoId);
  } else {
    // Since the request specified a video ID, the response only
    // contains one video resource.
    $updateVideo = $videos[0];

    // Modify video's default language and localizations properties.
    // Ensure that a value is set for the resource's snippet.defaultLanguage property.
    $updateVideo['snippet']['defaultLanguage'] = $defaultLanguage;
    $localizations = $updateVideo['localizations'];

    if (is_null($localizations)) {
      $localizations = array();
    }
    $localizations[$language] = array('title' => $title, 'description' => $description);
    $updateVideo['localizations'] = $localizations;

    // Call the YouTube Data API's videos.update method to update an existing video.
    $videoUpdateResponse = $youtube->videos->update("snippet,localizations", $updateVideo);

    $htmlBody .= "<h2>Updated video</h2><ul>";
    $htmlBody .= sprintf('<li>(%s) default language: %s</li>', $videoId,
        $videoUpdateResponse['snippet']['defaultLanguage']);
    $htmlBody .= sprintf('<li>title(%s): %s</li>', $language,
        $videoUpdateResponse['localizations'][$language]['title']);
    $htmlBody .= sprintf('<li>description(%s): %s</li>', $language,
        $videoUpdateResponse['localizations'][$language]['description']);
    $htmlBody .= '</ul>';
  }
}

/**
 * Returns localized metadata for a video in a selected language.
 * If the localized text is not available in the requested language,
 * this method will return text in the default language.
 *
 * @param Google_Service_YouTube $youtube YouTube service object.
 * @param string $videoId The videoId parameter instructs the API to return the
 * localized metadata for the video specified by the video id.
 * @param string language The language of the localized metadata.
 * @param $htmlBody - html body.
 */
function getVideoLocalization(Google_Service_YouTube $youtube, $videoId, $language, &$htmlBody) {
  // Call the YouTube Data API's videos.list method to retrieve videos.
  $videos = $youtube->videos->listVideos("snippet", array(
      'id' => $videoId,
      'hl' => $language
  ));

  // If $videos is empty, the specified video was not found.
  if (empty($videos)) {
    $htmlBody .= sprintf('<h3>Can\'t find a video with video id: %s</h3>', $videoId);
  } else {
    // Since the request specified a video ID, the response only
    // contains one video resource.
    $localized = $videos[0]["snippet"]["localized"];

    $htmlBody .= "<h3>Video</h3><ul>";
    $htmlBody .= sprintf('<li>title(%s): %s</li>', $language, $localized['title']);
    $htmlBody .= sprintf('<li>description(%s): %s</li>', $language, $localized['description']);
    $htmlBody .= '</ul>';
  }
}

/**
 * Returns a list of localized metadata for a video.
 *
 * @param Google_Service_YouTube $youtube YouTube service object.
 * @param string $videoId The videoId parameter instructs the API to return the
 * localized metadata for the video specified by the video id.
 * @param $htmlBody - html body.
 */
function listVideoLocalizations(Google_Service_YouTube $youtube, $videoId, &$htmlBody) {
  // Call the YouTube Data API's videos.list method to retrieve videos.
  $videos = $youtube->videos->listVideos("snippet,localizations", array(
      'id' => $videoId
  ));

  // If $videos is empty, the specified video was not found.
  if (empty($videos)) {
    $htmlBody .= sprintf('<h3>Can\'t find a video with video id: %s</h3>', $videoId);
  } else {
    // Since the request specified a video ID, the response only
    // contains one video resource.
    $localizations = $videos[0]["localizations"];

    $htmlBody .= "<h3>Video</h3><ul>";
    foreach ($localizations as $language => $localization) {
      $htmlBody .= sprintf('<li>title(%s): %s</li>', $language, $localization['title']);
      $htmlBody .= sprintf('<li>description(%s): %s</li>', $language, $localization['description']);
    }
    $htmlBody .= '</ul>';
  }
}

?>

<!doctype html>
<html>
<head>
<title>Set and retrieve localized metadata for a video</title>
</head>
<body>
  <?=$htmlBody?>
</body>
</html>

Python #1

The following code sample calls the API's videos.update method to update a video owned by the channel authorizing the request.

This example uses the Python client library.

#!/usr/bin/python

import httplib2
import os
import sys

from apiclient.discovery import build
from apiclient.errors import HttpError
from oauth2client.client import flow_from_clientsecrets
from oauth2client.file import Storage
from oauth2client.tools import argparser, run_flow


# The CLIENT_SECRETS_FILE variable specifies the name of a file that contains
# the OAuth 2.0 information for this application, including its client_id and
# client_secret. You can acquire an OAuth 2.0 client ID and client secret from
# the Google Developers Console at
# https://console.developers.google.com/.
# Please ensure that you have enabled the YouTube Data API for your project.
# For more information about using OAuth2 to access the YouTube Data API, see:
#   https://developers.google.com/youtube/v3/guides/authentication
# For more information about the client_secrets.json file format, see:
#   https://developers.google.com/api-client-library/python/guide/aaa_client_secrets
CLIENT_SECRETS_FILE = "client_secrets.json"

# This OAuth 2.0 access scope allows for full read/write access to the
# authenticated user's account.
YOUTUBE_READ_WRITE_SCOPE = "https://www.googleapis.com/auth/youtube"
YOUTUBE_API_SERVICE_NAME = "youtube"
YOUTUBE_API_VERSION = "v3"

# This variable defines a message to display if the CLIENT_SECRETS_FILE is
# missing.
MISSING_CLIENT_SECRETS_MESSAGE = """
WARNING: Please configure OAuth 2.0

To make this sample run you will need to populate the client_secrets.json file
found at:

   %s

with information from the Developers Console
https://console.developers.google.com/

For more information about the client_secrets.json file format, please visit:
https://developers.google.com/api-client-library/python/guide/aaa_client_secrets
""" % os.path.abspath(os.path.join(os.path.dirname(__file__),
                                   CLIENT_SECRETS_FILE))

def get_authenticated_service(args):
  flow = flow_from_clientsecrets(CLIENT_SECRETS_FILE,
    scope=YOUTUBE_READ_WRITE_SCOPE,
    message=MISSING_CLIENT_SECRETS_MESSAGE)

  storage = Storage("%s-oauth2.json" % sys.argv[0])
  credentials = storage.get()

  if credentials is None or credentials.invalid:
    credentials = run_flow(flow, storage, args)

  return build(YOUTUBE_API_SERVICE_NAME, YOUTUBE_API_VERSION,
    http=credentials.authorize(httplib2.Http()))

def update_video(youtube, options):
  # Call the API's videos.list method to retrieve the video resource.
  videos_list_response = youtube.videos().list(
    id=options.video_id,
    part='snippet'
  ).execute()

  # If the response does not contain an array of "items" then the video was
  # not found.
  if not videos_list_response["items"]:
    print "Video '%s' was not found." % options.video_id
    sys.exit(1)

  # Since the request specified a video ID, the response only contains one
  # video resource. This code extracts the snippet from that resource.
  videos_list_snippet = videos_list_response["items"][0]["snippet"]

  # Preserve any tags already associated with the video. If the video does
  # not have any tags, create a new array. Append the provided tag to the
  # list of tags associated with the video.
  if "tags" not in  videos_list_snippet:
    videos_list_snippet["tags"] = []
  videos_list_snippet["tags"].append(options.tag)

  # Update the video resource by calling the videos.update() method.
  videos_update_response = youtube.videos().update(
    part='snippet',
    body=dict(
      snippet=videos_list_snippet,
      id=options.video_id
    )).execute()

if __name__ == "__main__":
  argparser.add_argument("--video-id", help="ID of video to update.",
    required=True)
  argparser.add_argument("--tag", default="youtube",
    help="Additional tag to add to video.")
  args = argparser.parse_args()

  youtube = get_authenticated_service(args)
  try:
    update_video(youtube, args)
  except HttpError, e:
    print "An HTTP error %d occurred:\n%s" % (e.resp.status, e.content)
  else:
    print "Tag '%s' was added to video id '%s'." % (args.tag, args.video_id)

Python #2

The following code sample demonstrates how to use the following API methods to set and retrieve localized metadata for a video:

  • It calls the videos.update method to update the default language of a video's metadata and to add a localized version of this metadata in a selected language.
  • It calls the videos.list method with the hl parameter set to a specific language to retrieve localized metadata in that language.
  • It calls the videos.list method and includes localizations in the part parameter value to retrieve all of the localized metadata for that video.

This example uses the Python client library.

#!/usr/bin/python

# Usage example:
# python video_localizations.py --action='<action>' --video_id='<video_id>' --default_language='<default_language>' --language='<language>' --title='<title>' --description='<description>'

import httplib2
import os
import sys

from apiclient.discovery import build
from apiclient.errors import HttpError
from oauth2client.client import flow_from_clientsecrets
from oauth2client.file import Storage
from oauth2client.tools import argparser, run_flow


# The CLIENT_SECRETS_FILE variable specifies the name of a file that contains

# the OAuth 2.0 information for this application, including its client_id and
# client_secret. You can acquire an OAuth 2.0 client ID and client secret from
# the Google Developers Console at
# https://console.developers.google.com/.
# Please ensure that you have enabled the YouTube Data API for your project.
# For more information about using OAuth2 to access the YouTube Data API, see:
#   https://developers.google.com/youtube/v3/guides/authentication
# For more information about the client_secrets.json file format, see:
#   https://developers.google.com/api-client-library/python/guide/aaa_client_secrets
CLIENT_SECRETS_FILE = "client_secrets.json"

# This OAuth 2.0 access scope allows for full read/write access to the
# authenticated user's account.
YOUTUBE_READ_WRITE_SCOPE = "https://www.googleapis.com/auth/youtube"
YOUTUBE_API_SERVICE_NAME = "youtube"
YOUTUBE_API_VERSION = "v3"

# This variable defines a message to display if the CLIENT_SECRETS_FILE is
# missing.
MISSING_CLIENT_SECRETS_MESSAGE = """
WARNING: Please configure OAuth 2.0

To make this sample run you will need to populate the client_secrets.json file
found at:
   %s
with information from the APIs Console
https://console.developers.google.com

For more information about the client_secrets.json file format, please visit:
https://developers.google.com/api-client-library/python/guide/aaa_client_secrets
""" % os.path.abspath(os.path.join(os.path.dirname(__file__),
                                   CLIENT_SECRETS_FILE))

# Authorize the request and store authorization credentials.
def get_authenticated_service(args):
  flow = flow_from_clientsecrets(CLIENT_SECRETS_FILE, scope=YOUTUBE_READ_WRITE_SCOPE,
    message=MISSING_CLIENT_SECRETS_MESSAGE)

  storage = Storage("%s-oauth2.json" % sys.argv[0])
  credentials = storage.get()

  if credentials is None or credentials.invalid:
    credentials = run_flow(flow, storage, args)

  return build(YOUTUBE_API_SERVICE_NAME, YOUTUBE_API_VERSION,
    http=credentials.authorize(httplib2.Http()))


# Call the API's videos.update method to update an existing video's default language,
# localized title and description in a specific language.
def set_video_localization(youtube, video_id, default_language, language, title, description):
  results = youtube.videos().list(
    part="snippet,localizations",
    id=video_id
  ).execute()

  video = results["items"][0]
  # Ensure that a value is set for the resource's snippet.defaultLanguage property.
  video["snippet"]["defaultLanguage"] = default_language
  if "localizations" not in video:
    video["localizations"] = {}
  video["localizations"][language] = {
    "title": title,
    "description": description
  }

  update_result = youtube.videos().update(
    part="snippet,localizations",
    body=video
  ).execute()

  localization = update_result["localizations"][language]

  print ("Updated video '%s' default language to '%s', localized title to '%s'"
         " and description to '%s' in language '%s'"
          % (video_id, default_language, localization["title"], localization["description"], language))


# Call the API's videos.list method to retrieve an existing video localization.
# If the localized text is not available in the requested language,
# this method will return text in the default language.
def get_video_localization(youtube, video_id, language):
  results = youtube.videos().list(
    part="snippet",
    id=video_id,
    hl=language
  ).execute()

  # The localized object contains localized text if the hl parameter specified
  # a language for which localized text is available. Otherwise, the localized
  # object will contain metadata in the default language.
  localized = results["items"][0]["snippet"]["localized"]

  print ("Video title is '%s' and description is '%s' in language '%s'"
         % (localized["title"], localized["description"], language))


# Call the API's videos.list method to list the existing video localizations.
def list_video_localizations(youtube, video_id):
  results = youtube.videos().list(
    part="snippet,localizations",
    id=video_id
  ).execute()

  localizations = results["items"][0]["localizations"]

  for language, localization in localizations.iteritems():
    print ("Video title is '%s' and description is '%s' in language '%s'"
           % (localization["title"], localization["description"], language))


if __name__ == "__main__":
  # The "action" option specifies the action to be processed.
  argparser.add_argument("--action", help="Action")
  # The "video_id" option specifies the ID of the selected YouTube video.
  argparser.add_argument("--video_id",
    help="ID for video for which the localization will be applied.")
  # The "default_language" option specifies the language of the video's default metadata.
  argparser.add_argument("--default_language", help="Default language of the video to update.",
    default="en")
  # The "language" option specifies the language of the localization that is being processed.
  argparser.add_argument("--language", help="Language of the localization.", default="de")
  # The "title" option specifies the localized title of the video to be set.
  argparser.add_argument("--title", help="Localized title of the video to be set.",
    default="Localized Title")
  # The "description" option specifies the localized description of the video to be set.
  argparser.add_argument("--description", help="Localized description of the video to be set.",
    default="Localized Description")

  args = argparser.parse_args()

  if not args.video_id:
    exit("Please specify video id using the --video_id= parameter.")

  youtube = get_authenticated_service(args)
  try:
    if args.action == 'set':
      set_video_localization(youtube, args.video_id, args.default_language, args.language, args.title, args.description)
    elif args.action == 'get':
      get_video_localization(youtube, args.video_id, args.language)
    elif args.action == 'list':
      list_video_localizations(youtube, args.video_id)
    else:
      exit("Please specify a valid action using the --action= parameter.")
  except HttpError, e:
    print "An HTTP error %d occurred:\n%s" % (e.resp.status, e.content)
  else:
    print "Set and retrieved localized metadata for a video."

Errors

The table below identifies error messages that the API could return in response to a call to this method. Please see the error message documentation for more detail.

Error type Error detail Description
badRequest (400) defaultLanguageNotSet The API request is trying to add localized video details without specifying the default language of the video details.
badRequest (400) invalidDefaultBroadcastPrivacySetting The request attempts to set an invalid privacy setting for the default broadcast.
badRequest (400) invalidRequest The request metadata is invalid. This error occurs if the request updates the snippet part of a video resource but does not set a value for both the snippet.title and snippet.categoryId properties.
forbidden (403) forbidden
forbidden (403) forbiddenLicenseSetting The request attempts to set an invalid license for the video.
forbidden (403) forbiddenPrivacySetting The request attempts to set an invalid privacy setting for the video.
notFound (404) videoNotFound The video that you are trying to update cannot be found. Check the value of the id field in the request body to ensure that it is correct.

Try it!

Use the API Explorer to call this method on live data and see the API request and response.