RSS Feed Reader & RSS to JSON Converter (Apify Actor)

Read many RSS and Atom feeds in one run. Paste feed or website URLs (feeds are autodiscovered), get title, link, date, author, summary, categories, image as clean JSON. $0.30 per 1,000 items. Runs as an Apify Actor, callable from MCP clients via the Apify MCP server (https://mcp.apify.com/?actors=pennydata/rss-atom-feed-reader-bulk).

Hosted MCP Server

npx add-mcp 'https://mcp.apify.com/?actors=pennydata/rss-atom-feed-reader-bulk'

Installs into Claude Code, Codex, Cursor and more

Documentation

RSS Feed Reader & RSS to JSON Converter - Bulk Atom Parser (pennydata/rss-atom-feed-reader-bulk) Actor

RSS feed reader and RSS to JSON converter: read many RSS and Atom feeds in one run. Paste feed or website URLs (feeds are autodiscovered), get title, link, date, author, summary, categories, image as clean JSON. $0.30 per 1,000 items.

Pricing

from $0.21 / 1,000 feed item returneds

This Actor is paid per event. You are not charged for the Apify platform usage, but only a fixed price for specific events. Since this Actor supports Apify Store discounts, the price gets lower the higher subscription plan you have.

Learn more: https://docs.apify.com/actors/running/actors-in-store.md#pay-per-event

What's an Apify Actor?

An Actor is a serverless cloud program that runs on the Apify platform. It has two run modes. In Batch mode, an Actor accepts a well-defined JSON input, performs an action which can take anything from a few seconds to a few hours, and optionally produces a well-defined JSON output, datasets with results, or files in key-value store. In Standby mode, an Actor provides a web server which can be used as a website, API, or an MCP server.

Apify vocabulary and the platform model are defined once, in the agent quickstart at https://apify.com/agents.md.

How to integrate an Actor?

If asked about integration, you help developers integrate Actors into their projects. You adapt to their stack and deliver integrations that are safe, well-documented, and production-ready.

Do not guess an integration path. Every one of them is in the agent quickstart at https://apify.com/agents.md: the Apify MCP server, Agent Skills with the Apify CLI, the JavaScript and Python clients, the REST API, and the account-free path for an agent with no human to sign in. It also carries the rule on stating cost before the first paid run.

For examples already wired to this Actor's own input schema, see the API section below.

Each client library has reference documentation the quickstart does not restate: JavaScript/TypeScript (npm install apify-client) and Python (pip install apify-client).

README

RSS Feed Reader: Bulk RSS & Atom, JSON Feed, Autodiscover

Real output (local run 2026-10-25, first 5 of 6 rows, 3 feeds, maxItemsPerFeed 2):

feedTitletitlepublishedauthorstatus
The GitHub BlogHow bug bounty sharpens one researcher’s security skills2026-10-22T17:21:30.000ZShilpa Kumariok
The GitHub BlogThe bridge to agent-scale Git infrastructure2026-10-21T16:00:00.000ZEleanor Whiteok
Hacker News: Front PageGoogle has officially turned these Nest thermostats back into dumb thermostats2026-10-24T23:14:30.000Zgnabgibok
Hacker News: Front PageAmerica Has Lost 200k of Jobs in Media, Film and the Arts. How Much Is AI?2026-10-24T23:11:54.000Zgnabgibok
BBC NewsPalestinian families displaced as Israeli forces demolish Hebron homes2026-10-24T23:02:06.000Znullok

Copy-paste input for this run:

{"urls":["https://github.blog/feed/","https://hnrss.org/frontpage","https://feeds.bbci.co.uk/news/world/rss.xml"],"maxItemsPerFeed":2}

RSS feed reader API for many feeds at once. Paste RSS 2.0, Atom or JSON Feed URLs, or just a website URL and the feed is autodiscovered, then get one normalized item per post: title, link, ISO date, author, summary, categories, image and enclosure. No login, no browser, no proxies. Pay $0.0003 per item ($0.30 per 1,000); failed or empty feeds cost nothing.

Use it for news monitoring, blog and podcast aggregation, content curation, competitor tracking, newsletter research and feeding feeds into Zapier, Make, n8n or your own pipeline via the Apify API.

Why this feed reader

  • Bulk: hundreds of feeds in one run, one shared output schema for RSS, Atom and JSON Feed.
  • Autodiscovery: give https://example.com and it reads <link rel="alternate"> feed links, then tries common paths (/feed, /rss.xml, /atom.xml, /feed.json).
  • Resilient: a dead, blocked or non-feed URL is logged, skipped, listed in the FAILED_FEEDS key-value record and not charged. The run still succeeds with the feeds that worked.
  • Per-row status + SUMMARY: every dataset row has status (ok feed item, error feed unreadable with reason, skipped feed read but no items matched). Only ok rows are charged. A SUMMARY record in the key-value store holds the counts per status and datasetRows.
  • Since-date filter: only items published on or after a date.
  • Normalized dates: always ISO 8601 (or null), whatever the feed uses (RFC 822, dc:date, Atom updated).

Input

  • urls: feed URLs or website URLs (aliases feedUrls, feeds, url also work).
  • sinceDate: optional ISO date or date-time; older items are skipped and not charged. Items with no date are kept.
  • publishedAfter, filterByDate: aliases of sinceDate.
  • onlyNew: monitoring mode. Returns only entries not seen in an earlier run (seen guid/link per feed URL is kept in a named key-value store). Only new entries are charged. The first run sets the baseline.
  • stateStoreName: name of that store (default rss-seen-state); use one name per monitor.
  • webhookUrl: optional. POSTs the items returned by the run to this URL: Slack and Discord incoming-webhook URLs get a readable message, any other URL gets JSON {count, items}. Off by default. A failed POST is logged and never fails the run.
  • since: alias of sinceDate.
  • fetchTimeoutSeconds: HTTP timeout per feed request (5 to 120, default 25).
  • keywords: optional list; keep only items whose title or summary contains any keyword (case-insensitive). Others are not charged.
  • includeContent: add a content field with the full item body when the feed has one.
  • dedupe: skip items whose guid/link already appeared in an earlier feed of the same run.
  • maxItemsPerFeed: newest items per feed (default 20, max 1000). Also caps your cost per feed.

Switching from another RSS actor

Paste your saved input as it is and change only the actor ID. These input names work unchanged:

Rival actorTheir inputHere
automation-lab/rss-feed-readerfeeds, maxItemsPerFeed, publishedAftersame names accepted
santamaria-automations/rss-feed-readerfeedUrls, maxItemsPerFeed, includeContent, filterByDate, fetchTimeoutSecondssame names accepted

Options this actor does not know are ignored with a warning in the log; the run does not fail. Output field names differ from other actors (see Output above), so check downstream mappings once. Names are from the rivals' public input schemas on 2026-10-22; this is not affiliated with them.

Output (one item per post)

feedUrl, sourceUrl, feedTitle, feedFormat (rss / atom / jsonfeed), guid, title, link, published, updated, author, summary (HTML stripped, max 2,000 chars), contentHtml (as given in the feed), categories, imageUrl, authors (all authors), enclosureUrl, enclosureType, enclosures (every enclosure or JSON Feed 1.1 attachment: url, type, length, durationSeconds), durationSeconds (podcast episodes), content (only with includeContent), status.

Example input

{
  "urls": ["https://hnrss.org/frontpage", "https://github.blog"],
  "sinceDate": "2026-10-01",
  "maxItemsPerFeed": 20
}

The default input runs as-is, so you can click Start without editing anything.

Example output

Values are illustrative of the shape, not a real post.

{
  "feedUrl": "https://example.com/feed.xml",
  "sourceUrl": "https://example.com",
  "feedTitle": "Example Blog",
  "feedFormat": "rss",
  "guid": "https://example.com/post-1",
  "title": "Post title",
  "link": "https://example.com/post-1",
  "published": "2026-10-05T10:00:00.000Z",
  "updated": null,
  "author": "Jane Doe",
  "summary": "Plain-text summary of the post.",
  "categories": ["news"],
  "imageUrl": null,
  "enclosureUrl": null
}

Feed finder mode (discover every RSS feed on a website)

Set "mode": "discover" and paste website URLs. For each site the actor returns every RSS, Atom or JSON feed it advertises (HTML <link rel="alternate"> tags, then common paths like /feed and /rss.xml), each one validated by parsing it. One row per feed: feedUrl, feedTitle, feedFormat, itemCount, latestItemDate, sampleTitles. Sites with no feed give an unbilled skipped row. Billed with the same per-result event as feed items ($0.30 per 1,000 rows).

{ "mode": "discover", "urls": ["https://github.blog", "https://www.bbc.com/news"] }

Monitor feeds: only new items, charged only for new items

Set "onlyNew": true and put the task on a schedule. Each run returns just the entries that were not in any earlier run, so you pay only for new posts and never see the same one twice. Combine with keywords to alert on a topic and since to ignore old posts on the first run.

Recipe (daily):

  1. Open the actor, paste the input below (or your own feeds), click Save as a new task.
  2. Schedules, then Create new schedule, cron 0 7 * * *, add the task.
  3. On the task add a Slack, email or webhook integration with trigger Run succeeded and Include dataset items. Days with no new posts return an empty dataset and cost nothing.

Copy-paste example: 34 government and agency press-release feeds (SEC, FDA, EU Commission, and more; each answered HTTP 200 with items when checked on 2026-10-25):

{
  "urls": [
    "https://www.sec.gov/news/pressreleases.rss",
    "https://www.fda.gov/about-fda/contact-fda/stay-informed/rss-feeds/press-releases/rss.xml",
    "https://www.fda.gov/about-fda/contact-fda/stay-informed/rss-feeds/recalls/rss.xml",
    "https://ec.europa.eu/commission/presscorner/api/rss?language=en",
    "https://www.gov.uk/search/news-and-communications.atom",
    "https://www.gov.uk/government/organisations/hm-treasury.atom",
    "https://www.gov.uk/government/organisations/home-office.atom",
    "https://www.gov.uk/government/organisations/financial-conduct-authority.atom",
    "https://www.gov.uk/government/organisations/department-of-health-and-social-care.atom",
    "https://www.gov.uk/government/organisations/competition-and-markets-authority.atom",
    "https://www.gov.uk/government/organisations/foreign-commonwealth-development-office.atom",
    "https://www.gov.uk/government/organisations/ministry-of-defence.atom",
    "https://www.gov.uk/government/organisations/department-for-education.atom",
    "https://www.gov.uk/government/organisations/department-for-energy-security-and-net-zero.atom",
    "https://www.gov.uk/government/organisations/department-for-science-innovation-and-technology.atom",
    "https://www.gov.uk/government/organisations/cabinet-office.atom",
    "https://www.justice.gov/news/rss?m=1",
    "https://www.federalreserve.gov/feeds/press_all.xml",
    "https://www.federalreserve.gov/feeds/press_monetary.xml",
    "https://www.federalreserve.gov/feeds/press_enforcement.xml",
    "https://www.consumerfinance.gov/about-us/newsroom/feed/",
    "https://tools.cdc.gov/api/v2/resources/media/132608.rss",
    "https://www.nasa.gov/news-release/feed/",
    "https://www.energy.gov/rss/articles.xml",
    "https://www.ecb.europa.eu/rss/press.html",
    "https://www.bankofengland.co.uk/rss/news",
    "https://www.who.int/rss-feeds/news-english.xml",
    "https://api.io.canada.ca/io-server/gc/news/en/v2?sort=publishedDate&orderBy=desc&pick=50&format=atom",
    "https://www.pm.gov.au/rss.xml",
    "https://www.cpsc.gov/Newsroom/CPSC-RSS-Feed/Recalls-RSS",
    "https://www.cftc.gov/RSS/RSSGP/rssgp.xml",
    "https://www.gov.uk/government/organisations/department-for-transport.atom",
    "https://www.gov.uk/government/organisations/department-for-business-and-trade.atom",
    "https://www.gov.uk/government/organisations/ofcom.atom"
  ],
  "onlyNew": true,
  "stateStoreName": "gov-press-monitor",
  "maxItemsPerFeed": 50
}

Notes: the first run returns up to maxItemsPerFeed current items and marks everything currently in the feed as seen (the baseline); the store keeps the last 5,000 IDs per feed. Use a different stateStoreName for each monitor. Feeds that fail or have nothing new add an unbilled row.

Get new RSS items in Slack every hour

  1. Create an incoming webhook in Slack (Apps, Incoming Webhooks) or Discord (channel settings, Integrations, Webhooks) and copy its URL.
  2. Click Save as a new task with the input below. Run it once: the first run sets the baseline.
  3. Under Schedules, create a schedule with cron 0 * * * * and add the task. Each run posts only the new items to your channel; runs with nothing new post nothing and are not charged.
{
  "urls": ["https://hnrss.org/frontpage", "https://github.blog/feed/"],
  "keywords": ["apify", "scraping"],
  "onlyNew": true,
  "stateStoreName": "my-slack-alerts",
  "webhookUrl": "https://hooks.slack.com/services/T000/B000/XXXX",
  "webhookFormat": "auto"
}

webhookFormat is auto (Slack and Discord detected by URL), slack, discord or generic (JSON {count, items}, for Zapier, Make, n8n or your own endpoint). Items are sent in messages of at most 10. A 429 or 5xx reply is retried once; a webhook error never fails the run (the result is in the SUMMARY record under webhook, and items stay in the dataset). The URL is stored as a secret input and never logged.

Daily alerts (run it on a schedule)

Get new posts from your feeds in Slack or email every morning, with no code:

  1. Open the actor and set your input (see the JSON below). Click Save as a new task and name it, for example daily-feeds.
  2. Go to Schedules in the Apify Console, then Create new schedule. Set the cron to 0 7 * * * (every day at 07:00; pick your time zone). Under Actors/Tasks, add the daily-feeds task and save.
  3. Open the task, then Integrations, then Add integration. Choose Slack (or Email) with trigger Run succeeded, and select the channel or address. Enable Include dataset items if you want the posts in the message. (Integrations are in the Apify Console; availability can depend on your plan.)

Input for a daily digest (small maxItemsPerFeed keeps each run cheap):

{
  "urls": ["https://hnrss.org/frontpage", "https://github.blog", "https://www.theverge.com/rss/index.xml"],
  "keywords": ["apify", "scraping"],
  "maxItemsPerFeed": 10
}

Cost per run is at most feeds × maxItemsPerFeed × $0.0003; with the input above that is under $0.01. Note: each run re-reads the latest items, so a post still in the feed can appear again the next day. Set sinceDate to yesterday's date in the task to only get recent posts, and update it when you like. Failed feeds are not billed.

FAQ

Does it support OPML? Not yet; paste the feed URLs. Does it fetch full articles? No. It reads only the feed document itself (plus the page at the URL you give, for autodiscovery). contentHtml is whatever the feed publisher includes. Which feed versions? RSS 0.9x/1.0 (RDF)/2.0, Atom 1.0, JSON Feed 1.x. Am I charged for feeds that fail? No, only items added to the dataset are billed. Is this affiliated with any publisher? No. Feeds are published by sites for syndication; their own terms apply to how you reuse the content.

Pricing (pay per event)

Event feed-item: one item pushed to the dataset, $0.0003 ($0.30 per 1,000). No start fee.

Honest limits

  • Feeds usually expose only the latest 10 to 100 items; this actor cannot return older posts.
  • Autodiscovery needs the site to publish a feed link or use a common feed path; sites that block automated requests are skipped.
  • Summaries are plain text; formatting is in contentHtml when the feed provides it.
  • Item text and author names are public data supplied by the publisher; handle them according to the privacy law that applies to you.

Feedback

If this Actor worked for you or didn't, please leave an honest rating on its Store page or open an issue from the Issues tab. We read both and fix reported problems.

More from PennyData

AI disclosure

This actor was written with the assistance of an AI model (Claude, by Anthropic) and tested locally on live feeds.


Other languages

Español: Lector de feeds RSS y Atom a JSON

Lee muchos feeds RSS o Atom a la vez y los convierte a JSON: título, enlace, fecha, autor y contenido de cada entrada. Admite filtros por fecha y palabras clave; sin clave de API. Precio: 0,0003 USD por entrada devuelta (0,30 USD por 1.000); los feeds vacíos o con error no se cobran.

Ejemplo de entrada:

{"urls":["https://hnrss.org/frontpage","https://github.blog/feed/"],"maxItemsPerFeed":20}

Português: Leitor de feeds RSS e Atom para JSON

Leia vários feeds RSS ou Atom de uma vez e converta para JSON: título, link, data, autor e conteúdo de cada item. Aceita filtros por data e palavras-chave; sem chave de API. Preço: US$ 0,0003 por item retornado (US$ 0,30 por 1.000); feeds vazios ou com erro não são cobrados.

Exemplo de entrada:

{"urls":["https://hnrss.org/frontpage","https://github.blog/feed/"],"maxItemsPerFeed":20}

Deutsch: RSS- und Atom-Feeds in JSON umwandeln

Liest viele RSS- oder Atom-Feeds auf einmal und wandelt sie in JSON um: Titel, Link, Datum, Autor und Inhalt jedes Eintrags. Mit Filtern für Datum und Stichwörter; kein API-Schlüssel nötig. Preis: 0,0003 USD pro zurückgegebenem Eintrag (0,30 USD pro 1.000); leere oder fehlerhafte Feeds kosten nichts.

Beispieleingabe:

{"urls":["https://hnrss.org/frontpage","https://github.blog/feed/"],"maxItemsPerFeed":20}

I built this and earn from its runs. Written with AI assistance (Claude).

Actor input Schema

urls (type: array):

RSS 2.0, Atom or JSON Feed URLs. If a URL is an ordinary web page, the actor looks for a feed in its HTML (and common paths such as /feed, /rss.xml, /atom.xml) and reads that.

sinceDate (type: string):

Optional. ISO date or date-time (e.g. 2026-10-01 or 2026-10-01T12:00:00Z). Items published before it are skipped and not charged. Items without a date are kept.

since (type: string):

Alias of sinceDate. ISO date or date-time.

maxItemsPerFeed (type: integer):

Newest items to return per feed. Also caps what you are charged per feed.

mode (type: string):

read (default): return feed items. discover: find every RSS, Atom or JSON feed a website advertises, validate each and return one row per feed (title, format, item count, latest item date). Same per-result price, empty sites cost nothing.

feedUrls (type: array):

Alias of "urls"; both lists are merged and de-duplicated.

keywords (type: array):

Optional. Keep only items whose title or summary contains any of these words (case-insensitive). Filtered-out items are not charged.

includeContent (type: boolean):

Add a content field with the full item body (content:encoded / Atom content) when the feed provides it.

dedupe (type: boolean):

Skip items whose guid/link already appeared in an earlier feed of this run.

publishedAfter (type: string):

Alias of sinceDate.

filterByDate (type: string):

Alias of sinceDate.

fetchTimeoutSeconds (type: integer):

HTTP timeout per feed request, 5 to 120.

onlyNew (type: boolean):

Return only entries not seen in a previous run. Seen entry IDs (guid or link) are remembered per feed URL in a named key-value store, so a daily schedule yields just the new entries, and you are charged only for those. The first run returns the current items (up to Max items per feed) and sets the baseline.

stateStoreName (type: string):

Named key-value store holding the seen-entry IDs for onlyNew. Use different names for different monitors.

webhookUrl (type: string):

Optional. After the run, POST the emitted items to this URL in batches of up to 10 items per message. Slack and Discord incoming-webhook URLs get a readable message; any other URL gets JSON {count, items}. Combine with Only new items on a schedule for an alert bot. Failed or rate-limited posts are retried once and never fail the run. Leave empty for no webhook.

webhookFormat (type: string):

auto (default) detects Slack and Discord by host; or force slack, discord or generic JSON.

Actor input object example

{
  "urls": [
    "https://hnrss.org/frontpage",
    "https://feeds.bbci.co.uk/news/world/rss.xml",
    "https://rss.nytimes.com/services/xml/rss/nyt/Technology.xml",
    "https://feeds.arstechnica.com/arstechnica/index",
    "https://github.blog/feed/"
  ],
  "maxItemsPerFeed": 3,
  "mode": "read",
  "includeContent": false,
  "dedupe": false,
  "fetchTimeoutSeconds": 25,
  "onlyNew": false,
  "stateStoreName": "rss-seen-state",
  "webhookFormat": "auto"
}

Actor output Schema

items (type: string):

No description

summary (type: string):

No description

API

You can run this Actor programmatically using our API. Below are code examples in JavaScript, Python, and CLI, as well as the OpenAPI specification and MCP server setup.

JavaScript example

import { ApifyClient } from 'apify-client';

// Initialize the ApifyClient with your Apify API token
// Replace the '<YOUR_API_TOKEN>' with your token
const client = new ApifyClient({
    token: '<YOUR_API_TOKEN>',
});

// Prepare Actor input
const input = {
    "urls": [
        "https://hnrss.org/frontpage",
        "https://feeds.bbci.co.uk/news/world/rss.xml",
        "https://rss.nytimes.com/services/xml/rss/nyt/Technology.xml",
        "https://feeds.arstechnica.com/arstechnica/index",
        "https://github.blog/feed/"
    ],
    "maxItemsPerFeed": 3
};

// Run the Actor and wait for it to finish
const run = await client.actor("pennydata/rss-atom-feed-reader-bulk").call(input);

// Fetch and print Actor results from the run's dataset (if any)
console.log('Results from dataset');
console.log(`💾 Check your data here: https://console.apify.com/storage/datasets/${run.defaultDatasetId}`);
const { items } = await client.dataset(run.defaultDatasetId).listItems();
items.forEach((item) => {
    console.dir(item);
});

// 📚 Want to learn more 📖? Go to → https://docs.apify.com/api/client/js/docs

Python example

from apify_client import ApifyClient

# Initialize the ApifyClient with your Apify API token
# Replace '<YOUR_API_TOKEN>' with your token.
client = ApifyClient("<YOUR_API_TOKEN>")

# Prepare the Actor input
run_input = {
    "urls": [
        "https://hnrss.org/frontpage",
        "https://feeds.bbci.co.uk/news/world/rss.xml",
        "https://rss.nytimes.com/services/xml/rss/nyt/Technology.xml",
        "https://feeds.arstechnica.com/arstechnica/index",
        "https://github.blog/feed/",
    ],
    "maxItemsPerFeed": 3,
}

# Run the Actor and wait for it to finish
run = client.actor("pennydata/rss-atom-feed-reader-bulk").call(run_input=run_input)

# Fetch and print Actor results from the run's dataset (if there are any)
print(f"💾 Check your data here: https://console.apify.com/storage/datasets/{run.default_dataset_id}")
for item in client.dataset(run.default_dataset_id).iterate_items():
    print(item)

# 📚 Want to learn more 📖? Go to → https://docs.apify.com/api/client/python/docs/quick-start

CLI example

echo '{
  "urls": [
    "https://hnrss.org/frontpage",
    "https://feeds.bbci.co.uk/news/world/rss.xml",
    "https://rss.nytimes.com/services/xml/rss/nyt/Technology.xml",
    "https://feeds.arstechnica.com/arstechnica/index",
    "https://github.blog/feed/"
  ],
  "maxItemsPerFeed": 3
}' |
apify call pennydata/rss-atom-feed-reader-bulk --silent --output-dataset

MCP server setup

{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,pennydata/rss-atom-feed-reader-bulk"
        }
    }
}

The hosted server signs you in with OAuth on first connect, so no API token belongs in this config. Clients without OAuth support can send an Authorization: Bearer <APIFY_API_TOKEN> header instead, using a token from API & Integrations in Apify Console (https://console.apify.com/settings/integrations).

OpenAPI specification

Download the OpenAPI definition: https://api.apify.com/v2/actors/yLJbMaSCPkfJxi85x/builds/slnI3aWlV7SzoGkDQ/openapi.json