Guess Method
The Guess method tests common feed paths against the base URL as a fallback when other methods don't find feeds.
How It Works
Many websites place feeds at predictable paths. The Guess method tests these paths:
/feed
/rss
/atom.xml
/feed.xml
/rss.xml
/index.xmlEach path is appended to the base URL and checked for a valid feed.
Ancestor Paths
Some sites serve their feed from a section directory, not the root. An example is a post at /blog/post-slug/ with the feed at /blog/feed.xml. In addition to the root-level paths, the Guess method tests path-style URIs against the directory ancestors of the base URL:
https://example.com/blog/post-slug/
→ https://example.com/feed.xml (root)
→ https://example.com/blog/feed.xml (ancestor)
→ https://example.com/blog/post-slug/feed.xmlThe maxAncestorDepth option controls how many directory levels from the root are tested (default: 2 for feeds). Set it to 0 to only test root-level paths:
const feeds = await discoverFeeds(url, {
methods: {
guess: {
maxAncestorDepth: 0,
},
},
})Every configured URI is tested against each ancestor directory the same way it is tested against the root: /feed.xml resolves under the directory, and a bare query URI like ?feed=rss is appended to it (https://example.com/blog/?feed=rss).
Section Links
Sites often keep their feed under a content section that isn't part of the current page's path. An example is a homepage linking to /blog with the feed at /blog/rss.xml. The Guess method scans the page HTML for same-origin links whose path is a single section segment and tests path-style URIs against them:
https://example.com/ with <a href="/blog">
→ https://example.com/blog/rss.xml
→ https://example.com/blog/feed.xml
→ ...The recognized section segments are exported as sectionNames:
import { sectionNames } from 'feedscout/feeds'
// ['blog', 'news', 'posts', 'articles', 'writing', 'notes', 'journal', 'podcast', 'changelog']You can pass your own list:
const feeds = await discoverFeeds(url, {
methods: {
guess: {
sectionNames: ['blog', 'updates'],
},
},
})Setting sectionNames: [] disables section-link probing.
URI Sets
There are three predefined URI sets:
Minimal
Basic paths that cover most modern sites:
import { urisMinimal } from 'feedscout/feeds'
// [
// '/feed',
// '/rss',
// '/atom.xml',
// '/feed.xml',
// '/rss.xml',
// '/index.xml',
// ]Balanced (Default)
Includes JSON Feed and common variations:
import { urisBalanced } from 'feedscout/feeds'
// urisMinimal + [
// '/feed/',
// '/index.atom',
// '/index.rss',
// '/feed.json',
// ]Comprehensive
Includes WordPress, Blogger, and many other patterns:
import { urisComprehensive } from 'feedscout/feeds'
// urisBalanced + [
// '/atom',
// '/rss2.xml',
// '?format=rss',
// '?rss=1',
// '/feeds/posts/default',
// ...
// ]Query URIs behave differently from path URIs: a bare ?format=rss is appended to the current page's path (https://example.com/blog?format=rss), while /-prefixed paths always resolve from the site root. This matches platforms like WordPress and Squarespace that serve feeds via a query parameter on the page you're on.
Configuration
Feedscout comes with reasonable defaults, but you can customize which paths are tested if needed.
Custom URIs
Specify which paths to test:
const feeds = await discoverFeeds(url, {
methods: {
guess: {
uris: ['/feed', '/rss.xml', '/custom-feed'],
},
},
})Additional Base URLs
Test paths on additional domains (e.g., subdomains):
import { getWwwCounterpart, getSubdomainVariants } from 'feedscout/methods'
const feeds = await discoverFeeds('https://example.com', {
methods: {
guess: {
uris: ['/feed', '/rss.xml'],
additionalBaseUrls: [
getWwwCounterpart('https://example.com'),
...getSubdomainVariants('https://example.com', ['blog', 'feeds']),
],
},
},
})This will test:
https://example.com/feedhttps://www.example.com/feedhttps://blog.example.com/feedhttps://feeds.example.com/feed- (and the same for
/rss.xml)
Utility Functions
getWwwCounterpart
Returns the www or non-www variant of a URL:
import { getWwwCounterpart } from 'feedscout/methods'
getWwwCounterpart('https://example.com')
// 'https://www.example.com'
getWwwCounterpart('https://www.example.com')
// 'https://example.com'getSubdomainVariants
Generates subdomain variants of a URL:
import { getSubdomainVariants } from 'feedscout/methods'
getSubdomainVariants('https://example.com', ['blog', 'feeds'])
// [
// 'https://blog.example.com',
// 'https://feeds.example.com',
// ]generateUrlCombinations
Combines base URLs with URI paths:
import { generateUrlCombinations } from 'feedscout/methods'
generateUrlCombinations(['https://example.com'], ['/feed', '/rss'])
// [
// 'https://example.com/feed',
// 'https://example.com/rss',
// ]Default Values
You can import the default Guess options:
import { defaultGuessOptions } from 'feedscout/feeds'Using Directly
You can use the Guess discovery function directly:
import { discoverUrisFromGuess } from 'feedscout/methods'
const uris = discoverUrisFromGuess({
baseUrl: 'https://example.com',
uris: ['/feed', '/rss.xml'],
})
// [
// 'https://example.com/feed',
// 'https://example.com/rss.xml',
// ]NOTE
The Guess method builds absolute URLs from the base URL. It does not check if they exist. Validation happens in discoverFeeds.
When to Use
The Guess method should typically be used as a fallback:
const feeds = await discoverFeeds(url, {
methods: ['html', 'headers', 'guess'],
})Since it generates many URLs to test, it's slower than HTML and Headers methods. Use it when:
- HTML and Headers methods don't find any feeds.
- You suspect a feed exists but isn't properly advertised.
- You're scanning a site that doesn't follow autodiscovery standards.