Search code examples
node.jsgoogle-apiyoutube-apigoogle-analytics-api

Getting 403 forbidden when trying to retrieve metrics using YouTube Analytics API


I am new to Google Analytics api and was following this tutorial to acquire estimatedMinutesWatched and averageViewDuration, however I always got the 403 forbidden code as response.

I want to ask first, how to fix this, are we only supposed to retrieve data from our own channel? second, is there a way that we can retrieve the metrics without specifying a channel id? I might want to retrieve metrics from many videos from different channels and I felt specifying a channel is unnecessary. Thank you!

Below is the code that I currently have:

const fs = require('fs');
const readline = require('readline');
const { google } = require('googleapis');
const { GoogleSpreadsheet } = require('google-spreadsheet');

const scope = ['https://www.googleapis.com/auth/youtube.readonly'];
const creds = require('./client_secret.json');
const doc = new GoogleSpreadsheet('1YNzey4giSw-29oFGPCfGLBkMHCFB1o2oLr3qLIQZTVQ');

(async () => {
    await doc.useServiceAccountAuth(creds);
    await doc.loadInfo();
    const sheet = doc.sheetsByIndex[0];
    const rows = await sheet.getRows();
    // const ids = rows.map(r => r.id).join(',');
    const ids = 'IKiAiD3SONw';

    fs.readFile("oauth_client_creds.json", (err, content) => {
        if (err) {
            return console.log("Cannot load client secret file:", err);
        }

        // Authorize a client with credentials, then make API call.
        const credentials = JSON.parse(content);
        const { client_secret, client_id, redirect_uris } = credentials.installed;
        const oAuth2Client = new google.auth.OAuth2(
            client_id,
            client_secret,
            redirect_uris[0]
        );

        const authUrl = oAuth2Client.generateAuthUrl({
            access_type: "offline",
            scope: scope
        });
        console.log("Visit this URL to authorize this app:", authUrl);

        const rl = readline.createInterface({
            input: process.stdin,
            output: process.stdout
        });
        rl.question("Enter the auth code from that URL: ", code => {
            rl.close();
            oAuth2Client.getToken(code, (err, token) => {
                oAuth2Client.setCredentials(token);
                callApi(oAuth2Client);
            });
        });
    });

    let callApi = auth => {
        const youtubeAnalytics = google.youtubeAnalytics({ version: "v2", auth });

        youtubeAnalytics.reports
            .query({
                startDate: "2019-01-01",
                endDate: "2021-12-31",
                ids: "channel==UCbXm_tde_rLHG8gv48wSULw",
                filters: `video==${ids}`,
                dimensions: "video",
                metrics: "estimatedMinutesWatched,averageViewDuration"
            })
            .then(async response => {
                console.log(response);
                console.log(response.data.rows);
                response.data.rows.forEach(async (row, index) => {
                    rows[index].minutes_watched = row[1];
                    rows[index].avd = row[2];
                    await rows[index].save();
                });
            })
            .catch(error => console.log("The API returned an error: ", error.message));
    };
})();

Solution

  • Since you have always gotten a 403 error, it sounds like you are not passing your API credentials correctly OR you are requesting someone else's Channel information.

    To answer your question, you can only retrieve metrics for your own channel OR if another user has authorized your application.

    The channel you are querying appears to be formatted incorrectly, or has not completed setup. I think UCbXm_tde_rLHG8gv48wSULw should not have underlines. Create a test channel on your Youtube account and copy the ID.

    To resolve the 403 error:

    1. Ensure you have created an API key
    2. Ensure you have saved your credentials correctly in your json file
    3. Ensure the file has the extension .json
    4. Ensure you are requesting your own channel ID

    I would also check out the following:

    • Granting Authorization Access (link)
    • Youtube Analytics API (link)