youtube-apiyoutube-data-api

Persistent 403 Access Forbidden for YouTube Data API channels.list (managedByMe) with Content Manager Account


Body:

I am developing a Node.js application to interact with the YouTube Data API v3. I am trying to list channels managed by my YouTube Content Owner account. Despite extensive troubleshooting, I consistently receive a 403 Access forbidden error.

Problem: When calling youtube.channels.list({ part: 'id,snippet,statistics', managedByMe: true }), the API returns: Error fetching channel list: Access forbidden. The request may not be properly authorized.

API Error Details: {
  code: 403,
  message: 'Access forbidden. The request may not be properly authorized.',
  errors: [
    {
      message: 'Access forbidden. The request may not be properly authorized.',
      domain: 'youtube.common',
      reason: 'forbidden'
    }
  ]
}

Context & Steps Taken:

Authenticated Account Permissions: My Google account (iconstats@gmail.com) has confirmed "Content Manager" access for the "MovieBox Record Label" Content Owner within the YouTube Studio UI. I can manually log in and manage content for this Content Owner.

OAuth Scopes: My Node.js application is configured to request the following scopes, and the OAuth consent screen confirms they are granted:

https://www.googleapis.com/auth/yt-analytics.readonly

https://www.googleapis.com/auth/youtube.readonly

https://www.googleapis.com/auth/youtubepartner A recent authentication log shows the access_token and refresh_token were successfully acquired with all these scopes.

Authentication Flow: I am using the google.auth.OAuth2 client in Node.js. My process involves:

Generating an auth URL.

Opening it in the browser for user consent.

Handling the oauth2callback to exchange the code for tokens.

Saving tokens.json.

Setting oauth2Client.setCredentials(tokens) before making API calls.

I have repeatedly deleted tokens.json and re-authenticated to ensure fresh tokens with all scopes are obtained.

API Call: The relevant part of my Node.js code for the API call is:

const { google } = require("googleapis");
const oauth2Client = /* ... initialized oauth2Client ... */ ; // (credentials set from tokens.json)

const youtube = google.youtube({
    version: "v3",
    auth: oauth2Client,
});

try {
    const responseManagedByMe = await youtube.channels.list({
        part: "id,snippet,statistics",
        managedByMe: true,
        maxResults: 50,
    });
    // ... handle successful response ...
} catch (error) {
    // ... logs the 403 error above ...
}

Given that the iconstats@gmail.com account has Content Manager access in the YouTube UI and my application is successfully acquiring tokens with the youtubepartner scope, why am I still receiving a 403 Access forbidden error for the channels.list call with managedByMe: true? Is there a specific project-level approval, whitelisting, or a different API method/parameter combination required for Content Owners to list managed channels via the API?


Solution

  • How I Solved the 403 'Access Forbidden' When Using youtube.channels.list with managedByMe: true

    After running into this issue myself and thoroughly troubleshooting, I finally resolved it. Here's what I learned:
    Even with valid OAuth scopes and confirmed Content Manager access, a call to:

    youtube.channels.list({
      part: 'id,snippet,statistics',
      managedByMe: true,
    })
    

    ...can still return a 403 Forbidden if either:


    Solution

    You must provide the onBehalfOfContentOwner parameter along with managedByMe: true.

    Here’s a working example:

    const { google } = require("googleapis");
    
    const youtube = google.youtube({
      version: "v3",
      auth: oauth2Client, // previously authorized using proper scopes
    });
    
    const contentOwnerId = "YOUR_CONTENT_OWNER_ID"; // e.g. 'JpuVTLwbAz2D0q2E4Sb6kA'
    
    const response = await youtube.channels.list({
      part: "id,snippet,statistics",
      managedByMe: true,
      onBehalfOfContentOwner: contentOwnerId,
      maxResults: 50,
    });