Skip to content

Discover WebSub Hubs ​

Feedscout can discover WebSub (formerly PubSubHubbub) hubs from feeds and webpages. Hubs enable real-time notifications when content is updated.

What Is WebSub? ​

WebSub is a protocol for real-time content updates. A hub acts as an intermediary between publishers and subscribers:

  1. Publishers notify the hub when content changes.
  2. Subscribers receive instant updates from the hub.

Each hub result contains:

  • hub: The hub URL to subscribe to.
  • topic: The feed URL that the hub serves updates for.

Basic Usage ​

typescript
import { discoverHubs } from 'feedscout'

const hubs = await discoverHubs('https://example.com/feed.xml', {
  methods: ['headers', 'feed', 'html'],
})

Each result contains the hub and topic URLs:

typescript
{
  hub: 'https://pubsubhubbub.appspot.com/',
  topic: 'https://example.com/feed.xml',
}

Without a rel="self" link, topic falls back to the input URL. A hub found by two methods with the same topic is returned once.

Discovery Methods ​

Unlike feed discovery, hub discovery uses three different methods:

MethodSourceDescription
headersHTTP Link headersParses rel="hub" and rel="self" links
feedFeed contentExtracts hub links from Atom, RSS, or JSON Feed
htmlHTML contentScans for <link rel="hub"> elements

Headers Method ​

Parses HTTP Link headers for hub information:

http
Link: <https://pubsubhubbub.appspot.com>; rel="hub"
Link: <https://example.com/feed.xml>; rel="self"

Feed Method ​

Extracts hub links from feed content:

Atom feeds:

jsx
<feed xmlns="http://www.w3.org/2005/Atom">
  <link rel="hub" href="https://pubsubhubbub.appspot.com" />
  <link rel="self" href="https://example.com/feed.xml" />
</feed>

// [{
//   hub: 'https://pubsubhubbub.appspot.com/',
//   topic: 'https://example.com/feed.xml',
// }]

RSS feeds with Atom namespace:

jsx
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
  <channel>
    <atom:link rel="hub" href="https://pubsubhubbub.appspot.com" />
    <atom:link rel="self" href="https://example.com/feed.xml" />
  </channel>
</rss>

// [{
//   hub: 'https://pubsubhubbub.appspot.com/',
//   topic: 'https://example.com/feed.xml',
// }]

JSON Feed:

json
{
  "version": "https://jsonfeed.org/version/1.1",
  "feed_url": "https://example.com/feed.json",
  "hubs": [
    { "type": "WebSub", "url": "https://pubsubhubbub.appspot.com" }
  ]
}

// [{
//   hub: 'https://pubsubhubbub.appspot.com/',
//   topic: 'https://example.com/feed.json',
// }]

HTML Method ​

Scans for <link> elements in HTML:

html
<link rel="hub" href="https://pubsubhubbub.appspot.com" />
<link rel="self" href="https://example.com/feed.xml" />

Specifying Methods ​

Control which methods to use:

typescript
// Use all methods
const hubs = await discoverHubs(feedUrl, {
  methods: ['headers', 'feed', 'html'],
})

// Feed content only
const hubs = await discoverHubs(feedUrl, {
  methods: ['feed'],
})

Using Existing Content ​

If you already have the content and headers, pass them directly:

typescript
const response = await fetch('https://example.com/feed.xml')
const content = await response.text()

const hubs = await discoverHubs(
  {
    url: 'https://example.com/feed.xml',
    content,
    headers: response.headers,
  },
  {
    methods: ['headers', 'feed'],
  },
)

Custom Fetch Function ​

Use a custom HTTP client. See Customize Data Fetching for examples with Axios, Got, Ky, and more.

Specifications ​

Hub discovery follows these specifications: