How to use the Youtube Data API V3 with Node.js

In this article, we will learn how to use the googleapis npm module to authenticate our users with their youtube channel. Then we will use the youtube data API to fetch the channel and the video data associated with this channel. By using the refresh token we received earlier during authentication.

Before we begin.

We will be writing just the backend code but don’t worry. We will display the information on the web page . Although, it would just be an alternative to logging it to console

Creating and Enabling Youtube API on Google Client Id.

  1. Go to https://console.developers.google.com/ and either create a new project or select an existing one.
  2. On the left under API & Services select credentials.
  3. Click on Create credentials and select create oAuth Client ID
  4. Select Web Application as Application Type and give it any name you want.
  5. For use in this basic Application, you can leave the Authorized Javascript Origins blank but add http://localhost:3000/auth/youtube/callback to the Authorized Redirect URIs. I will be using this route but it is totally up to you to decide what route to use for authentications. Click Save.
  6. You would be shown a prompt with your Client ID and Client Secret to save them somewhere. We would be using these credentials to get the tokens for retrieving the user data.

Now that we have our Client Id setup we will start working on the actual code.

Setting up A Node.js Project

Set up a Nodejs project by typing the below command at a location of your choice. We would not be storing thee tokens as this is a demo app but Ideally, you may want to store the refresh token as this would allow you to regenerate the access token for a channel. you could use any storage mechanism of your choice.

npm init & npm i express googleapis dotenv

After this project is created. Add a file named .env and add the previously created Client Id and Client Secret in the file as

GOOGLE_CLIENTID =
GOOGLE_CLIENTSECRET = 

Plan of Action

This would be the path we will take to create our project.

  • We will first create an authentication URL by using the oAuth2 client that the googleapis npm package provides us.
  • We would redirect to that authentication URL and ask the end-user to authenticate with the channel they wish to get data for.
  • We would receive an accessToken and a refresh token. We would use the refresh token and pass the data to the youtube data API to get first channel data and second the video data for all videos.

Coding our Project

Let us first setup our app.js

const express = require('express');
require('dotenv').config()
const app = express();
const PORT = process.env.PORT || 3000;

app.get("/", (req, res)=>{
    res.send("HomePage");
})

const youtube = require('./routes/youtube')

app.use("/youtube",youtube);

app.listen(PORT, _=>console.log(`The Server started ${PORT}`));

We will create just the one service named youtube. create a folder named route in the project directory. Create a file named youtube.js where from now on all our logic that included authentication to fetching data would be written.

Creating the Youtube Service

Authenticating with a youtube channel.

var {google} = require('googleapis');
var router =require("express").Router();

var settingOauthClient = function (req, res, next) {
    try {
        const clientID=  process.env.GOOGLE_CLIENTID;   
        const clientSecret= process.env.GOOGLE_CLIENTSECRET;
        var REDIRECT_URL = `http://localhost:3000/youtube/auth/callback`;
        var oAuth2Client = new google.auth.OAuth2(clientID, clientSecret, REDIRECT_URL);
        req.oAuth2Client = oAuth2Client;
        next();
    }catch(error){
        console.log("An error occurred", error)
        res.status(406).json(error)
    }
}

var youtubeAuthURL =  function(req, res, next) {
    const url = req.oAuth2Client.generateAuthUrl({
        access_type: 'offline',
        prompt:'consent',
        scope: ['https://www.googleapis.com/auth/youtube',
            'https://www.googleapis.com/auth/youtubepartner-channel-audit']
    });
    console.log(url);
    res.redirect(url)
}


router.get('/auth', settingOauthClient,youtubeAuthURL);
module.exports  = router;

Understanding the youtubeAuth

Our youtube auth is a combination of two middleware that runs on the route ” /youtube/auth”. First, create the OAuth2 client using the googleapis npm module in the settingOauthClient middleware. This client we create will be responsible for authentication. We pass the client Id, Client Secret and the Redirect URL we specified earlier while we created the OAuth client on google console developer. We then generate the Authentication URL for the mentioned scopes and redirect our user on the authentication URL in the youtubeAuthUrl middleware.

Checking our Auth middlewares

Lets hit the route “/youtube/auth”. Which is configured to redirect us to the authentication URL. When we

Authenticating with google

After you enter the email Id it will ask the end-user to choose a youtube channel after which it will ask the end-user to authenticate for the scopes you provided before. So it is very important to ask for right and app-specific permissions if you are trying to make a commercial app.

Asking user the permission to manage the youtube account

Don’t worry if you are getting.

Warning to Unverified apps

Just Click on Advanced and click Go to. Read this article to understand why this happens: Link to article here.

Understanding Scopes

The scope specifies what permission your app would have on the channel that the user is authenticating. Additionally, You may not want the above scopes. Be very careful about what scopes you choose. If you are making a commercial app. As our scope of youtube partner-channel-audit retrieves the entire audit data for a channel. Read about the available youtube scopes here.

Setting up the callback URL

var youtubeAuthCallback = async function (req, res, next) {
    try {
        var code = req.query.code;
        console.log(code)
        if (code) {
            const {tokens} = await req.oAuth2Client.getToken(code);
            console.log(tokens);
            res.send(tokens)
        } else {
            throw new Error("no Token");
        }
    }catch (error) {
        res.json({error: true, description: error.message})
    }
}

