30

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.

mpgn
  • 7,121
  • 9
  • 67
  • 100
  • Related: https://stackoverflow.com/questions/44615704/push-notifications-for-new-live-broadcasts-via-pubsubhubbub – Xeoncross Apr 08 '19 at 14:08

11 Answers11

38

You can do this by using search.list and specifying the channel ID, setting the type to video, and setting eventType to live.

For example, when I searched for:

https://www.googleapis.com/youtube/v3/search?part=snippet&channelId=UCXswCcAMb5bvEUIDEzXFGYg&type=video&eventType=live&key=[API_KEY]

I got the following:


{
 "kind": "youtube#searchListResponse",
 "etag": "\"sGDdEsjSJ_SnACpEvVQ6MtTzkrI/gE5P_aKHWIIc6YSpRcOE57lf9oE\"",
 "pageInfo": {
  "totalResults": 1,
  "resultsPerPage": 5
 },
 "items": [
  {
   "kind": "youtube#searchResult",
   "etag": "\"sGDdEsjSJ_SnACpEvVQ6MtTzkrI/H-6Tm7-JewZC0-CW4ALwOiq9wjs\"",
   "id": {
    "kind": "youtube#video",
    "videoId": "W4HL6h-ZSws"
   },
   "snippet": {
    "publishedAt": "2015-09-08T11:46:23.000Z",
    "channelId": "UCXswCcAMb5bvEUIDEzXFGYg",
    "title": "Borussia Dortmund vs St. Pauli 1-0 Live Stream",
    "description": "Borussia Dortmund vs St. Pauli Live Stream Friendly Match.",
    "thumbnails": {
     "default": {
      "url": "https://i.ytimg.com/vi/W4HL6h-ZSws/default.jpg"
     },
     "medium": {
      "url": "https://i.ytimg.com/vi/W4HL6h-ZSws/mqdefault.jpg"
     },
     "high": {
      "url": "https://i.ytimg.com/vi/W4HL6h-ZSws/hqdefault.jpg"
     }
    },
    "channelTitle": "",
    "liveBroadcastContent": "live"
   }
  }
 ]
}
Michael
  • 8,362
  • 6
  • 61
  • 88
not_a_bot
  • 2,332
  • 2
  • 19
  • 33
13

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?

Smorfty
  • 139
  • 1
  • 4
  • 1
    Welcome to SO. This post doesn't really answer the question. When you get more reputation, you'll be able to post this sort of material as comments... – Nick Apr 02 '19 at 17:36
  • 13
    this is exactly my battle right now in 2019... hard to imagine youtube doesn't provide a cheap API request just to see if a channel is live... using the liveBroadcast API doesn't help because it's not comprehensive to me and there is no way to specify a channel... – aequalsb Oct 18 '19 at 19:15
  • May help: https://stackoverflow.com/questions/56385532/how-to-find-if-a-youtube-channel-is-currently-live-streaming-without-using-searc – Lee Goddard Jul 28 '20 at 15:06
10

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!';

}
Michael
  • 8,362
  • 6
  • 61
  • 88
TJ Dobbs
  • 101
  • 1
  • 2
  • 1
    There is a more-complete, official code sample for listing live streams: https://github.com/youtube/api-samples/blob/master/php/list_streams.php – Xeoncross Apr 08 '19 at 14:13
10

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.)

Michael
  • 8,362
  • 6
  • 61
  • 88
VityaSchel
  • 579
  • 7
  • 18
  • Backlinked from [another answer](https://stackoverflow.com/a/67005488/241211). – Michael Feb 09 '22 at 17:49
  • 1
    Thank you. Great answer. Not using the Google API is generally preferred, as it forces a lot of artifical limitations & weirdness, whereas parsing a HTML page at least gives you the "real result" you are looking for.... – Akito Jan 25 '23 at 22:40
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" }.

eth0
  • 4,977
  • 3
  • 34
  • 48
2

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

  • e.g. lofi beats is usually live,

    $ 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)
    
  • whereas MKBHD is not

    $ 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
    
Michael
  • 8,362
  • 6
  • 61
  • 88
Elijah Yap
  • 373
  • 2
  • 5
1

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.

Michael
  • 8,362
  • 6
  • 61
  • 88
1

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).

Michael
  • 8,362
  • 6
  • 61
  • 88
Optimal
  • 407
  • 3
  • 9
1

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'
}
Michael
  • 8,362
  • 6
  • 61
  • 88
Brett Donald
  • 6,745
  • 4
  • 23
  • 51
0

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.

Monu Yadav
  • 519
  • 2
  • 17
0

Here is another solution without usage of the YouTube Data API. If you parse out these meta tags they tell you if it is a live broadcast along with the start time. If these tags are missing, then the channel is not live.

There are also additional meta tags available that list out the title, description and other useful information.

To view whether it is a scheduled stream, just check the startDate and compare it to the current time.

<span itemprop="publication" itemscope itemtype="http://schema.org/BroadcastEvent">
   <meta itemprop="isLiveBroadcast" content="True">
   <meta itemprop="startDate" content="2022-07-13T21:47:38+00:00">
</span>

You can query for these tags by:

document.querySelector('meta[itemprop="isLiveBroadcast"]').content === "True"

Sidenote: You don't even need to parse the HTML to know, since the tag won't exist at all if the channel isn't live, so here's a quick and dirty solution:

const data = await fetch(`https://www.youtube.com/[id]/live`)
const isLive = (await data.text()).includes('isLiveBroadcast')
cyw
  • 520
  • 1
  • 4
  • 14