9

My final goal is to set up a Webhook whenever a YouTube user uploads a video. After some research I got to this article.

But when I get to the part https://www.youtube.com/xml/feeds/videos.xml?channel_id=CHANNEL_ID, I got Restricted topic error when trying the subscribe to the Google/SuperFeedr hubs. I also got my callback URL working.

The topic I want to subscribe to is this: https://www.youtube.com/xml/feeds/videos.xml?channel_id=UC7T8roVtC_3afWKTOGtLlBA

Which shows nothing upon visiting via a browser.

Am I doing something wrong? I've been struggling for a few hours now, any help is appreciated. Thanks!

UPDATE: I found this, but those feeds doesn't have the rel=”hub” attribute, so probably useless if I want to subscribe it to hub.

Poyu
  • 116
  • 1
  • 1
  • 6
  • Not sure why Google points to a superfeedr hub, because... well, they don't ping us! However, you should get data from their hub. – Julien Genestoux Apr 23 '15 at 13:15
  • 1
    Same issue here. It also took me long time to realise that `https://www.youtube.com/XML/feeds/videos.xml?channel_id=` url were different from `` given in youtube channel page source code – user3498909 Apr 24 '15 at 11:25
  • Did you manage to make it work ? – user3498909 Apr 24 '15 at 11:41
  • Has anyone managed to make this work with Youtube API v3? I'm getting the restricted topic as well and no notifcations ... – thomas May 07 '15 at 09:54
  • Well, I found [this](http://www.reddit.com/r/youtube/comments/339idg/youtube_just_dropped_its_support_for_rssatom_feeds/), but that feed doesn't have `rel=”hub”` so it's useless to me. Tried subscribing to that, but never get any notifications. It's really frustrating... – Poyu May 07 '15 at 13:13
  • Really hoping for some help here, I've had the same problem. Someone also has listed here: https://code.google.com/p/gdata-issues/issues/detail?id=7138 – Nicholas Petersen May 12 '15 at 09:11
  • See also the discussion here (no answers given though): https://code.google.com/p/gdata-issues/issues/detail?id=5602 – Nicholas Petersen May 12 '15 at 09:14
  • I was the one that created [issue 7138](https://code.google.com/p/gdata-issues/issues/detail?id=7138), hope they answer us soon. – Poyu May 12 '15 at 13:06
  • 1
    It has been fixed : https://code.google.com/p/gdata-issues/issues/detail?id=7138#c15 – user3498909 Oct 28 '15 at 15:45
  • 2
    Worked for me using the `https://www.youtube.com/xml/feeds/videos.xml?channel_id=CHANNEL_ID` format now (subscriber diagnostics at https://pubsubhubbub.appspot.com/subscribe didn't work though..). – danmichaelo May 29 '17 at 17:19

4 Answers4

8
  1. you need to send request to subscribe a channel
  2. a callback that varifies the subscription request and get actual data on update

subscribe function:

subscribe.php may look like:

<?php

function subscribeYoutubeChannel($channel_id = null, $subscribe = true) {
    $subscribe_url = 'https://pubsubhubbub.appspot.com/subscribe';
    $topic_url = 'https://www.youtube.com/xml/feeds/videos.xml?channel_id={CHANNEL_ID}';
    $callback_url = 'http://' . $_SERVER['SERVER_NAME'] . str_replace(basename($_SERVER['REQUEST_URI']), '', $_SERVER['REQUEST_URI']) . 'youtube_subscribe_callback.php';

    $data = array(
        'hub.mode' => $subscribe ? 'subscribe' : 'unsubscribe',
        'hub.callback' => $callback_url,
        'hub.lease_seconds'=>60*60*24*365,
        'hub.topic'=> str_replace(array(
            '{CHANNEL_ID}'
        ), array(
            $channel_id
        ), $topic_url)
    );

    $opts = array('http' =>
        array(
            'method'  => 'POST',
            'header'  => 'Content-type: application/x-www-form-urlencoded',
            'content' => http_build_query($data)
        )
    );

    $context  = stream_context_create($opts);

    @file_get_contents($subscribe_url, false, $context);

    return preg_match('200', $http_response_header[0]) === 1;
}

after the request is sent, the pusub service will call youtube_subscribe_callback.php to verify the subscription it will use the GET method and it expects to receive an answer which is "hub_challenge". after that if you upload a video to your test channel youtube_subscribe_callback.php will receive POST request with data.

so youtube_subscribe_callback.php (defined in subscribeYoutubeChannel function) may look like:

 <?php
    if (isset($_GET['hub_challenge'])) {
        echo $_REQUEST['hub_challenge'];
    } else {
    
        $video = parseYoutubeUpdate(file_get_contents('php://input'));
        
    }
    
    function parseYoutubeUpdate($data) {
        $xml = simplexml_load_string($data, 'SimpleXMLElement', LIBXML_NOCDATA);
        $video_id = substr((string)$xml->entry->id, 9);
        $channel_id = substr((string)$xml->entry->author->uri, 32);
        $published = (string)$xml->entry->published;
    
        return array(
            'video_id'=>$video_id,
            'channel_id'=>$channel_id,
            'published'=>$published
        );
    }
Sam Carlton
  • 1,190
  • 1
  • 17
  • 18
salexch
  • 2,644
  • 1
  • 20
  • 17
  • It's 'hub.challenge' not 'hub_challenge' (at least now it is). Also, maybe useful for someone to know specifically that this value for 'hub.challenge' is passed as a query param (not in headers or body) when the callback URL is hit after the subscription request. – timraybould Sep 18 '19 at 13:10
  • Do you know if there is a limit in the number of channels I can subscribe to? I am thinking about using this as the primary way to get a channel update, but for hundreds of thousands of channels. – Alex Benfica May 26 '20 at 15:49
  • 2
    @timraybould PHP will replace dot with underscore in $_GET, so 'hub_challenge' is correct here. – Markus Laire Sep 06 '20 at 13:46
3

I wasn't able to subscribe channel by id, but was able to do it by username:

https://www.youtube.com/feeds/videos.xml?user=username

So, you go to this page:

https://pubsubhubbub.appspot.com/subscribe

Insert your callback URL, RSS feed from youtube with username, and mode "subscribe".

Don't forget to reply from your callback URL, so it can confirm subscription, in PHP just print:

echo $_REQUEST["hub_challenge"];

More details here and here.

dikirill
  • 1,873
  • 1
  • 19
  • 21
  • BTW, I've subscribed yesterday through pubsubhubbub one of news channels on youtube, and never get ping back to my callback url. So, I'm not sure if this works for youtube RSS feeds. – dikirill Sep 03 '15 at 13:39
3

The process is usually two steps, first you go to the subscribe page, input your callback server url, topic url (which is basically the feed url for the ytb channel you want to listen to, the other fields are optional), the pub server will verify your subscription with a GET request to your callback server, in go it can look like this:

http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
    challenge := r.URL.Query().Get("hub.challenge")
    if challenge != "" {
        fmt.Fprintf(w, challenge)
    }
})

Then on every new video (or title, desc of an old video is updated), the pub will submit a POST request to your server with an xml in the body looking similar to this:

<?xml version='1.0' encoding='UTF-8'?>
<feed xmlns:yt="http://www.youtube.com/xml/schemas/2015" xmlns="http://www.w3.org/2005/Atom">
  <link rel="hub" href="https://pubsubhubbub.appspot.com" />
  <link rel="self" href="https://www.youtube.com/xml/feeds/videos.xml?channel_id=UCtEorrVfo4GQsN82HsrnKyk" />
  <title>YouTube video feed</title>
  <updated>2018-12-12T06:02:55.950497732+00:00</updated>
  <entry>
    <id>yt:video:_em_FFNUcvs</id>
    <yt:videoId>_em_FFNUcvs</yt:videoId>
    <yt:channelId>UCtEorrVfo4GQsN82HsrnKyk</yt:channelId>
    <title>December 12, 20</title>
    <link rel="alternate" href="https://www.youtube.com/watch?v=_em_FFNUcvs" />
    <author>
      <name>Ak Ram</name>
      <uri>https://www.youtube.com/channel/UCtEorrVfo4GQsN82HsrnKyk</uri>
    </author>
    <published>2018-12-12T05:57:07+00:00</published>
    <updated>2018-12-12T06:02:55.950497732+00:00</updated>
  </entry>
</feed>
Akram Saouri
  • 1,179
  • 8
  • 15
1

I think The guide's url is wrong

https://www.youtube.com/xml/feeds/videos.xml is not working anymore. but without /xml then is working.

There is a sample.

https://www.youtube.com/feeds/videos.xml?channel_id=UCJHiO2Dfao-qpYiA79swtAA https://www.youtube.com/xml/feeds/videos.xml?channel_id=UCJHiO2Dfao-qpYiA79swtAA