Search code examples
javagoogle-cloud-platformyoutubehttp-status-code-401google-people-api

*401 Unauthorized* When following tutorial Java implementation of Video.insert by developers.google.com


I am trying to upload an mp4 file to my youtube channel using the YouTube Data API, however, I keep getting a 401 Unauthorized back.

Using the google console cloud I created an (unrestricted) API key. Afterwards, I enabled YouTube Data API v3 I then copied the java code snippet from the use cases documentation for making a Video.Insert call to their services.

The things I changed from the snippet (required):

I used the aforementioned API key to replace "YOUR_API_KEY" And also replaced new File("YOUR_FILE") for obvious reasons. The file is a 17MB mp4 file.

Because the package provided with the snippet no longer comes with com.google.api.client.json.jackson2.JacksonFactory; Following this solution I included the dependency:

<dependency>
    <groupId>com.google.http-client</groupId>
    <artifactId>google-http-client-jackson</artifactId>
    <version>1.29.2</version>
</dependency>

And I replaced JacksonFactory.getDefaultInstance() with new JacksonFactory()

Finally, as youtubeService.videos().insert(args) doesn't support a string as its first argument I replaced the string with a List.of() of the CSV string. I've also tried a List with each of the comma-seperated strings as items in the list but that doesn't seem to change the outcome either.

This results in the following request: https://youtube.googleapis.com/upload/youtube/v3/videos?key=MyKeyAware&part=snippet&part=status&uploadType=resumable

For good measure, here are the relevant dependencies I'm using (excluding the aforementioned dependency):

<dependency>
    <groupId>com.google.api-client</groupId>
    <artifactId>google-api-client</artifactId>
    <version>1.35.1</version>
</dependency>
<dependency>
    <groupId>com.google.apis</groupId>
    <artifactId>google-api-services-youtube</artifactId>
    <version>v3-rev20220612-1.32.1</version>
</dependency>

I would really appreciate some help as I've been struggling with this issue for a while now!

Code:

package nl.phi.ysg.service.YoutubeApi;

import com.google.api.client.googleapis.javanet.GoogleNetHttpTransport;
import com.google.api.client.googleapis.json.GoogleJsonResponseException;
import com.google.api.client.http.InputStreamContent;
import com.google.api.client.http.javanet.NetHttpTransport;
import com.google.api.client.json.JsonFactory;
import com.google.api.client.json.jackson.JacksonFactory;
import com.google.api.services.youtube.YouTube;
import com.google.api.services.youtube.model.Video;
import com.google.api.services.youtube.model.VideoSnippet;
import com.google.api.services.youtube.model.VideoStatus;
import org.springframework.core.io.ClassPathResource;

import java.io.BufferedInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.security.GeneralSecurityException;
import java.util.List;

public class YoutubeApiServiceImpl implements YoutubeApiService {
    private static final String DEVELOPER_KEY = "...";

    private static final String APPLICATION_NAME = "YSG";
    private static final JsonFactory JSON_FACTORY = new JacksonFactory();

    /**
     * Build and return an authorized API client service.
     *
     * @return an authorized API client service
     * @throws GeneralSecurityException, IOException
     */
    public static YouTube getService() throws GeneralSecurityException, IOException {
        final NetHttpTransport httpTransport = GoogleNetHttpTransport.newTrustedTransport();
        return new YouTube.Builder(httpTransport, JSON_FACTORY, null).setApplicationName(APPLICATION_NAME).build();
    }
    

    public static void main(String[] args) throws GeneralSecurityException, IOException, GoogleJsonResponseException {
        YouTube youtubeService = getService();
        
        // Define the Video object, which will be uploaded as the request body.
        Video video = new Video();

        // Add the snippet object property to the Video object.
        VideoSnippet snippet = new VideoSnippet();
        snippet.setCategoryId("22");
        snippet.setDescription("Description of uploaded video.");
        snippet.setTitle("Test video upload.");
        video.setSnippet(snippet);

        // Add the status object property to the Video object.
        VideoStatus status = new VideoStatus();
        status.setPrivacyStatus("private");
        video.setStatus(status);

        File mediaFile = new ClassPathResource("test/test.mp4").getFile();
        InputStreamContent mediaContent = new InputStreamContent("application/octet-stream", new BufferedInputStream(new FileInputStream(mediaFile)));
        mediaContent.setLength(mediaFile.length());

        // Define and execute the API request
        YouTube.Videos.Insert request = youtubeService.videos().insert(List.of("snippet,status"), video, mediaContent);
        Video response = request.setKey(DEVELOPER_KEY).execute();
        System.out.println(response);
    }

}


Solution

  • It's unclear from your question but the error indicates that you're not including User authentication (OAuth) and this is required by the YouTube API:

    See the Quickstart specifically creating OAuth client ID in step 2b.

    The API key is used to authenticate your app.

    The OAuth2 client ID is used to authenticate human users.