feed vs feedparser vs rss vs rss-parser
RSS and Atom Feed Generation and Parsing in JavaScript
feedfeedparserrssrss-parserSimilar Packages:

RSS and Atom Feed Generation and Parsing in JavaScript

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.

Npm Package Weekly Downloads Trend

3 Years

Github Stars Ranking

Stat Detail

Package
Downloads
Stars
Size
Issues
Publish
License
feed01,36460.9 kB233 months agoMIT
feedparser01,97672 kB1520 days agoMIT
rss01,041-489 years agoMIT
rss-parser01,5091.87 MB803 years agoMIT

RSS and Atom Feed Tools in JavaScript: Generation vs Parsing Compared

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.

🛠️ Core Purpose: Generate vs Parse

Feed Generators: Creating Valid Feeds

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

Feed Parsers: Consuming External Feeds

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: feedparser is officially deprecated. Its npm page states: "This package is no longer maintained." Do not use it in new projects.

📡 Supported Feed Formats

PackageRSS 2.0Atom 1.0JSON FeedRDF
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.

🧪 API Design and Developer Experience

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 pubDateisoDate and linklink, 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.

🌐 Environment Support

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

🔒 Security and Maintenance

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

🧩 Real-World Usage Scenarios

Scenario 1: Building a Blog with Multiple Feed Formats

You run a Next.js blog and want to offer RSS, Atom, and JSON Feed.

  • Best choice: feed
  • Why? Single API for all three formats, automatic escaping, and TypeScript support.
// 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());
  }
}

Scenario 2: Aggregating News from Multiple Sources

You’re building a feed reader that pulls from various RSS/Atom endpoints.

  • Best choice: rss-parser
  • Why? Normalizes diverse feed structures into a consistent object model.
const 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
  }))
);

Scenario 3: Adding a Simple RSS Feed to a Static Site

You have a small Eleventy or Hugo-like site and only need basic RSS 2.0.

  • Best choice: rss
  • Why? Tiny footprint, no extra features you won’t use.
const 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());

📊 Summary Table

Featurefeedrssrss-parserfeedparser
Status✅ Active✅ Stable✅ Active❌ Deprecated
Primary RoleGeneratorGeneratorParserParser
RSS 2.0
Atom 1.0
JSON Feed
Browser Support✅ (with XML text)
Auto-EscapingN/A
TypeScript

💡 Final Recommendation

  • Need to generate feeds? → Use feed for full format support and safety, or rss for minimal RSS-only needs.
  • Need to parse feeds? → Use 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.

How to Choose: feed vs feedparser vs rss vs rss-parser

  • feed:

    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.

  • feedparser:

    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.

  • rss:

    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.

  • rss-parser:

    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.

README for feed

Feed for Node.js
npm version License: MIT

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.

Getting Started

Installation

$ yarn add feed

Example

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

Options

Feed Options

PropertyTypeDescription
titlestringRequired. Feed title
idstringFeed identifier (required for Atom)
linkstringURL to the feed's website
descriptionstringFeed description/subtitle
copyrightstringCopyright notice
languagestringLanguage code (e.g., "en", "fr-CA")
updatedDateLast update date (default: now)
generatorstringGenerator name (default: "https://github.com/jpmonette/feed")
imagestringURL to feed image/logo
faviconstringURL to feed favicon
authorAuthorFeed author
feedLinksobjectLinks to feed formats ({ rss, atom, json })
feedstringSelf-referencing feed URL
hubstringWebSub/PubSubHubbub hub URL
ttlnumberTime to live in minutes (RSS)
docsstringRSS specification docs URL
stylesheetstringURL to XSL stylesheet
podcastbooleanEnable iTunes/Google podcast extensions
categorystringPodcast category name

Item Options

PropertyTypeDescription
titlestringRequired. Item title
linkstringRequired. URL to the item
dateDateRequired. Last modified/updated date
idstringUnique identifier (Atom/JSON)
guidstringRSS-specific GUID
descriptionstringBrief summary or excerpt
contentstringFull content (HTML allowed)
authorAuthor[]Item authors
contributorAuthor[]Item contributors
categoryCategory[]Item categories
publishedDateOriginal publication date
copyrightstringItem copyright notice
imagestring | EnclosureImage attachment
audiostring | EnclosureAudio attachment
videostring | EnclosureVideo attachment
enclosureEnclosureGeneric media enclosure
extensionsExtension[]Custom extensions

Types

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>;
}

Migrating from < 3.0.0

If 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;

Star History

Star History Chart

More Information

License

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.