Channels: update

Updates a channel's metadata. Note that this method currently only supports updates to the channel resource's brandingSettings and invideoPromotion objects and their child properties. 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/channels

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 following table 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.

The API currently only allows the parameter value to be set to either brandingSettings, invideoPromotion, or localizations. (You can only update any one of those parts with a single request.)

Note that this method overrides the existing values for all of the mutable properties that are contained in the part that the parameter value specifies.
Optional parameters
onBehalfOfContentOwner string
This parameter can only be used in a properly authorized request. The onBehalfOfContentOwner parameter indicates that the authenticated user 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 needs to be linked to the specified YouTube content owner.

Request body

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

  • You must specify a value for these properties:

    • id

  • You can set values for these properties:

    • brandingSettings.channel.country
    • brandingSettings.channel.description
    • brandingSettings.channel.defaultLanguage
    • brandingSettings.channel.defaultTab
    • brandingSettings.channel.featuredChannelsTitle
    • brandingSettings.channel.featuredChannelsUrls[]
    • brandingSettings.channel.keywords
    • brandingSettings.channel.moderateComments
    • brandingSettings.channel.profileColor
    • brandingSettings.channel.showRelatedChannels
    • brandingSettings.channel.showBrowseView
    • brandingSettings.channel.trackingAnalyticsAccountId
    • brandingSettings.channel.unsubscribedTrailer
    • brandingSettings.image.bannerExternalUrl
    • brandingSettings.image.trackingImageUrl
    • brandingSettings.image.watchIconImageUrl
    • invideoPromotion.position.type
    • invideoPromotion.position.cornerPosition
    • invideoPromotion.defaultTiming.type
    • invideoPromotion.defaultTiming.offsetMs
    • invideoPromotion.items[].id.type
    • invideoPromotion.items[].id.videoId
    • invideoPromotion.items[].id.websiteUrl
    • invideoPromotion.items[].timing.type
    • invideoPromotion.items[].timing.offsetMs
    • invideoPromotion.items[].customMessage
    • invideoPromotion.items[].promotedByContentOwner
    • localizations.(key)
    • localizations.(key).title
    • localizations.(key).description

    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 channel 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.

Java #1

This sample calls the API's channels.update method to set invideoPromotion properties for the channel.

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.client.http.InputStreamContent;
import com.google.api.services.samples.youtube.cmdline.Auth;
import com.google.api.services.youtube.YouTube;
import com.google.api.services.youtube.model.*;
import com.google.common.collect.Lists;

import java.io.IOException;
import java.math.BigInteger;
import java.util.List;

/**
 * Add a featured video to a channel.
 *
 * @author Ikai Lan <ikai@google.com>
 */
public class InvideoProgramming {

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

    /**
     * This sample video introduces WebM on YouTube Developers Live.
     */
    private static final String FEATURED_VIDEO_ID = "w4eiUiauo2w";