router.get('/auth/callback', settingOauthClient,youtubeAuthCallback);

The callback would give us the tokens that we would use to make request. As you can see we first used the settingOauthClient middleware which we use to setup our oAuth2Client because we would be using it to extract the tokens that we get in the callback. Over here we have simply send the tokens on the screen but now we will the youtube functions so that using this token. We would fetch the channel data.

Creating a Youtube Client to fetch Data using the Youtube data API v3.

Create a module folder inside the route folder to store this file. Something like this.

folder structure

Creating youtubeClient.js

const {google} = require('googleapis');
require('dotenv').config()

module.exports = class youtubeClient {
    constructor({refreshToken}) {
        this.refreshToken = refreshToken;
        this.oAuth2Client = new google.auth.OAuth2(process.env.GOOGLE_CLIENTID, process.env.GOOGLE_CLIENTSECRET, `${process.env.BASE_URL}/services/youtube/connect/callback`);
        this.params = {};
        this.apiName = "";
    }

    setCredentialsOnClient() {
        this.oAuth2Client.setCredentials({refresh_token: this.refreshToken});
    }


    setParams(type) {
        switch (type) {
            case 'channels':
                this.apiName = 'channels'
                this.params = {
                    part: 'contentDetails,snippet,contentOwnerDetails,statistics',
                    mine: true,
                };
                break;
            case 'videos':
                this.apiName = 'search'
                this.params = {
                    part: "snippet",
                    forMine: true,
                    maxResult: 25, 
                    type: "video"
                };
                break;
            default:
                break;
        }
    }

    async getDataWithClient(type, channelId = "") {
        try {
            type = type.toLowerCase();
            this.setCredentialsOnClient();
            this.setParams(type);
            let totalFetchedResult = 0;
            let youtubeData = google.youtube('v3');
            if (type == 'videos') this.params.id = channelId;
            let data = [];
            while (true) {
                const youtubeContentData = await youtubeData[this.apiName].list({
                    ...this.params,
                    auth: this.oAuth2Client
                })
                data.push(youtubeContentData.data)
                if (type == 'channels' || data.length == youtubeContentData.data.pageInfo.totalResults) return data;
            }
        } catch (error) {
            console.log(error.message)
        }
    }

    async ChannelDataRequest() {
        try {
            let data = await this.getDataWithClient(`channels`);
            let videosFromChannel = await this.getDataWithClient('videos',data[0].items[0].id);
            let newYoutubeData = {
                AccountName: data[0].items[0].id,
                VideoCount: 0,
                User: this.userId,
                Service: this.serviceId,
                channel: {
                    ...data[0].items[0]
                },
                videos: [...videosFromChannel]
            }
            console.log(newYoutubeData)
            return newYoutubeData;
        } catch (error) {
            console.log("Error in save", error)
        }
    }
}

Understanding the youtubeClient.js

First we required the googleapis module and our .env config. The youtubeClient is a class that takes only one parameter the refreshToken that we received in the callback. Lets discuss the member methods of this class.

  1. setCredentialsOnClient
    This method simply sets the refresh token on the oauth2Client we created in our constructor.
  2. setParams
    Now we are getting two types of data with youtube data api v3. The channel Data and the video data. the parameter we are sending for both cases differ. So this method takes in a type (channel or videos) and sets the correct params on the params variable.
  3. getDataWithClient
    This method takes in the type discussed above and an optional channel Id all it does is to use the youtube v3 API to fetch the data. In the case of videos, we need to specify the channelId we want to fetch data from(the one for which we received the refresh token). The reason you see us using a while loop is that we only receive 5 results per page. So we would want to get all the data before sending it out. So we are looping till we have all data. Not the best way but just gets our work done.
  4. channelDataRequest
    This would be the function you would call. It would be single-handedly responsible to call every other function and fetch all data. It then returns this data.

Changes to the Callback function to return the Youtube channel Data.

var youtubeAuthCallback = async function (req, res, next) {
    try {
        var code = req.query.code;
        console.log(code)
        if (code) {
            const {tokens} = await req.oAuth2Client.getToken(code);
            console.log(tokens);
            let ytClient = require('./module/youtubeClient');
            let youtubeClient = new ytClient({refreshToken:tokens.refresh_token})
            let channelData = await youtubeClient.ChannelDataRequest();
            res.send(channelData)
        } else {
            throw new Error("no Token");
        }
    }catch (error) {
        res.json({error: true, description: error.message})
    }
}

So as you could see we are returning the channelData from callback itself. Change it to use your needs. Now when you go to this authentication url. after authentication is successful you would receive a response with channel Data like the one mentioned below . I am using an old yt channel that I don’t have future plan to upload to but has enough data to make us understand what this api returns.

I am not attaching the real data but a few screenshots as the real data is over 1000 lines.

youtube channelData from data v3 api
youtube video Data form data v3 api

Now that we understand how to fetch the youtube data. In the upcoming article we will look how to change the title, description ,thumbnails using the api. We will make it even more powerful by combining it with a cron job. So that it will update the title every few minutes if some event occurred.

Till then you could learn how to create CRON JOBS using the article we wrote before . LINK TO THE ARTICLE

Link to the entire code here.

Leave a Reply