feed, feedparser, rss, and rss-parser are npm packages that handle RSS and Atom feed operations in JavaScript applications. feed and rss focus on generating valid RSS, Atom, and JSON Feed output from structured data, while feedparser and rss-parser specialize in parsing existing XML-based feeds into usable JavaScript objects. These tools enable developers to syndicate content or consume external feeds in Node.js or browser environments, though their capabilities, maintenance status, and architectural approaches differ significantly.
When building applications that publish or consume syndicated content, you’ll likely encounter RSS, Atom, or JSON Feed formats. The four packages under review fall into two distinct categories: feed generators (feed, rss) and feed parsers (feedparser, rss-parser). Understanding their roles, capabilities, and current state is crucial for making the right architectural choice.
feed and rss help you produce standardized feed documents from your content.
// Using `feed` to generate multiple formats
import { Feed } from 'feed';
const feed = new Feed({
title: 'My Blog',
description: 'Tech insights',
id: 'https://example.com/',
link: 'https://example.com/',
language: 'en',
feedLinks: {
rss2: 'https://example.com/rss.xml',
atom: 'https://example.com/atom.xml'
}
});
feed.addItem({
title: 'Post 1',
id: 'https://example.com/post1',
link: 'https://example.com/post1',
description: 'Content here',
date: new Date()
});
const rssFeed = feed.rss2(); // RSS 2.0 string
const atomFeed = feed.atom1(); // Atom 1.0 string
const jsonFeed = feed.json1(); // JSON Feed 1.0 string
// Using `rss` (RSS 2.0 only)
import RSS from 'rss';
const feed = new RSS({
title: 'My Blog',
description: 'Tech insights',
feed_url: 'https://example.com/rss.xml',
site_url: 'https://example.com/'
});
feed.item({
title: 'Post 1',
description: 'Content here',
url: 'https://example.com/post1',
date: new Date()
});
const rssString = feed.xml(); // Only RSS 2.0
rss-parser and the deprecated feedparser help you read and extract data from existing feed URLs or XML strings.
// Using `rss-parser` (modern, maintained)
import Parser from 'rss-parser';
const parser = new Parser();
const feed = await parser.parseURL('https://example.com/feed.xml');
console.log(feed.title);
feed.items.forEach(item => console.log(item.title));
// Also works with raw XML
const feedFromXml = await parser.parseString(xmlString);
// Using `feedparser` (deprecated — do not use)
// const FeedParser = require('feedparser');
// const feedparser = new FeedParser();
// request('http://example.com/feed.xml')
// .pipe(feedparser)
// .on('readable', function() {
// let item;
// while (item = this.read()) {
// console.log(item.title);
// }
// });
// This approach is outdated and unsupported.
⚠️ Critical Note:
feedparseris officially deprecated. Its npm page states: "This package is no longer maintained." Do not use it in new projects.
| Package | RSS 2.0 | Atom 1.0 | JSON Feed | RDF |
|---|---|---|---|---|
feed | ✅ | ✅ | ✅ | ❌ |
rss | ✅ | ❌ | ❌ | ❌ |
rss-parser | ✅ | ✅ | ❌ | ✅ |
feedparser | ✅ | ✅ | ❌ | ✅ |
If you need to generate Atom or JSON Feed, only feed supports them. If you’re parsing RDF feeds, both rss-parser and the deprecated feedparser handle them, but only rss-parser is safe to use.
feed offers a fluent, object-oriented API with strong TypeScript definitions. It validates inputs and escapes content automatically, reducing XSS risks.
rss uses a simpler, procedural style. It’s easy to get started but lacks built-in escaping — you must sanitize content yourself.
rss-parser provides a promise-based interface with consistent output regardless of input format. It normalizes fields like pubDate → isoDate and link → link, making consumption predictable.
feedparser used a streaming, event-driven model based on Node.js streams. While memory-efficient for large feeds, this pattern is harder to use and doesn’t work in browsers.
feed: Works in Node.js and browsers (via bundlers). No external dependencies.rss: Pure JavaScript, works everywhere.rss-parser: Works in Node.js and browsers. In browsers, you must provide XML text (due to CORS); it can’t fetch URLs directly.feedparser: Node.js only (relies on streams and HTTP modules).feed: Actively maintained, auto-escapes HTML in titles/descriptions.rss: Minimal maintenance, but stable; you must escape user-generated content.rss-parser: Actively maintained, uses xml2js under the hood with secure defaults.feedparser: Deprecated, contains unpatched vulnerabilities, and uses outdated dependencies.You run a Next.js blog and want to offer RSS, Atom, and JSON Feed.
feed// Next.js API route
import { Feed } from 'feed';
export default function handler(req, res) {
const feed = new Feed({ /* ... */ });
posts.forEach(post => feed.addItem({ /* ... */ }));
if (req.query.format === 'atom') {
res.setHeader('Content-Type', 'application/atom+xml');
res.send(feed.atom1());
} else if (req.query.format === 'json') {
res.setHeader('Content-Type', 'application/json');
res.send(feed.json1());
} else {
res.setHeader('Content-Type', 'application/rss+xml');
res.send(feed.rss2());
}
}
You’re building a feed reader that pulls from various RSS/Atom endpoints.
rss-parserconst parser = new Parser();
const urls = ['https://a.com/feed', 'https://b.com/atom'];
const feeds = await Promise.all(
urls.map(url => parser.parseURL(url))
);
const allItems = feeds.flatMap(feed =>
feed.items.map(item => ({
title: item.title,
source: feed.title,
link: item.link
}))
);
You have a small Eleventy or Hugo-like site and only need basic RSS 2.0.
rssconst feed = new RSS({
title: 'My Site',
site_url: 'https://mysite.com',
feed_url: 'https://mysite.com/rss.xml'
});
posts.forEach(post => feed.item({
title: post.title,
description: post.excerpt,
url: `https://mysite.com${post.url}`,
date: post.date
}));
fs.writeFileSync('rss.xml', feed.xml());
| Feature | feed | rss | rss-parser | feedparser |
|---|---|---|---|---|
| Status | ✅ Active | ✅ Stable | ✅ Active | ❌ Deprecated |
| Primary Role | Generator | Generator | Parser | Parser |
| RSS 2.0 | ✅ | ✅ | ✅ | ✅ |
| Atom 1.0 | ✅ | ❌ | ✅ | ✅ |
| JSON Feed | ✅ | ❌ | ❌ | ❌ |
| Browser Support | ✅ | ✅ | ✅ (with XML text) | ❌ |
| Auto-Escaping | ✅ | ❌ | N/A | ❌ |
| TypeScript | ✅ | ❌ | ✅ | ❌ |
feed for full format support and safety, or rss for minimal RSS-only needs.rss-parser. Never use feedparser.These tools solve different halves of the syndication problem. Pick the right one for your side of the equation — and always verify that your chosen package is actively maintained and secure.
Choose feed if you need a modern, well-maintained library for generating RSS 2.0, Atom 1.0, and JSON Feed 1.0 from JavaScript objects. It provides a clean, fluent API with strong TypeScript support and handles edge cases like escaping and date formatting correctly. Ideal for blogs, news sites, or any application that needs to publish machine-readable content feeds.
Avoid feedparser in new projects — it is officially deprecated per its npm page and GitHub repository. While it was once a streaming SAX-based parser for RSS and Atom feeds in Node.js, it hasn't been updated in years and lacks support for modern JavaScript features, security patches, and feed format variations. Use rss-parser instead for parsing needs.
Choose rss if you only need to generate RSS 2.0 feeds (not Atom or JSON Feed) and prefer a minimal, dependency-free solution. It’s a lightweight generator with a straightforward API, but it doesn’t support newer feed standards or advanced metadata. Suitable for simple use cases where bundle size is critical and Atom/JSON Feed isn’t required.
Choose rss-parser if your primary need is parsing RSS, Atom, or RDF feeds from external sources into consistent JavaScript objects. It works in both Node.js and browsers, normalizes fields across feed types, and supports custom XML parsing options. Best for aggregators, readers, or any app consuming third-party feeds.
jpmonette/feed - RSS 2.0, JSON Feed 1.0, and Atom 1.0 generator for Node.js
Making content syndication simple and intuitive!
👩🏻💻 Developer Ready: Quickly generate syndication feeds for your Website.
💪🏼 Strongly Typed: Developed using TypeScript / type-safe.
🔒 Tested: Tests & snapshot for each syndication format to avoid regressions.
$ yarn add feed
import { Feed } from "feed";
const feed = new Feed({
title: "Feed Title",
description: "This is my personal feed!",
id: "http://example.com/",
link: "http://example.com/",
language: "en", // optional, used only in RSS 2.0, possible values: http://www.w3.org/TR/REC-html40/struct/dirlang.html#langcodes
image: "http://example.com/image.png",
favicon: "http://example.com/favicon.ico",
copyright: "All rights reserved 2013, John Doe",
updated: new Date(2013, 6, 14), // optional, default = today
generator: "awesome", // optional, default = 'https://github.com/jpmonette/feed'
feedLinks: {
json: "https://example.com/json",
atom: "https://example.com/atom",
},
author: {
name: "John Doe",
email: "johndoe@example.com",
link: "https://example.com/johndoe",
},
});
posts.forEach((post) => {
feed.addItem({
title: post.title,
id: post.url,
link: post.url,
description: post.description,
content: post.content,
author: [
{
name: "Jane Doe",
email: "janedoe@example.com",
link: "https://example.com/janedoe",
},
{
name: "Joe Smith",
email: "joesmith@example.com",
link: "https://example.com/joesmith",
},
],
contributor: [
{
name: "Shawn Kemp",
email: "shawnkemp@example.com",
link: "https://example.com/shawnkemp",
},
{
name: "Reggie Miller",
email: "reggiemiller@example.com",
link: "https://example.com/reggiemiller",
},
],
date: post.date,
image: post.image,
});
});
feed.addCategory("Technologie");
feed.addContributor({
name: "Johan Cruyff",
email: "johancruyff@example.com",
link: "https://example.com/johancruyff",
});
console.log(feed.rss2());
// Output: RSS 2.0
console.log(feed.atom1());
// Output: Atom 1.0
console.log(feed.json1());
// Output: JSON Feed 1.0
| Property | Type | Description |
|---|---|---|
title | string | Required. Feed title |
id | string | Feed identifier (required for Atom) |
link | string | URL to the feed's website |
description | string | Feed description/subtitle |
copyright | string | Copyright notice |
language | string | Language code (e.g., "en", "fr-CA") |
updated | Date | Last update date (default: now) |
generator | string | Generator name (default: "https://github.com/jpmonette/feed") |
image | string | URL to feed image/logo |
favicon | string | URL to feed favicon |
author | Author | Feed author |
feedLinks | object | Links to feed formats ({ rss, atom, json }) |
feed | string | Self-referencing feed URL |
hub | string | WebSub/PubSubHubbub hub URL |
ttl | number | Time to live in minutes (RSS) |
docs | string | RSS specification docs URL |
stylesheet | string | URL to XSL stylesheet |
podcast | boolean | Enable iTunes/Google podcast extensions |
category | string | Podcast category name |
| Property | Type | Description |
|---|---|---|
title | string | Required. Item title |
link | string | Required. URL to the item |
date | Date | Required. Last modified/updated date |
id | string | Unique identifier (Atom/JSON) |
guid | string | RSS-specific GUID |
description | string | Brief summary or excerpt |
content | string | Full content (HTML allowed) |
author | Author[] | Item authors |
contributor | Author[] | Item contributors |
category | Category[] | Item categories |
published | Date | Original publication date |
copyright | string | Item copyright notice |
image | string | Enclosure | Image attachment |
audio | string | Enclosure | Audio attachment |
video | string | Enclosure | Video attachment |
enclosure | Enclosure | Generic media enclosure |
extensions | Extension[] | Custom extensions |
interface Author {
name?: string;
email?: string;
link?: string;
avatar?: string; // JSON Feed only
}
interface Enclosure {
url: string;
type?: string; // MIME type (e.g., "audio/mpeg")
length?: number; // File size in bytes
title?: string;
duration?: number; // Duration in seconds (for podcasts)
}
interface Category {
name?: string;
domain?: string; // RSS
scheme?: string; // Atom
term?: string; // Atom
}
interface Extension {
name: string;
objects: Record<string, unknown>;
}
< 3.0.0If you are migrating from a version older than 3.0.0, be sure to update your import as we migrated to ES6 named imports.
If your environment supports the ES6 module syntax, you can import as described above:
import { Feed } from "feed";
Otherwise, you can stick with require():
- const Feed = require('feed');
+ const Feed = require('feed').Feed;
Copyright (C) 2013, Jean-Philippe Monette contact@jpmonette.net
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.