    /**
     * This code sample demonstrates different ways that the API can be used to
     * promote your channel content. It includes code for the following tasks:
     * <ol>
     * <li>Feature a video.</li>
     * <li>Feature a link to a social media channel.</li>
     * <li>Set a watermark for videos on your channel.</li>
     * </ol>
     *
     * @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, "invideoprogramming");

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

            // Construct a request to retrieve the current user's channel ID.
            // In the API response, only include channel information needed for
            // this use case. The channel's uploads playlist identifies the
            // channel's most recently uploaded video.
            // See https://developers.google.com/youtube/v3/docs/channels/list
            ChannelListResponse channelListResponse = youtube.channels().list("id,contentDetails")
                    .setMine(true)
                    .setFields("items(contentDetails/relatedPlaylists/uploads,id)")
                    .execute();

            // The user's default channel is the first item in the list. If the
            // user does not have a channel, this code should throw a
            // GoogleJsonResponseException explaining the issue.
            Channel myChannel = channelListResponse.getItems().get(0);
            String channelId = myChannel.getId();

            // The promotion appears 15000ms (15 seconds) before the video ends.
            InvideoTiming invideoTiming = new InvideoTiming();
            invideoTiming.setOffsetMs(BigInteger.valueOf(15000l));
            invideoTiming.setType("offsetFromEnd");

            // This is one type of promotion and promotes a video.
            PromotedItemId promotedItemId = new PromotedItemId();
            promotedItemId.setType("video");
            promotedItemId.setVideoId(FEATURED_VIDEO_ID);

            // Set a custom message providing additional information about the
            // promoted video or your channel.
            PromotedItem promotedItem = new PromotedItem();
            promotedItem.setCustomMessage("Check out this video about WebM!");
            promotedItem.setId(promotedItemId);

            // Construct an object representing the invideo promotion data, and
            // add it to the channel.
            InvideoPromotion invideoPromotion = new InvideoPromotion();
            invideoPromotion.setDefaultTiming(invideoTiming);
            invideoPromotion.setItems(Lists.newArrayList(promotedItem));

            Channel channel = new Channel();
            channel.setId(channelId);
            channel.setInvideoPromotion(invideoPromotion);

            Channel updateChannelResponse = youtube.channels()
                    .update("invideoPromotion", channel)
                    .execute();

            // Print data from the API response.
            System.out.println("\n================== Updated Channel Information ==================\n");
            System.out.println("\t- Channel ID: " + updateChannelResponse.getId());

            InvideoPromotion promotions = updateChannelResponse.getInvideoPromotion();
            promotedItem = promotions.getItems().get(0); // We only care about the first item
            System.out.println("\t- Invideo promotion video ID: " + promotedItem
                    .getId()
                    .getVideoId());
            System.out.println("\t- Promotion message: " + promotedItem.getCustomMessage());

            // In-video programming can also be used to feature links to
            // associated websites, merchant sites, or social networking sites.
            // The code below overrides the promotional video set above by
            // featuring a link to the YouTube Developers Twitter feed.
            PromotedItemId promotedTwitterFeed = new PromotedItemId();
            promotedTwitterFeed.setType("website");
            promotedTwitterFeed.setWebsiteUrl("https://twitter.com/youtubedev");

            promotedItem = new PromotedItem();
            promotedItem.setCustomMessage("Follow us on Twitter!");
            promotedItem.setId(promotedTwitterFeed);

            invideoPromotion.setItems(Lists.newArrayList(promotedItem));
            channel.setInvideoPromotion(invideoPromotion);

            // Call the API to set the in-video promotion data.
            updateChannelResponse = youtube.channels()
                    .update("invideoPromotion", channel)
                    .execute();

            // Print data from the API response.
            System.out.println("\n================== Updated Channel Information ==================\n");
            System.out.println("\t- Channel ID: " + updateChannelResponse.getId());

            promotions = updateChannelResponse.getInvideoPromotion();
            promotedItem = promotions.getItems().get(0);
            System.out.println("\t- Invideo promotion URL: " + promotedItem
                    .getId()
                    .getWebsiteUrl());
            System.out.println("\t- Promotion message: " + promotedItem.getCustomMessage());

            // This example sets a custom watermark for the channel. The image
            // used is the watermark.jpg file in the "resources/" directory.
            InputStreamContent mediaContent = new InputStreamContent("image/jpeg",
                    InvideoProgramming.class.getResourceAsStream("/watermark.jpg"));

            // Indicate that the watermark should display during the last 15
            // seconds of the video.
            InvideoTiming watermarkTiming = new InvideoTiming();
            watermarkTiming.setType("offsetFromEnd");
            watermarkTiming.setDurationMs(BigInteger.valueOf(15000l));
            watermarkTiming.setOffsetMs(BigInteger.valueOf(15000l));

            InvideoBranding invideoBranding = new InvideoBranding();
            invideoBranding.setTiming(watermarkTiming);
            youtube.watermarks().set(channelId, invideoBranding, mediaContent).execute();

        } 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();
        }
    }

}

Java #2

This sample demonstrates how to use the following API methods to set and retrieve localized metadata for a channel:
  • It calls the channels.update method to update the default language of a channel's metadata and to add a localized version of this metadata in a selected language. Note that to set the default language for a channel resource, you actually need to update the brandingSettings.channel.defaultLanguage property.
  • It calls the channels.list method with the hl parameter set to a specific language to retrieve localized metadata in that language.
  • It calls the channels.list method and includes localizations in the part parameter value to retrieve all of the localized metadata for that channel.

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.Channel;
import com.google.api.services.youtube.model.ChannelListResponse;
import com.google.api.services.youtube.model.ChannelLocalization;
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 channel by:
 *
 * 1. Updating language of the default metadata and setting localized metadata
 *   for a channel via "channels.update" method.
 * 2. Getting the localized metadata for a channel in a selected language using the
 *   "channels.list" method and setting the "hl" parameter.
 * 3. Listing the localized metadata for a channel using "channels.list" method and
 *   including "localizations" in the "part" parameter.
 *
 * @author Ibrahim Ulukaya
 */
public class ChannelLocalizations {

