# RSS & Atom Feed Reader + New Items Monitor (`thomson-digital/rss-feed-monitor`) Actor

Read any RSS, Atom or JSON Feed into clean JSON (title, link, date, author, categories, enclosures). Auto-discover feeds from a homepage. Filter by keyword or date. Monitor mode returns only new posts since the last run — schedule it for competitor blogs, podcasts, changelogs and news.

- **URL**: https://apify.com/thomson-digital/rss-feed-monitor.md
- **Developed by:** [Matt](https://apify.com/thomson-digital) (community)
- **Categories:** News, Automation, Developer tools
- **Security:** Limited permissions
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

$1.00 / 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.

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 & Atom Feed Reader + New Items Monitor

Turn any **RSS, Atom or JSON Feed** into clean, flat JSON — title, link, publication date, author, categories, summary, full content and podcast enclosures. Paste a feed URL or just a homepage: the Actor **auto-discovers** the feed from `<link rel="alternate">` and common paths like `/feed`, `/rss` and `/atom.xml`.

Enable **monitor mode** and schedule it to get **only the new posts** since the last run — competitor blogs, product changelogs, podcasts, Substack newsletters, GitHub releases and news wires.

No browser, no proxies, no login: it only reads the public feed files publishers already expose to readers and aggregators, so runs stay fast and cheap.

### What does this Actor do?

- 📡 **Reads RSS 2.0, Atom and JSON Feed** into one unified schema
- 🔎 **Auto-discovers feeds** from a blog or company homepage
- 🧾 **Rich fields**: title, link, guid, published/updated dates, author, categories/tags, plain-text summary, HTML/text content, enclosure (podcast/media) URL + type + size, image
- 🎯 **Keyword and regex filters** — keep only the posts that match your topics
- 📅 **Date filter** — only items from the last N days or after a date
- 🆕 **Monitor mode** — remembers items between runs and outputs only new ones (perfect with Apify Schedules + email/Slack/webhook)
- 🛡️ **Robust**: retries with backoff, honors `Retry-After`, per-feed error report, one broken feed never fails the whole run
- 🤖 **AI-agent friendly**: simple input, flat JSON, usable via the Apify API and MCP

### Why use an RSS / Atom feed API?

Feeds are the cleanest public API most blogs, newsrooms, podcasts and SaaS changelogs still publish. Compared to scraping HTML articles, a feed gives you structured titles, dates and permalinks in one request — ideal for monitoring, alerting, RAG ingestion and content aggregation.

### What data can it extract?

| Field | Description |
| --- | --- |
| `title`, `link`, `guid` | Item title, permalink and stable id |
| `publishedAt`, `updatedAt` | Normalized UTC timestamps when the feed provides dates |
| `author`, `categories` | Author name(s) and tags |
| `summary`, `contentText`, `contentHtml` | Excerpt and full body (optional) |
| `enclosureUrl`, `enclosureType`, `enclosureLength` | Podcast / media attachments |
| `feedTitle`, `feedUrl`, `feedFormat` | Source feed metadata (`rss` / `atom` / `json`) |
| `isNew` | Set in monitor mode when the item was not seen before |

### How to read or monitor RSS feeds

1. Open the **Input** tab and paste one or more feed URLs (or homepage URLs).
2. Optionally set keyword filters, a date window, or enable **Monitor mode**.
3. Click **Start**. Results appear in the **Dataset** tab within seconds.
4. For monitoring: run once to save the baseline, then create an Apify **Schedule** (hourly/daily) and add an email, Slack or webhook integration.

### How much does it cost?

Pay per event: you are charged for each feed item written to the dataset. Feed discovery, filtered-out items and the monitor-mode baseline run are not charged per item. Platform usage is covered by the Actor (you do not pay compute on top). Set a maximum cost per run in the run options — the Actor stops cleanly when it is reached.

Typical runs of a few feeds with tens of items finish in well under a minute on 256 MB.

### Input

Only `feedUrls` is required. Example:

```json
{
  "feedUrls": [
    "https://www.nasa.gov/feed/",
    "https://github.com/apify/apify-sdk-python/releases.atom"
  ],
  "maxItemsPerFeed": 20,
  "includeKeywords": [],
  "onlyNewItems": false,
  "includeContent": true
}
```

| Field | Description |
| --- | --- |
| `feedUrls` | Feed URLs or website URLs (auto-discovery on). |
| `maxItemsPerFeed` | Cap on items written per feed (default 50). |
| `includeKeywords` / `excludeKeywords` | Case-insensitive keyword filters on title/summary/content/tags/author. |
| `includeUrlPatterns` / `excludeUrlPatterns` | Regex filters on the item link. |
| `publishedWithinDays` / `publishedAfter` | Date window. |
| `onlyNewItems` | Monitor mode: output only items not seen before. |
| `emitAllOnFirstRun` | Also emit items on the first monitor run. |
| `discoverFromPage` | Auto-find feeds from homepages (default on). |
| `includeContent` | Include `contentText` / `contentHtml`. |
| Advanced | `maxConcurrency`, `requestTimeoutSecs`, `maxRetries`, `proxyConfiguration`. |

See the **Input** tab for the full form.

### Output

One dataset item per feed entry. Export as JSON, CSV, Excel, XML or via API. Example:

```json
{
  "feedUrl": "https://www.nasa.gov/feed/",
  "feedTitle": "Hacker News",
  "feedFormat": "rss",
  "title": "Example story title",
  "link": "https://example.com/story",
  "guid": "https://news.ycombinator.com/item?id=123",
  "publishedAt": "2026-11-05T12:34:56Z",
  "author": null,
  "summary": "Example story title",
  "categories": [],
  "extractedAt": "2026-11-05T18:00:00Z"
}
```

A per-feed report (format, items found/filtered/output, new items, errors) is saved to the key-value store record **`SUMMARY`**.

### How to monitor a feed for new posts

1. Add the feeds to `feedUrls` and enable **Monitor mode**.
2. Run once — this saves the baseline (no results, no per-item charge).
3. Create a **Schedule** (e.g. every hour or daily) in Apify Console.
4. Add an integration (email, Slack, Google Sheets, Zapier, Make, webhook) to receive the new items.

Seen item ids are stored in a private named key-value store `rss-feed-monitor-state` in your own Apify account. Delete a record there to reset the baseline for a feed.

### FAQ

**What feed formats are supported?** RSS 2.0 (including RDF/RSS 1.0 channel), Atom 1.0 and JSON Feed 1.1. Most blogs (WordPress, Ghost, Substack, Medium), podcasts, GitHub release Atom feeds and news sites work out of the box.

**Can I paste a homepage instead of a feed URL?** Yes. With discovery on, the Actor looks for `<link rel="alternate" type="application/rss+xml">` (and Atom/JSON equivalents) plus common paths like `/feed`, `/rss`, `/atom.xml`, `/feed.xml`, `/feed.json`.

**Does monitor mode re-emit edited posts?** Items are keyed by GUID / link (or title+date fallback). If the publisher keeps the same GUID and only edits the body, the item stays "seen". A brand-new GUID/link is treated as new.

**Is it legal?** Feeds are public files that publishers expose specifically for syndication. The Actor collects only what the feed already publishes. You are responsible for how you use the output and for respecting each publisher's terms and copyright (especially full content fields).

**The feed is empty or blocked — what happens?** The feed is reported in `SUMMARY` with a status such as `http-error`, `no-feed-found` or `empty`; other feeds in the same run continue. Some sites (e.g. Hacker News) return HTTP 419 to datacenter IPs — enable Apify Proxy for those hosts, or use a different feed.

### Support

Open an issue on the Actor's **Issues** tab on Apify Store. For programmatic access, see the **API** tab.

# Actor input Schema

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

One per line. Paste a direct RSS / Atom / JSON Feed URL, or a homepage / blog URL — the Actor will discover the feed from <link rel="alternate"> and common paths like /feed, /rss, /atom.xml.

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

Maximum number of items to output for each feed. Keep it small for testing. In monitor mode the Actor still reads the whole feed to detect new items, but only writes up to this many new ones.

## `includeKeywords` (type: `array`):

Optional. Keep an item only if its title, summary, content, categories or author contain at least one of these keywords (case-insensitive).

## `excludeKeywords` (type: `array`):

Optional. Drop items whose title/summary/content/categories/author contain any of these keywords.

## `includeUrlPatterns` (type: `array`):

Optional. Keep only items whose link matches at least one regular expression.

## `excludeUrlPatterns` (type: `array`):

Optional. Drop items whose link matches any of these regular expressions.

## `publishedWithinDays` (type: `integer`):

Optional. Keep only items whose published/updated date is within the last N days.

## `publishedAfter` (type: `string`):

Optional. ISO date such as 2026-01-31.

## `keepItemsWithoutDate` (type: `boolean`):

Some feeds omit dates. When a date filter is set, such items are kept by default; turn this off to drop them.

## `onlyNewItems` (type: `boolean`):

Remembers every item seen per feed (in your private named key-value store 'rss-feed-monitor-state') and outputs only items that were not present in previous runs. Schedule the Actor hourly or daily for new posts, podcast episodes or changelog entries. The first run only saves a baseline.

## `emitAllOnFirstRun` (type: `boolean`):

In monitor mode, the first run normally outputs nothing and just saves the baseline. Enable this to output all (filtered) items on that first run (marked isNew=true).

## `discoverFromPage` (type: `boolean`):

When the input looks like a website (not a feed), look for <link rel="alternate" type="application/rss+xml"> and common feed paths.

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

When enabled, output contentText and contentHtml (truncated). Disable to get a lighter dataset of titles, links and dates only.

## `maxConcurrency` (type: `integer`):

How many feeds to fetch in parallel.

## `requestTimeoutSecs` (type: `integer`):

HTTP timeout for each feed request, in seconds.

## `maxRetries` (type: `integer`):

How many times to retry a failed or rate-limited request.

## `proxyConfiguration` (type: `object`):

Optional. Most public feeds work without a proxy. Use Apify Proxy only if a feed blocks datacenter IPs.

## Actor input object example

```json
{
  "feedUrls": [
    "https://www.nasa.gov/feed/",
    "https://github.com/apify/apify-sdk-python/releases.atom"
  ],
  "maxItemsPerFeed": 20,
  "includeKeywords": [],
  "excludeKeywords": [],
  "includeUrlPatterns": [],
  "excludeUrlPatterns": [],
  "keepItemsWithoutDate": true,
  "onlyNewItems": false,
  "emitAllOnFirstRun": false,
  "discoverFromPage": true,
  "includeContent": true,
  "maxConcurrency": 5,
  "requestTimeoutSecs": 30,
  "maxRetries": 3,
  "proxyConfiguration": {
    "useApifyProxy": false
  }
}
```

# Actor output Schema

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

Dataset containing all feed items

## `summary` (type: `string`):

Key-value store record with per-feed counts and errors

# 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://www.nasa.gov/feed/",
        "https://github.com/apify/apify-sdk-python/releases.atom"
    ],
    "maxItemsPerFeed": 20
};

// Run the Actor and wait for it to finish
const run = await client.actor("thomson-digital/rss-feed-monitor").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://www.nasa.gov/feed/",
        "https://github.com/apify/apify-sdk-python/releases.atom",
    ],
    "maxItemsPerFeed": 20,
}

# Run the Actor and wait for it to finish
run = client.actor("thomson-digital/rss-feed-monitor").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://www.nasa.gov/feed/",
    "https://github.com/apify/apify-sdk-python/releases.atom"
  ],
  "maxItemsPerFeed": 20
}' |
apify call thomson-digital/rss-feed-monitor --silent --output-dataset

```

## MCP server setup

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

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/OpejLfStMPsK3eomZ/builds/6hMSSmjwiJnMqQ1cD/openapi.json
