# RSS Feed Reader: RSS, Atom & JSON Feeds to Clean Data (`larkmoor/rss-feed-reader`) Actor

Read any number of RSS, Atom and JSON feeds, or just paste website URLs and the feed is found for you. One clean row per item: title, link, date, author, summary, categories, image and podcast enclosure. Keyword and date filters, de-duplication. No start fee, pay per item.

- **URL**: https://apify.com/larkmoor/rss-feed-reader.md
- **Developed by:** [Larkmoor Data](https://apify.com/larkmoor) (community)
- **Categories:** News, Automation
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $0.51 / 1,000 feed items

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](#api) section below.

Each client library has reference documentation the quickstart does not restate: [JavaScript/TypeScript](https://docs.apify.com/api/client/js/docs.md) (`npm install apify-client`) and [Python](https://docs.apify.com/api/client/python/docs.md) (`pip install apify-client`).

# README

## RSS Feed Reader: RSS, Atom & JSON Feeds to Clean Data

Paste a list of feed URLs, or just website and blog addresses, and get one clean, consistent row per item: title, link, publish date (ISO 8601, UTC), author, a plain-text summary, categories, the lead image, and the podcast or media enclosure. RSS 0.9x/1.0/2.0, Atom and JSON Feed are all read the same way, so you never deal with three formats again.

No API key, no browser, no proxy: feeds are public, machine-readable files that publishers make for exactly this purpose.

### What you can use it for

- **News and brand monitoring**: watch 200 news sites, blogs and press rooms and keep only items that mention your keywords
- **Content aggregation**: feed a newsletter, a Slack channel, a Notion database or a website section from many sources at once
- **AI and LLM pipelines**: pull fresh articles with clean text summaries (or full content) into a RAG index or an agent
- **Podcast tracking**: list new episodes with their audio enclosure URL across many shows
- **Competitor watch**: follow the blogs, changelogs and release notes of the companies you track
- **Research and archiving**: collect dated items from academic, government and industry feeds into one table

### Why this one

- **Website URLs work too**: if you paste `https://www.theverge.com` instead of a feed address, the feed is found from the page's `<link rel="alternate">` tag or common paths (`/feed`, `/rss.xml`, `/atom.xml`, `/index.xml` and more)
- **One schema for every format**: RSS, Atom and JSON Feed items come out with the same fields
- **Clean text**: HTML tags and entities stripped from titles and summaries; summary length is yours to set
- **Images found for you**: media thumbnails, media content, image enclosures, or the first image in the item body
- **Filters that save money**: keyword filter and "last N days" filter run before anything is charged, and duplicate stories across feeds are dropped
- **No start fee beyond a tenth of a cent** and a low price per item

### Input

| Field | What it does | Default |
|---|---|---|
| `feedUrls` | Feed URLs or website/blog URLs, one per line | required |
| `maxItemsPerFeed` | Newest items to keep per feed | 50 |
| `maxAgeDays` | Only items published in the last N days | no limit |
| `keywords` | Keep items that contain any of these words | keep all |
| `includeContent` | Add the full body text as plain text | false |
| `summaryMaxChars` | Cut summaries to this length | 500 |
| `autoDiscover` | Find the feed when a URL is a web page | true |
| `dedupe` | Drop items whose link was already returned in the run | true |
| `maxResults` | Stop after this many items in total | 5,000 |
| `concurrency` | Feeds read in parallel (1–20) | 8 |
| `timeoutSeconds` | Timeout per request | 20 |
| `userAgent` | Custom User-Agent | polite feed reader |

Example input:

```json
{
  "feedUrls": ["https://hnrss.org/frontpage", "https://www.theverge.com", "https://blog.python.org"],
  "maxItemsPerFeed": 20,
  "maxAgeDays": 7,
  "keywords": ["python", "linux", "ai"]
}
```

### Output

| Field | Meaning |
|---|---|
| `feedUrl`, `input` | The feed that was read and the URL you gave |
| `feedTitle`, `feedLink`, `feedType` | Feed name, its website, and the format (rss20, atom10, json…) |
| `title`, `link`, `guid` | Item title, its URL and the feed's own id for it |
| `published`, `updated` | ISO 8601 dates in UTC |
| `author` | Author name when the feed gives one |
| `summary` | Plain-text summary, cut to `summaryMaxChars` |
| `content` | Full plain-text body (when `includeContent` is on) |
| `categories` | Tags / categories as a list |
| `imageUrl` | Lead image of the item |
| `enclosureUrl` | Attached media (podcast audio, video, file) |

Sample rows from a test run (October 2026):

```json
[
  {"feedTitle": "Hacker News: Front Page", "feedType": "rss20", "title": "Linux 7.3 Released",
   "link": "https://news.ycombinator.com/...", "published": "2026-10-19T07:23:57+00:00", "author": "cjd8",
   "summary": "Article URL: ... Points: 412 # Comments: 233", "categories": []},
  {"feedTitle": "The Verge", "feedType": "atom10", "title": "Video game ownership bill introduced in Congress",
   "published": "2026-10-18T16:27:51+00:00", "imageUrl": "https://platform.theverge.com/...jpg",
   "summary": "A new bill would require ...", "categories": ["Gaming", "Policy"]}
]
```

### How much does it cost?

Pay per result: **$0.60 per 1,000 feed items** on the Free plan, plus $0.001 per run start, with automatic discounts on paid Apify plans. Platform compute is included. Items dropped by your keyword, date or de-duplication filters are not charged, and a feed that cannot be read costs nothing.

Worked examples:

- **A daily digest of 50 blogs**, about 10 new items each with `maxAgeDays: 1`: 500 items = **$0.30 a day**
- **Brand monitoring across 300 news feeds**, keyword filter keeps 120 items: **$0.07 per run**
- **A one-off archive pull** of 100 feeds × 100 items: 10,000 items = **$6.00**

### FAQ

**Some sites have no feed. What happens?** The run logs "no RSS/Atom/JSON feed found on this page" for that URL and moves on; nothing is charged for it.

**How far back can I go?** As far as the feed itself goes. Most feeds publish the newest 10–100 items. For older history, schedule the actor daily and keep the dataset, or use an archive tool.

**Can I get only new items since my last run?** Use `maxAgeDays: 1` on a daily schedule (or 7 on a weekly one). Duplicates inside a run are removed automatically.

**Are dates normalised?** Yes: every date is converted to ISO 8601 in UTC, whatever format the feed used.

**Is it legal?** RSS, Atom and JSON feeds are published so that software can read them. This actor requests each feed once per run, with a clear User-Agent, like any feed reader. Respect each publisher's copyright when you republish their content: titles, links and short summaries are the usual fair practice.

**Can I schedule it?** Yes: save a task with your feed list and run it hourly, daily or weekly, then send new items to Slack, email, Google Sheets or a webhook.

### Integrations

Run it through the Apify API, on a schedule, or from Make, Zapier, n8n, Google Sheets, webhooks and AI agents (Apify MCP server). Export the dataset as JSON, CSV, Excel, XML or HTML.

### Changelog

- 0.1 (October 2026): first release: RSS, Atom and JSON Feed; feed auto-discovery; keyword, date and duplicate filters; images and enclosures.

# Actor input Schema

## `feedUrls` (type: `array`):

RSS, Atom or JSON Feed URLs, or plain website/blog URLs (the feed is discovered from the page or common paths like /feed). One per line.

## `maxItemsPerFeed` (type: `integer`):

Newest items first, as the feed lists them. Most feeds carry 10–100 items. Default: 50.

## `maxAgeDays` (type: `integer`):

Skip items published before this many days ago. Empty = no date filter.

## `keywords` (type: `array`):

Keep only items whose title, summary, content or categories contain at least one of these words (case-insensitive). Empty = keep all.

## `includeContent` (type: `boolean`):

Add the item's full body text (content:encoded / Atom content) as plain text. Default: false.

## `summaryMaxChars` (type: `integer`):

Summaries are cleaned of HTML and cut to this length. Default: 500.

## `autoDiscover` (type: `boolean`):

When a URL is a web page, look for its <link rel=alternate> feed and common feed paths. Default: true.

## `dedupe` (type: `boolean`):

Drop items whose link (or id) was already returned in this run, e.g. the same story in two feeds. Default: true.

## `maxResults` (type: `integer`):

Stop after this many items across all feeds. Default: 5,000.

## `concurrency` (type: `integer`):

How many feeds are read at the same time. Default: 8.

## `timeoutSeconds` (type: `integer`):

Default: 20.

## `userAgent` (type: `string`):

Optional custom User-Agent header. Empty = a polite feed-reader User-Agent.

## Actor input object example

```json
{
  "feedUrls": [
    "https://hnrss.org/frontpage",
    "https://www.theverge.com",
    "https://blog.python.org"
  ],
  "maxItemsPerFeed": 50,
  "keywords": [],
  "includeContent": false,
  "summaryMaxChars": 500,
  "autoDiscover": true,
  "dedupe": true,
  "maxResults": 5000,
  "concurrency": 8,
  "timeoutSeconds": 20
}
```

# Actor output Schema

## `results` (type: `string`):

All results as JSON items in the run's default dataset (also downloadable as CSV/Excel from the dataset).

# 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

```javascript
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 = {
    "feedUrls": [
        "https://hnrss.org/frontpage",
        "https://www.theverge.com",
        "https://blog.python.org"
    ]
};

// Run the Actor and wait for it to finish
const run = await client.actor("larkmoor/rss-feed-reader").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

```python
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 = { "feedUrls": [
        "https://hnrss.org/frontpage",
        "https://www.theverge.com",
        "https://blog.python.org",
    ] }

# Run the Actor and wait for it to finish
run = client.actor("larkmoor/rss-feed-reader").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

```bash
echo '{
  "feedUrls": [
    "https://hnrss.org/frontpage",
    "https://www.theverge.com",
    "https://blog.python.org"
  ]
}' |
apify call larkmoor/rss-feed-reader --silent --output-dataset

```

## MCP server setup

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

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/9dIgJx6qaObXhW6Zt/builds/awnnPAtEkAY0R73Fw/openapi.json