    /**
     * 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 channel.
     *
     * @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:
                    setChannelLocalization(getId("channel"), getDefaultLanguage(),
                            getLanguage(), getMetadata("description"));
                    break;
                case GET:
                    getChannelLocalization(getId("channel"), getLanguage());
                    break;
                case LIST:
                    listChannelLocalizations(getId("channel"));
                    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 channel's default language and sets its localized metadata.
     *
     * @param channelId The id parameter specifies the channel ID for the resource
     * that is being updated.
     * @param defaultLanguage The language of the channel's default metadata
     * @param language The language of the localized metadata
     * @param description The localized description to be set
     * @throws IOException
     */
    private static void setChannelLocalization(String channelId, String defaultLanguage,
        String language, String description) throws IOException {
        // Call the YouTube Data API's channels.list method to retrieve channels.
        ChannelListResponse channelListResponse = youtube.channels().
            list("brandingSettings,localizations").setId(channelId).execute();

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

        // Modify channel's default language and localizations properties.
        // Ensure that a value is set for the resource's snippet.defaultLanguage property.
        // To set the snippet.defaultLanguage property for a channel resource,
        // you actually need to update the brandingSettings.channel.defaultLanguage property.
        channel.getBrandingSettings().getChannel().setDefaultLanguage(defaultLanguage);

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

        // Update the channel resource by calling the channels.update() method.
        Channel channelResponse = youtube.channels()
            .update("brandingSettings,localizations", channel).execute();

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

    /**
     * Returns localized metadata for a channel 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 channelId The id parameter specifies the channel ID for the resource
     * that is being updated.
     * @param language The language of the localized metadata
     * @throws IOException
     */
    private static void getChannelLocalization(String channelId, String language)
        throws IOException {
        // Call the YouTube Data API's channels.list method to retrieve channels.
        ChannelListResponse channelListResponse = youtube.channels().
            list("snippet").setId(channelId).set("hl", language).execute();

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

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

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

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

        // Print information from the API response.
        System.out.println("\n================== Channel ==================\n");
        System.out.println("  - ID: " + channel.getId());
        for (String language : localizations.keySet()) {
            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 sample demonstrates how to use the following API methods to set and retrieve localized metadata for a channel:
  • It calls the channels.update method to update the default language of a channel's metadata and to add a localized version of this metadata in a selected language. Note that to set the default language for a channel resource, you actually need to update the brandingSettings.channel.defaultLanguage property.
  • It calls the channels.list method with the hl parameter set to a specific language to retrieve localized metadata in that language.
  • It calls the channels.list method and includes localizations in the part parameter value to retrieve all of the localized metadata for that channel.

This example uses the PHP client library.

<?php

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

/**
 * Library Requirements
 *
 * 1. Install composer (https://getcomposer.org)
 * 2. On the command line, change to this directory (api-samples/php)
 * 3. Require the google/apiclient library
 *    $ composer require google/apiclient:~2.0
 */
if (!file_exists(__DIR__ . '/vendor/autoload.php')) {
  throw new \Exception('please run "composer require google/apiclient:~2.0" in "' . __DIR__ .'"');
}

require_once __DIR__ . '/vendor/autoload.php';
session_start();

$htmlBody = <<<END
<form method="GET">
  <div>
    Action:
    <select id="action" name="action">
      <option value="set">Set Localization - Fill in: channel ID, default language, language, description</option>
      <option value="get">Get Localization- Fill in: channel ID, language</option>
      <option value="list">List Localizations - Fill in: channel ID, language</option>
    </select>
  </div>
  <br>
  <div>
    Channel ID: <input type="text" id="channelId" name="channelId" placeholder="Enter Channel 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>
    Description: <input type="text" id="description" name="description" placeholder="Enter Description">
  </div>
  <br>
  <input type="submit" value="GO!">
</form>
END;

/*
 * You can acquire an OAuth 2.0 client ID and client secret from the
 * {{ Google Cloud Console }} <{{ https://cloud.google.com/console }}>
 * 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);

/*
 * 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);

// Check if an auth token exists for the required scopes
$tokenSessionKey = 'token-' . $client->prepareScopes();
if (isset($_GET['code'])) {
  if (strval($_SESSION['state']) !== strval($_GET['state'])) {
    die('The session state did not match.');
  }

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

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

// 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 (isset($_GET['action'])) {
    $htmlBody = '';
    $resource = $_GET['resource'];
    $channelId = $_GET['channelId'];
    $language = $_GET['language'];
    $defaultLanguage = $_GET['defaultLanguage'];
    $description = $_GET['description'];
    try {
      switch ($_GET['action']) {
        case 'set':
          setChannelLocalization($youtube, $channelId, $defaultLanguage,
              $language, $description, $htmlBody);
          break;
        case 'get':
          getChannelLocalization($youtube, $channelId, $language, $htmlBody);
          break;
        case 'list':
          listChannelLocalizations($youtube, $channelId, $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[$tokenSessionKey] = $client->getAccessToken();
} elseif ($OAUTH2_CLIENT_ID == 'REPLACE_ME') {
  $htmlBody = <<<END
  <h3>Client Credentials Required</h3>
  <p>
    You need to set <code>\$OAUTH2_CLIENT_ID</code> and
    <code>\$OAUTH2_CLIENT_ID</code> before proceeding.
  <p>
END;
} 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 channel's default language and sets its localized metadata.
 *
 * @param Google_Service_YouTube $youtube YouTube service object.
 * @param string $channelId The id parameter specifies the channel ID for the resource
 * that is being updated.
 * @param string $defaultLanguage The language of the channel's default metadata
 * @param string $language The language of the localized metadata
 * @param string $description The localized description to be set
 * @param $htmlBody - html body.
 */
function setChannelLocalization(Google_Service_YouTube $youtube, $channelId, $defaultLanguage,
    $language, $description, &$htmlBody) {
  // Call the YouTube Data API's channels.list method to retrieve channels.
  $channels = $youtube->channels->listChannels("brandingSettings,localizations", array(
      'id' => $channelId
  ));

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

    // Modify channel's default language and localizations properties.
    // Ensure that a value is set for the resource's snippet.defaultLanguage property.
    // To set the snippet.defaultLanguage property for a channel resource,
    // you actually need to update the brandingSettings.channel.defaultLanguage property.
    $updateChannel['brandingSettings']['channel']['defaultLanguage'] = $defaultLanguage;
    $localizations = $updateChannel['localizations'];

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

    // Call the YouTube Data API's channels.update method to update an existing channel.
    $channelUpdateResponse = $youtube->channels->update("brandingSettings,localizations",
        $updateChannel);

    $htmlBody .= "<h2>Updated channel</h2><ul>";
    $htmlBody .= sprintf('<li>(%s) default language: %s</li>', $channelId,
        $channelUpdateResponse['brandingSettings']['channel']['defaultLanguage']);
    $htmlBody .= sprintf('<li>description(%s): %s</li>', $language,
        $channelUpdateResponse['localizations'][$language]['description']);
    $htmlBody .= '</ul>';
  }
}

/**
 * Returns localized metadata for a channel 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 $channelId The channelId parameter instructs the API to return the
 * localized metadata for the channel specified by the channel id.
 * @param string language The language of the localized metadata.
 * @param $htmlBody - html body.
 */
function getChannelLocalization(Google_Service_YouTube $youtube, $channelId,
    $language, &$htmlBody) {
  // Call the YouTube Data API's channels.list method to retrieve channels.
  $channels = $youtube->channels->listChannels("snippet", array(
      'id' => $channelId,
      'hl' => $language
  ));

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

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

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

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

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

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

PHP #2

This sample calls the API's channelBanners.insert method to upload an image. With the returned URL, the sample calls channels.update method to update the channel's banner to this image.

This example uses the PHP client library.

<?php

/**
 * This sample sets a custom banner for a user's channel by:
 *
 * 1. Uploading a banner image with "youtube.channelBanners.insert" method via resumable upload
 * 2. Getting user's channel object with "youtube.channels.list" method and "mine" parameter
 * 3. Updating channel's banner external URL with "youtube.channels.update" method
 *
 * @author Ibrahim Ulukaya
*/

/**
 * Library Requirements
 *
 * 1. Install composer (https://getcomposer.org)
 * 2. On the command line, change to this directory (api-samples/php)
 * 3. Require the google/apiclient library
 *    $ composer require google/apiclient:~2.0
 */
if (!file_exists(__DIR__ . '/vendor/autoload.php')) {
  throw new \Exception('please run "composer require google/apiclient:~2.0" in "' . __DIR__ .'"');
}

require_once __DIR__ . '/vendor/autoload.php';
session_start();

/*
 * You can acquire an OAuth 2.0 client ID and client secret from the
 * {{ Google Cloud Console }} <{{ https://cloud.google.com/console }}>
 * 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);

// Check if an auth token exists for the required scopes
$tokenSessionKey = 'token-' . $client->prepareScopes();
if (isset($_GET['code'])) {
  if (strval($_SESSION['state']) !== strval($_GET['state'])) {
    die('The session state did not match.');
  }

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

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

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

    // REPLACE with the path to your file that you want to upload for thumbnail
    $imagePath = "/path/to/file.jpg";

    // Specify the size of each chunk of data, in bytes. Set a higher value for
    // reliable connection as fewer chunks lead to faster uploads. Set a lower
    // value for better recovery on less reliable connections.
    $chunkSizeBytes = 1 * 1024 * 1024;

    // Setting the defer flag to true tells the client to return a request which can be called
    // with ->execute(); instead of making the API call immediately.
    $client->setDefer(true);

    $chan = new Google_Service_YouTube_ChannelBannerResource();

    // Create a request for the API's channelBanners.insert method to upload the banner.
    $insertRequest = $youtube->channelBanners->insert($chan);

    // Create a MediaFileUpload object for resumable uploads.
    $media = new Google_Http_MediaFileUpload(
        $client,
        $insertRequest,
        'image/jpeg',
        null,
        true,
        $chunkSizeBytes
    );
    $media->setFileSize(filesize($imagePath));


    // Read the media file and upload it chunk by chunk.
    $status = false;
    $handle = fopen($imagePath, "rb");
    while (!$status && !feof($handle)) {
      $chunk = fread($handle, $chunkSizeBytes);
      $status = $media->nextChunk($chunk);
    }

    fclose($handle);

    // If you want to make other calls after the file upload, set setDefer back to false
    $client->setDefer(false);

    $thumbnailUrl = $status['url'];

    // Call the API's channels.list method with mine parameter to fetch authorized user's channel.
    $listResponse = $youtube->channels->listChannels('brandingSettings', array(
        'mine' => 'true',
    ));

    $responseChannel = $listResponse[0];
    $responseChannel['brandingSettings']['image']['bannerExternalUrl']=$thumbnailUrl;

     // Call the API's channels.update method to update branding settings of the channel.
     $updateResponse = $youtube->channels->update('brandingSettings', $responseChannel);

     $bannerMobileUrl = $updateResponse["brandingSettings"]["image"]["bannerMobileImageUrl"];

     $htmlBody .= "<h3>Thumbnail Uploaded</h3><ul>";
     $htmlBody .= sprintf('<li>%s</li>',
         $thumbnailUrl);
     $htmlBody .= sprintf('<img src="%s">', $bannerMobileUrl);
     $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[$tokenSessionKey] = $client->getAccessToken();
} elseif ($OAUTH2_CLIENT_ID == 'REPLACE_ME') {
  $htmlBody = <<<END
  <h3>Client Credentials Required</h3>
  <p>
    You need to set <code>\$OAUTH2_CLIENT_ID</code> and
    <code>\$OAUTH2_CLIENT_ID</code> before proceeding.
  <p>
END;
} 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>Banner Uploaded and Set</title>
</head>
<body>
  <?=$htmlBody?>
</body>
</html>

Python #1

This sample calls the API's channels.update method to set invideoPromotion properties for the channel.

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 Cloud Console }} at
# {{ https://cloud.google.com/console }}.
# 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 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 {{ Cloud Console }}
{{ https://cloud.google.com/console }}

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))

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

# If offsetMs is not valid, the API will throw an error
VALID_OFFSET_TYPES = ("offsetFromEnd", "offsetFromStart",)

def get_authenticated_service(args):
  flow = flow_from_clientsecrets(CLIENT_SECRETS_FILE, scope=YOUTUBE_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 add_featured_video(youtube, options):
  add_video_request = youtube.channels().update(
    part="invideoPromotion",
    # You can use the API Explorer to test API requests:
    #    https://developers.google.com/youtube/v3/docs/channels/update#try-it
    body={
      "invideoPromotion": {
        "items": [{
          "id": {
            "type": "video",
            "videoId": options.video_id
          },
          "timing": {
            "offsetMs": options.offset_ms,
            "type": options.offset_type
          }
        }],
      },
      "id": options.channel_id
  }).execute()

if __name__ == '__main__':
  argparser.add_argument("--channel-id", required=True,
    help="Channel ID of the channel to add a featured video")
  argparser.add_argument("--video-id",  required=True,
    help="Video ID to feature on your channel")
  argparser.add_argument("--offset-ms",
    help="Offset in milliseconds to show video.",
    default="10000")
  argparser.add_argument("--offset-type", choices=VALID_OFFSET_TYPES,
    help="Whether the offset is from the beginning or end of video playback.",
    default=VALID_OFFSET_TYPES[0])
  args = argparser.parse_args()

  youtube = get_authenticated_service(args)
  try:
    add_featured_video(youtube, args)
  except HttpError, e:
    print "An HTTP error %d occurred:\n%s" % (e.resp.status, e.content)
  else:
    print "Added featured video %s to channel %s." % (
      args.video_id, args.channel_id)

Python #2

This sample demonstrates how to use the following API methods to set and retrieve localized metadata for a channel:
  • It calls the channels.update method to update the default language of a channel's metadata and to add a localized version of this metadata in a selected language. Note that to set the default language for a channel resource, you actually need to update the brandingSettings.channel.defaultLanguage property.
  • It calls the channels.list method with the hl parameter set to a specific language to retrieve localized metadata in that language.
  • It calls the channels.list method and includes localizations in the part parameter value to retrieve all of the localized metadata for that channel.

This example uses the Python client library.

#!/usr/bin/python

# Usage example:
# python channel_localizations.py --action='<action>' --channel_id='<channel_id>' --default_language='<default_language>' --language='<language>' --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 Cloud Console }} at
# {{ https://cloud.google.com/console }}.
# 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 channels.update method to update an existing channel's default language,
# and localized description in a specific language.
def set_channel_localization(youtube, channel_id, default_language, language, description):
  results = youtube.channels().list(
    part="brandingSettings,localizations",
    id=channel_id
  ).execute()

  channel = results["items"][0]
  # Ensure that a value is set for the resource's snippet.defaultLanguage property.
  # To set the snippet.defaultLanguage property for a channel resource,
  # you actually need to update the brandingSettings.channel.defaultLanguage property.
  channel["brandingSettings"]["channel"]["defaultLanguage"] = default_language
  if "localizations" not in channel:
    channel["localizations"] = {}
  channel["localizations"][language] = {
    "description": description
  }

  update_result = youtube.channels().update(
    part="brandingSettings,localizations",
    body=channel
  ).execute()

  localization = update_result["localizations"][language]

  print ("Updated channel '%s' default language to '%s', localized description"
         " to '%s' in language '%s'" % (channel_id, localization["description"], language))


# Call the API's channels.list method to retrieve an existing channel localization.
# If the localized text is not available in the requested language,
# this method will return text in the default language.
def get_channel_localization(youtube, channel_id, language):
  results = youtube.channels().list(
    part="snippet",
    id=channel_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 "Channel description is '%s' in language '%s'" % (localized["description"], language)


# Call the API's channels.list method to list the existing channel localizations.
def list_channel_localizations(youtube, channel_id):
  results = youtube.channels().list(
    part="snippet,localizations",
    id=channel_id
  ).execute()

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

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


if __name__ == "__main__":
  # The "action" option specifies the action to be processed.
  argparser.add_argument("--action", help="Action")
  # The "channel_id" option specifies the ID of the selected YouTube channel.
  argparser.add_argument("--channel_id",
    help="ID for channel for which the localization will be applied.")
  # The "default_language" option specifies the language of the channel's default metadata.
  argparser.add_argument("--default_language", help="Default language of the channel 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 "description" option specifies the localized description of the chanel to be set.
  argparser.add_argument("--description", help="Localized description of the channel to be set.",
    default="Localized Description")

  args = argparser.parse_args()

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

  youtube = get_authenticated_service(args)
  try:
    if args.action == 'set':
      set_channel_localization(youtube, args.channel_id, args.default_language, args.language, args.description)
    elif args.action == 'get':
      get_channel_localization(youtube, args.channel_id, args.language)
    elif args.action == 'list':
      list_channel_localizations(youtube, args.channel_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 channel."

Python #3

This sample calls the API's channelBanners.insert method to upload an image. With the returned URL, the sample calls channels.update method to update the channel's banner to that image.

This example uses the Python client library.

#!/usr/bin/python


# This sample sets a custom banner to user's channel by:
#
# 1. Uploading a banner image with "youtube.channelBanners.insert" method via resumable upload
# 2. Getting user's channel object with "youtube.channels.list" method and "mine" parameter
# 3. Updating channel's banner external URL with "youtube.channels.update" method
#
# @author Ibrahim Ulukaya

import httplib
import httplib2
import os
import random
import sys
import time

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


# Explicitly tell the underlying HTTP transport library not to retry, since
# we are handling retry logic ourselves.
httplib2.RETRIES = 1

# Maximum number of times to retry before giving up.
MAX_RETRIES = 10

# Always retry when these exceptions are raised.
RETRIABLE_EXCEPTIONS = (httplib2.HttpLib2Error, IOError, httplib.NotConnected,
  httplib.IncompleteRead, httplib.ImproperConnectionState,
  httplib.CannotSendRequest, httplib.CannotSendHeader,
  httplib.ResponseNotReady, httplib.BadStatusLine)

# Always retry when an apiclient.errors.HttpError with one of these status
# codes is raised.
RETRIABLE_STATUS_CODES = [500, 502, 503, 504]

# CLIENT_SECRETS_FILE, name of a file containing the OAuth 2.0 information for
# this application, including client_id and client_secret. You can acquire an
# ID/secret pair from the APIs & auth tab at
#   https://cloud.google.com/console
# For more information about using OAuth2 to access Google APIs, please visit:
#   https://developers.google.com/accounts/docs/OAuth2
# For more information about the client_secrets.json file format, please visit:
#   https://developers.google.com/api-client-library/python/guide/aaa_client_secrets
# Please ensure that you have enabled the YouTube Data API for your project.
CLIENT_SECRETS_FILE = "client_secrets.json"

# An OAuth 2 access scope that allows for full read/write access.
YOUTUBE_READ_WRITE_SCOPE = "https://www.googleapis.com/auth/youtube"
YOUTUBE_API_SERVICE_NAME = "youtube"
YOUTUBE_API_VERSION = "v3"

# Helpful 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://cloud.google.com/console

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 upload_banner(youtube, image_file):
  insert_request = youtube.channelBanners().insert(
    media_body = MediaFileUpload(image_file, chunksize=-1, resumable=True)
  )

  image_url = resumable_upload(insert_request)
  set_banner(image_url)

def resumable_upload(insert_request):
  response = None
  error = None
  retry = 0
  while response is None:
    try:
      print "Uploading file..."
      status, response = insert_request.next_chunk()
      if 'url' in response:
        print "Banner was successfully uploaded to '%s'." % (
          response['url'])
      else:
        exit("The upload failed with an unexpected response: %s" % response)
    except HttpError, e:
      if e.resp.status in RETRIABLE_STATUS_CODES:
        error = "A retriable HTTP error %d occurred:\n%s" % (e.resp.status,
                                                             e.content)
      else:
        raise
    except RETRIABLE_EXCEPTIONS, e:
      error = "A retriable error occurred: %s" % e

    if error is not None:
      print error
      retry += 1
      if retry > MAX_RETRIES:
        exit("No longer attempting to retry.")

      max_sleep = 2 ** retry
      sleep_seconds = random.random() * max_sleep
      print "Sleeping %f seconds and then retrying..." % sleep_seconds
      time.sleep(sleep_seconds)

  return response['url']

def set_banner(banner_url):
  channels_response = youtube.channels().list(
    mine=True,
    part="brandingSettings"
  ).execute()

  if "brandingSettings" not in channels_response["items"][0]:
    channels_response["items"][0]["brandingSettings"]["image"]["bannerExternalUrl"] = []

  channel_brandingSettings = channels_response["items"][0]["brandingSettings"]

  channel_brandingSettings["image"]["bannerExternalUrl"] = banner_url

  channels_update_response = youtube.channels().update(
    part='brandingSettings',
    body=dict(
      brandingSettings=channel_brandingSettings,
      id = channels_response["items"][0]["id"]
    )).execute()

  banner_mobile_url = channels_update_response["brandingSettings"]["image"]["bannerMobileImageUrl"]
  print "Banner is set to '%s'." % (banner_mobile_url)

if __name__ == "__main__":
  argparser.add_argument("--file", required=True,
    help="Path to banner image file.")
  args = argparser.parse_args()

  if not os.path.exists(args.file):
    exit("Please specify a valid file using the --file= parameter.")

  youtube = get_authenticated_service(args)
  try:
    upload_banner(youtube, args.file)
  except HttpError, e:
    print "An HTTP error %d occurred:\n%s" % (e.resp.status, e.content)
  else:
    print "The custom banner was successfully uploaded."

Errors

The following table 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) brandingValidationError One of the values in the brandingSettings object failed validation. Use the channels.list method to retrieve the existing settings for the channel, and update the property values following the guidelines in the channels resource documentation.
badRequest (400) channelTitleUpdateForbidden When updating a channel's brandingSettings part, you must set the brandingSettings.channel.title property's value to the channel's current title or omit the property. The API returns an error if you change the property's value.
badRequest (400) defaultLanguageNotSetError The defaultLanguage must be set to update localizations.
badRequest (400) invalidBrandingOption One of the branding settings that you specified does not exist. Use the channels.list method to retrieve valid values and make sure to update them following the guidelines in the channels resource documentation.
badRequest (400) invalidCustomMessage The request metadata specifies an invalid custom message. Check the value of the invideoPromotion.items[].customMessage property in the resource that the request sent.
badRequest (400) invalidDuration The request metadata specifies an invalid duration in the invideoPromotion part.
badRequest (400) invalidDuration The request metadata specifies an invalid position type for determining how the promoted item is positioned in the video player. Check the value of the invideoPromotion.position.type property in the resource that the request sent.
badRequest (400) invalidRecentlyUploadedBy The request metadata specifies an invalid channel ID. Check the value of the invideoPromotion.items[].id.recentlyUploadedBy property in the resource that the request sent.
badRequest (400) invalidTimingOffset The request metadata specifies an invalid timing offset in the invideoPromotion part.
badRequest (400) invalidTimingOffset The request metadata specifies an invalid timing offset for determining when the promoted item should be displayed in the video player. Check the value of the invideoPromotion.timing.offsetMs property in the resource that the request sent.
badRequest (400) invalidTimingType The request metadata specifies an invalid timing method for determining when the promoted item should be displayed in the video player. Check the value of the invideoPromotion.timing.type property in the resource that the request sent.
badRequest (400) localizationValidationError One of the values in the localizations object failed validation. Use the channels.list method to retrieve valid values and make sure to update them following the guidelines in the channels resource documentation.
badRequest (400) tooManyPromotedItems Number of allowed promoted items exceeded in the invideoPromotion part.
forbidden (403) channelForbidden The channel specified in the id parameter does not support the request or the request is not properly authorized.
forbidden (403) promotedVideoNotAllowed The channel that the API request is attempting to update cannot be found. Check the value of the id property in the channel resource that the request sent to ensure that the channel ID is correct.
forbidden (403) websiteLinkNotAllowed The specified website url is not allowed.
notFound (404) channelNotFound The channel specified in the id parameter cannot be found.
notFound (404) channelNotFound The channel specified by the id parameter cannot be found or does not have branding options.
notFound (404) unknownChannelId The specified channel ID was not found.
notFound (404) unknownChannelId The specified recentlyUploadedBy channel ID was not found.
notFound (404) unknownVideoId The video ID specified as a promoted item cannot be found.
required (400) requiredItemIdType The request metadata must specify an item type in the invideoPromotion part.
required (400) requiredItemId The request metadata must specify an item id the invideoPromotion part.
required (400) requiredTimingOffset The request metadata must specify a default timing offset so that YouTube can determine when to display the promoted item. Set the value of the invideoPromotion.defaultTiming.offsetMs property in the resource that the request sends.
required (400) requiredTimingOffset The request metadata must specify a timing offset so that YouTube can determine when to display the promoted item. Set the value of the invideoPromotion.timing.offsetMs property in the resource that the request sends.
required (400) requiredTimingType The request metadata must specify a timing method so that YouTube can determine when to display the promoted item. Set the value of the invideoPromotion.defaultTiming.type property in the resource that the request sends.
required (400) requiredTimingType The request metadata must specify a timing method so that YouTube can determine when to display the promoted item. Set the value of the invideoPromotion.timing.type property in the resource that the request sends.
required (400) requiredTiming The request metadata must specify a timing for each item in the invideoPromotion part.
required (400) requiredVideoId The request metadata must specify a video ID to identify the promoted item.
required (400) requiredWebsiteUrl The request metadata must specify a website url in the invideoPromotion part. Set the value of the invideoPromotion.items[].id.websiteUrl property in the resource that the request sends.

Try it!

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