'How to check if YouTube channel is streaming live

I can't find any informations to check if a YouTube channel is actually streaming or not. With Twitch you just need the channel name, and with the API you can check if there is a live or not.

I don't want to use OAuth, normally a public API key is enough. Like checking the videos of a channel I want to know if the channel is streaming.



Solution 1:[1]

The search-method (https://www.googleapis.com/youtube/v3/search) is awfully expensive to use though. It costs 100 quota units (https://developers.google.com/youtube/v3/determine_quota_cost) out of the 10,000 you have by default. This means you only get 100 requests per day which is terrible.

You could request an increase in the quota but that seems like brute forcing the the problem.

Is there really no other simpler method?

Solution 2:[2]

I know this is old, but I figured it out myself with PHP.

$API_KEY = 'your api3 key';
$ChannelID = 'the users channel id';

$channelInfo = 'https://www.googleapis.com/youtube/v3/search?part=snippet&channelId='.$ChannelID.'&type=video&eventType=live&key='.$API_KEY;

$extractInfo = file_get_contents($channelInfo);
$extractInfo = str_replace('},]',"}]",$extractInfo);
$showInfo = json_decode($extractInfo, true);

if($showInfo['pageInfo']['totalResults'] === 0){
    
    echo 'Users channel is Offline';
    
} else {

    echo 'Users channel is LIVE!';

}

Solution 3:[3]

Guys I found better way to do this. Yes, it requires you to make GET requests to a YouTube page and parse HTML, but it will work with newer versions + works with consent + works with captcha (most likely, 90%)

All you need to do is make a request to https://youtube.com/channel/[CHANNELID]/live and check the href attribute of the <link rel="canonical" /> tag.

For example,

<link rel="canonical" href="https://www.youtube.com/channel/UC4cueEAH9Oq94E1ynBiVJhw">

means there is no livestream, while

<link rel="canonical" href="https://www.youtube.com/watch?v=SR9w_ofpqkU">

means there is a stream, and you can even fetch its data by videoid.

Since canonical URL is very important for SEO and redirect does not work in GET or HEAD requests anymore, I recommend using my method.

Also here is the simple script I use:

import { parse } from 'node-html-parser'
import fetch from 'node-fetch'

const channelID = process.argv[2] // process.argv is array of arguments passed in console

const response = await fetch(`https://youtube.com/channel/${channelID}/live`)
const text = await response.text()
const html = parse(text)
const canonicalURLTag = html.querySelector('link[rel=canonical]')
const canonicalURL = canonicalURLTag.getAttribute('href')
const isStreaming = canonicalURL.includes('/watch?v=')

console.log(isStreaming)

Then run npm init -y && npm i node-html-parser node-fetch to create project in working directory and install dependencies

Then run node isStreaming.js UC4cueEAH9Oq94E1ynBiVJhw and it will print true/false (400-600 ms per one execution)

It does require you to depend on node-html-parser and node-fetch, but you can make requests with the built-in HTTP library (which sucks) and rewrite this to use regex. (Do not parse HTML with regex.)

Solution 4:[4]

I was also struggling with API limits. The most reliable and cheapest way I've found was simply a HEAD request to https://www.youtube.com/channel/CHANNEL_ID/live. If the channel is live then it will auto load the stream. If not then it will load the channels videos feed. You can simply check the Content-Length header size to determine which. If live the size is almost 2x when NOT live.

And depending on your region you might need to accept the cookies consent page. Just send your request with cookies={ "CONSENT": "YES+cb.20210420-15-p1.en-GB+FX+634" }.

Solution 5:[5]

Every YouTube channel as a permanent livestream, even if the channel is currently not actively livestreaming. In the liveStream resource, you can find a boolean named isDefaultStream.

But where can we get this video (livestream) id? Go to https://www.youtube.com/user/CHANNEL_ID/live, right click on the stream and copy the video URL.

You can now make a GET request to https://youtube.googleapis.com/youtube/v3/videos?part=liveStreamingDetails&id=[VIDEO_ID]&key=[API_KEY] (this request has a quota cost of 1 unit, see here)

This will be the result if the stream is currently active/online.

{
    "kind": "",
    "etag": "",
    "items": [
        {
            "kind": "",
            "etag": "",
            "id": "",
            "liveStreamingDetails": {
                "actualStartTime": "",
                "scheduledStartTime": "",
                "concurrentViewers": "",
                "activeLiveChatId": ""
            }
        }
    ],
    "pageInfo": {
        "totalResults": 1,
        "resultsPerPage": 1
    }
}

If the stream is currently offline, the property concurrentViewers will not exist. In other words, the only difference between an online and offline livestream is that concurrentViewers is present or not present. With this information, you can check, if the channel is currently streaming or not (at least for his default stream).

Solution 6:[6]

if you point streamlink at a https://www.youtube.com/channel/CHANNEL_ID/live link, it will tell you if it is live or not

$ streamlink "https://www.youtube.com/channel/UCSJ4gkVC6NrvII8umztf0Ow/live"
[cli][info] Found matching plugin youtube for URL https://www.youtube.com/channel/UCSJ4gkVC6NrvII8umztf0Ow/live
Available streams: 144p (worst), 240p, 360p, 480p, 720p, 1080p (best)
$ streamlink "https://www.youtube.com/c/mkbhd/live"          
[cli][info] Found matching plugin youtube for URL https://www.youtube.com/c/mkbhd/live
error: Could not find a video on this page

Solution 7:[7]

I found youtube API to be very restrictive given the cost of search operation. Web scraping with aiohttp and beautifulsoup was not an option since the better indicators required javascript support. Hence I turned to selenium. I looked for the css selector

#info-text and then search for the string Started streaming or with watching now in it.

You can run a small API on heroku with flask as well.

Solution 8:[8]

The easisest way that I have found to this has been scraping the site. This can be done by finding this: <link rel="canonical" href="linkToActualYTLiveVideoPage"> as in Vitya's answer.

This is my simple Python code using bs4:

import requests
from bs4 import BeautifulSoup

def is_liveYT():
    channel_url = "https://www.youtube.com/c/LofiGirl/live"
    page = requests.get(channel_url, cookies={'CONSENT': 'YES+42'})
    soup = BeautifulSoup(page.content, "html.parser")
    live = soup.find("link", {"rel": "canonical"})
    if live: 
        print("Streaming")
    else:
        print("Not Streaming")

if __name__ == "__main__":
    is_liveYT()

It is pretty weird, honestly, that YouTube doesn't have a simple way to do this through the API, although this is probably easier.

Solution 9:[9]

I found the answer by @VityaSchel to be quite useful, but it doesn't distinguish between channels which have a live broadcast scheduled, and those which are broadcasting live now.

To distinguish between scheduled and live, I have extended his code to access the YouTube Data API to find the live streaming details:

import { parse } from 'node-html-parser'
import fetch from 'node-fetch'

const youtubeAPIkey = 'YOUR_YOUTUBE_API_KEY'
const youtubeURLbase = 'https://www.googleapis.com/youtube/v3/videos?key=' + youtubeAPIkey + '&part=liveStreamingDetails,snippet&id='

const c = {cid: process.argv[2]}    // process.argv is array of arguments passed in console

const response = await fetch(`https://youtube.com/channel/${c.cid}/live`)
const text = await response.text()
const html = parse(text)
const canonicalURLTag = html.querySelector('link[rel=canonical]')
const canonicalURL = canonicalURLTag.getAttribute('href')

c.live = false
c.configured = canonicalURL.includes('/watch?v=')
if (!c.configured) process.exit()

c.vid = canonicalURL.match(/(?<==).*/)[0]

const data = await fetch(youtubeURLbase + c.vid).then(response => response.json())
if (data.error) {
    console.error(data)
    process.exit(1)
}
const i = data.items.pop()  // pop() grabs the last item
c.title = i.snippet.title
c.thumbnail = i.snippet.thumbnails.standard.url
c.scheduledStartTime = i.liveStreamingDetails.scheduledStartTime
c.live = i.liveStreamingDetails.hasOwnProperty('actualStartTime')
if (c.live) {
    c.actualStartTime = i.liveStreamingDetails.actualStartTime
}

console.log(c)

Sample output from the above:

% node index.js UCNlfGuzOAKM1sycPuM_QTHg
{
  cid: 'UCNlfGuzOAKM1sycPuM_QTHg',
  live: true,
  configured: true,
  vid: '8yRgYiNH39E',
  title: '? Deep Focus 24/7 - Ambient Music For Studying, Concentration, Work And Meditation',
  thumbnail: 'https://i.ytimg.com/vi/8yRgYiNH39E/sddefault_live.jpg',
  scheduledStartTime: '2022-05-23T01:25:00Z',
  actualStartTime: '2022-05-23T01:30:22Z'
}

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 Smorfty
Solution 2 Michael
Solution 3 Michael
Solution 4
Solution 5 Michael
Solution 6 Elijah Yap
Solution 7
Solution 8 Michael
Solution 9 Michael