Skip to content

YouTube API

This note is about the YouTube API. I started looking into this so that I could have a bot that responds to chat messages over YouTube.

Note: anywhere that you need to provide a channel ID, if you want to fetch this manually:

  • Register your application (reference)
    • You have to make an API key here. API keys are part of GCP, which means you need a GCP project. The projects themselves are free; you pay for resource/service usage. I created a project and then made sure to select the new project from the dropdown at the top of the page.
    • Click ”➕ Create credentials” and then choose “API key”. It’ll give you the API key in plaintext; this is private!
      • It’s a good idea to restrict the API key so that it doesn’t have access to everything, that way you have less to worry about if it leaks.
        • You can’t actually restrict a key to specific APIs unless you’ve enabled those APIs in your GCP project already. E.g. on a fresh project, you’ll see an empty list:
          • Pasted image 20240223085258.png
        • The API that you want to enable is the YouTube Data API (reference). Note that it’s “v3” at the time of writing (Fri 02/23/2024).
        • Make sure that you actually restrict your key after adding the YouTube API.
  • If you ever need a client ID or client secret, those come from creating a web application on the OAuth page on https://console.developers.google.com/.
    • First, you need to configure a consent screen. Unless you use Google Workspace, you have to make your app available to external users.
      • As part of this, you need to list which scopes your application needs. You can find those on each individual API page, e.g. here. For example, for posting messages, it says you need youtube and youtube.force-ssl, so I filtered for those:
        • 300
      • When it comes to adding test users, you add them by their email addresses.
    • Then, add a web application. For the redirect URI, I set mine to http://localhost:3005/oauth2callback since port 3000 would already be in use on my service.
  • If you want to send messages, you need to go through the OAuth flow since you can’t send messages with just an API key (it wouldn’t know which name, profile picture, etc. to use).
  • The type of an OAuth2Client is Auth.OAuth2Client (reference).
  • GaxiosError comes from googleapis.Common, e.g. import { Common } from "googleapis"if (error instanceof Common.GaxiosError).

“Innertube” is the name of the internal YouTube API. According to the YouTube terms of service, you can’t use it without express permission (reference). The exact quote is:

You must not use undocumented APIs without express permission. You must access data from YouTube API services only according to the means stipulated in the authorized documentation of that YouTube API service.

This means that you can’t use libraries like YouTube.js.

They also don’t allow scraping (reference):

You and your API Clients must not, and must not encourage, enable, or require others to, directly or indirectly, scrape YouTube Applications or Google Applications, or obtain scraped YouTube data or content. Public search engines may scrape data only in accordance with YouTube’s robots.txt file or with YouTube’s prior written permission.

Testing the API by getting live chat messages

Section titled Testing the API by getting live chat messages

You can test it right on the documentation pages. A good way to start is to list chat messages of a livestream. First, get the livestream information by calling a GET of liveBroadcasts here to get your video ID. You can seemingly only do this for your own channel with this API:

  • Set part to snippet
  • Set broadcastStatus to active
    • Note that this parameter is incompatible with mine == true for reasons that make no sense. When you don’t specify mine at all but have broadcastStatus == true, it will only fetch your streams anyway.

This returns a response like this:

{
"kind": "youtube#liveBroadcastListResponse",
"etag": "kPAw-WgvYdrs_sdO1CYzjAq6iz8",
"pageInfo": {
"totalResults": 1,
"resultsPerPage": 5
},
"items": [
{
"kind": "youtube#liveBroadcast",
"etag": "Ddty5p0thAxTIH2vKoMxEXT8724",
"id": "VnwVzZGj9hg",
"snippet": {
"publishedAt": "2024-02-23T16:28:05Z",
"channelId": "UC6fWshBRcmOrkaLAFU_ULbQ",
"title": "Figuring out YouTube's chat API",
"description": "Powered by Restream https://restream.io\n\nI want to make my bot work on YouTube. The commands are all available on https://a.bot.land , but I want them to be accessible here too with something like \"!today\".",
"thumbnails": {
"default": {
"url": "https://i.ytimg.com/vi/VnwVzZGj9hg/default_live.jpg",
"width": 120,
"height": 90
}
// "medium", "high", "standard", and "maxres" removed for brevity
},
"scheduledStartTime": "2024-02-23T16:28:14Z",
"actualStartTime": "2024-02-23T16:28:19Z",
"isDefaultBroadcast": false,
"liveChatId": "KicKGFVDNmZXc2hCUmNtT3JrYUxBRlVfVUxiURILVm53VnpaR2o5aGc"
}
}
]
}

From that, you can see the liveChatId, which is what you can provide to GET liveChatMessages (reference). For that API, I specified these params: Pasted image 20240223094625.png

Note that you have to click the ➕ next to part to specify multiple fields.

You have to keep polling for messages using LiveChatMessages: list (note that the internal API also just polls but abstracts that away for you). One of the response fields is pollingIntervalMillis, which is the amount of time that the client should wait before asking for more messages. This changes based on how active the chat is; if the chat is very active, then this time will be lower.

This official page says that you get 10k requests per day in your quota. Here’s where you see your usage. You can request more quota using this form.