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?
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:
The onBehalfOfContentOwner
parameter is missing (required when using managedByMe: true
), or
The OAuth token was generated from a non-linked YouTube CMS account or the API client lacks sufficient permissions.
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,
});