# RSS Feed Reader & Feed Finder – RSS/Atom to JSON, Full Text (`openharvest/rss-feed-reader`) Actor

RSS feed reader for any RSS, Atom or JSON Feed: clean items with title, link, date, author, categories, summary, image and podcast enclosures. Paste a website, YouTube channel, Substack, Medium or GitHub URL and the feed finder discovers its feeds. Optional full article text. No start fee.

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

## Pricing

from $0.50 / 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 Feed Reader & Feed Finder – RSS/Atom to JSON, Full Text

RSS feed reader for any RSS, Atom or JSON Feed: clean items with title, link, date, author, categories, summary, image and podcast enclosures. Paste a website, YouTube channel, Substack, Medium or GitHub URL and the feed finder discovers its feeds. Optional full article text. No start fee.

**Price: $0.50 per 1,000 items**, $2 per 1,000 with full text. **No start fee.** Discovered feeds are listed for free.

### What you get

- **Feed formats** – RSS 2.0, RSS 0.9x, RSS 1.0 (RDF), Atom 1.0/0.3 and JSON Feed 1.x, in any encoding (UTF-8, ISO-8859-1, Windows-1251…), even slightly broken feeds
- **Finds feeds on websites** – `<link rel="alternate">` tags, "RSS" links on the page, RSS directory pages, platform patterns and common paths (`/feed`, `/rss`, `/atom.xml`, `/index.xml`, `/feed.xml`, `/feed.json`…)
- **Platform patterns** – WordPress, Substack, Medium (users, publications, tags), YouTube (`@handle`, channel, playlist), Blogger, GitHub (releases, commits, tags, user activity), Reddit, Tumblr, Ghost, Hugo, Jekyll, Mastodon
- **Clean items** – ISO dates, plain-text summary, author names (e-mail addresses removed), categories, best image (media:thumbnail, media:content, itunes:image, enclosure or first image)
- **Podcasts** – enclosure `{url, type, length}` and `durationSeconds`
- **Full text** (optional) – uses the full content when the feed already has it, otherwise downloads the article and extracts the main text with Mozilla Readability
- **Deduplication** across feeds and an **"only newer than"** filter for scheduled runs

### Use cases

- **News & content monitoring** – follow dozens of blogs, news sites and newsletters in one dataset.
- **AI agents, RAG and LLM pipelines** – fresh articles with full text for summarization, classification and embeddings.
- **Competitor and industry tracking** – company blogs, changelogs and GitHub releases on a schedule.
- **Podcast data** – episode lists with audio URLs, durations and artwork.
- **Lead research for media and PR** – find which sites have feeds and how active they are (`itemCount`, `lastItemAt`).
- **Feed aggregators and newsletters** – build daily digests to Slack, email, Google Sheets or Notion via integrations.

### How to use it

1. Click **Try for free** / **Start**.
2. Paste feed URLs into **Feed URLs** and/or websites into **Website URLs (find feeds)**.
3. Choose **What to do with discovered feeds** (`main`, `all` or `listOnly`), **Max items per feed**, an optional **Only items newer than** date and whether you want **full text**.
4. Click **Start** and download JSON, CSV or Excel, or use the API, Make, Zapier, n8n, Google Sheets or webhooks.

### Input

| Field | Type | Description |
|---|---|---|
| `feedUrls` | array | RSS/Atom/JSON feed URLs. A normal web page here is auto-discovered. |
| `websiteUrls` | array | Websites, YouTube channels, Substack/Medium/Blogger, GitHub repos, subreddits – their feeds are discovered. |
| `discoveryMode` | enum | `main` (default: read each site's main feed), `all` (read all found feeds), `listOnly` (only list feeds, free) |
| `maxItemsPerFeed` | integer | Newest items per feed. Default `20`, `0` = all |
| `onlyNewerThan` | string | `2026-10-01` or `1 day`, `7 days`, `2 weeks`… |
| `fullText` | boolean | Return full article text. Default `false` |
| `includeContentHtml` | boolean | Also return the item HTML from the feed. Default `false` |
| `dedupe` | boolean | Skip duplicate items across feeds. Default `true` |
| `proxyConfiguration` | object | Optional proxy for sites that block you |

With `{}` (empty input) the Actor reads two demo feeds (BBC World and Hacker News).

Example input:

```json
{
    "feedUrls": ["https://feeds.bbci.co.uk/news/world/rss.xml", "https://lexfridman.com/feed/podcast/"],
    "websiteUrls": ["https://techcrunch.com", "https://www.youtube.com/@LinusTechTips", "https://github.com/nodejs/node"],
    "discoveryMode": "main",
    "maxItemsPerFeed": 20,
    "onlyNewerThan": "7 days",
    "fullText": true
}
```

### Output

Each row has a `type`: `item` (feed entry), `feed` (a discovered feed, free) or `error` (free). Real sample output (texts shortened):

**Item (podcast episode)**

```json
{
    "type": "item",
    "feedUrl": "https://feeds.npr.org/510289/podcast.xml",
    "feedTitle": "Planet Money",
    "feedType": "rss",
    "siteUrl": "https://www.npr.org/podcasts/510289/planet-money",
    "guid": "422e04c9-24e3-4eca-bae9-fdd71d614953",
    "title": "Charles Ponzi's scheme (plus a new scam)",
    "link": "https://www.npr.org/2026/10/07/nx-s1-5992800/charles-ponzis-scheme-plus-a-new-scam",
    "publishedAt": "2026-10-07T07:00:00.000Z",
    "updatedAt": null,
    "author": "NPR",
    "categories": [],
    "summary": "Charles Ponzi was down on his luck. In 1919, the Italian immigrant had spent a decade and a half in the U.S. ...",
    "imageUrl": "https://media.npr.org/assets/img/2023/01/20/charles-ponzi-scheme-madoff-scam_wide-ccb0110316748d0fd134c9400fb3766cc19ca3f1.jpg?s=1280&c=66&f=jpg",
    "enclosure": {
        "url": "https://tracking.swap.fm/track/.../default.mp3?...&size=24495839",
        "type": "audio/mpeg",
        "length": 24495839
    },
    "durationSeconds": 1530,
    "commentsUrl": null,
    "fullText": "Charles Ponzi was down on his luck. In 1919, the Italian immigrant had spent a decade and a half in the U.S. ...",
    "wordCount": 292,
    "fullTextSource": "feed",
    "fullTextStatus": "ok",
    "fullTextError": null,
    "scrapedAt": "2026-10-07T21:18:25.542Z"
}
```

**Discovered feed (free)**

```json
{
    "type": "feed",
    "websiteUrl": "https://jvns.ca/",
    "feedUrl": "https://jvns.ca/atom.xml",
    "feedTitle": "Julia Evans",
    "feedType": "atom",
    "siteUrl": "https://jvns.ca/",
    "itemCount": 20,
    "lastItemAt": "2026-09-27T00:00:00.000Z",
    "discoveredVia": "link-tag",
    "platform": null,
    "isMainFeed": true
}
```

**Error (free)**

```json
{
    "type": "error",
    "websiteUrl": "https://example.com/",
    "errorCode": "NO_FEED_FOUND",
    "error": "No RSS, Atom or JSON feed found on https://example.com/ (checked <link rel=\"alternate\">, page links, platform patterns and common paths like /feed and /rss.xml)."
}
```

`errorCode` values: `INVALID_INPUT`, `NOT_FOUND`, `HTTP_ERROR`, `NOT_A_FEED`, `NO_FEED_FOUND`, `NO_ITEMS`, `DISCOVERY_FAILED`, `FEED_FAILED`.
`fullTextStatus` values: `ok`, `paywalled`, `blocked`, `no-content`, `not-html` (e.g. YouTube videos), `timeout`, `failed`, `not-requested`.

The dataset has ready-made views in Apify Console: **Overview**, **Full text**, **Podcasts & media** and **Discovered feeds & errors**.

### Pricing

Pay-per-event, **no start fee**. Platform usage is included.

| Event | Price | When it is charged |
|---|---|---|
| `item` | **$0.0005** ($0.50 / 1,000) | Each feed item saved |
| `full-text` | **$0.002** ($2 / 1,000) | Instead of `item`, when full text was returned |
| Discovered feeds, errors | **Free** | |

Each item is charged once: `full-text` only when `fullText` is on and text was actually returned, otherwise `item`.

| Job | Cost |
|---|---|
| 20 items from 2 feeds (default input) | **$0.02** |
| Find the feeds of 100 websites (`listOnly`) | **$0** |
| 50 feeds × 20 items, daily | **$0.50 / day** |
| 1,000 articles with full text | **$2.00** |

Tip: set **Max cost per run** in the run options. The Actor stops cleanly at your budget.

### Use with AI agents (MCP)

Add the Actor to the [Apify MCP server](https://mcp.apify.com) (`https://mcp.apify.com?tools=openharvest/rss-feed-reader`) or let agents find it with `search-actors` ("rss feed"). An agent can pass a plain website URL; it does not need to know the feed address.

Example `call-actor` input for "What did Simon Willison and the Cloudflare blog publish this week? Give me the full posts.":

```json
{
    "websiteUrls": ["https://simonwillison.net", "https://blog.cloudflare.com"],
    "onlyNewerThan": "7 days",
    "maxItemsPerFeed": 10,
    "fullText": true
}
```

Example for "Does this site have an RSS feed?":

```json
{ "websiteUrls": ["https://example-blog.com"], "discoveryMode": "listOnly" }
```

### FAQ

**How does feed discovery work?**
For each website the Actor checks, in order: platform patterns (YouTube, Medium, Substack, Blogger, GitHub, Reddit…), the page's `<link rel="alternate">` tags, links on the page that look like feeds (and RSS directory pages), and finally common paths such as `/feed`, `/rss`, `/atom.xml`, `/index.xml` and `/feed.xml`. Every candidate is downloaded and validated, so you only get real, working feeds.

**Which feed is the "main" feed?**
The first valid feed the site advertises that is not a comments feed. Use `discoveryMode: "all"` to read every feed (e.g. per-category feeds or a podcast feed).

**Where does the full text come from?**
If the feed already contains the full article (150+ words in `content:encoded`, Atom `content` or JSON Feed `content_html`), that text is used (`fullTextSource: "feed"`). Otherwise the article page is downloaded and the main text extracted (`fullTextSource: "page"`). Paywalled or blocked pages are not bypassed and are charged as a normal item.

**Can I get only new items every day?**
Yes. Schedule the Actor with `onlyNewerThan: "1 day"` (or `"2 hours"` for hourly runs).

**Why did a website return NO_FEED_FOUND?**
Some sites (for example many big news homepages) do not advertise a feed or block automated requests. If you know the feed URL, put it into `feedUrls` directly. Reddit and some news sites may rate-limit requests; enabling a proxy helps.

**Is the order newest first?**
Yes, when the feed has dates. `maxItemsPerFeed` always keeps the newest items.

### Is it legal to read RSS feeds?

RSS and Atom feeds are published so that others can read them automatically. This Actor reads only public feeds and pages, does not log in and does not bypass paywalls. Feed content is still copyrighted by its publishers, so check the publisher's terms before republishing full texts, and comply with laws such as GDPR when you process author names. If you are unsure, consult a lawyer.

### Related actors

- Google News Scraper – Headlines, Search & Topics with Real Article URLs and Full Text *(coming soon)*
- Hacker News Scraper – Stories, Comments, Search & Who Is Hiring *(coming soon)*
- Telegram Channel Scraper – Public Posts, Views & Media *(coming soon)*
- Podcast Scraper *(coming soon)*

### Support & feedback

Found a feed that doesn't parse or a site whose feed isn't discovered? Open an issue in the **Issues** tab with the URL.

# Actor input Schema

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

RSS, Atom or JSON Feed URLs to read. If you paste a normal web page here by mistake, the Actor finds its feed automatically. Leave empty and use <b>Website URLs</b> if you don't know the feed address.

## `websiteUrls` (type: `array`):

Websites, blogs, Substack/Medium/Blogger publications, YouTube channels (<code>youtube.com/@handle</code>), GitHub repos or subreddits. The Actor discovers their feeds via <code>\<link rel="alternate"></code>, page links, platform patterns and common paths (<code>/feed</code>, <code>/rss</code>, <code>/atom.xml</code>, <code>/index.xml</code>, <code>/feed.xml</code>). Every found feed is listed as a free <code>type: "feed"</code> row.

## `discoveryMode` (type: `string`):

<b>main</b> = read the main feed of each website (skips comment feeds). <b>all</b> = read every discovered feed. <b>listOnly</b> = only list the feeds (free), do not read items.

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

Maximum number of items (newest first) to return from each feed. 0 = everything the feed contains. You pay per item, so this also caps your cost.

## `onlyNewerThan` (type: `string`):

Optional. Skip items published before this date. Absolute date (YYYY-MM-DD) or relative period such as <code>1 day</code>, <code>7 days</code>, <code>2 weeks</code>. Useful for scheduled runs that should return only new items. Items without a date are kept.

## `fullText` (type: `boolean`):

Return the full text of every item. If the feed already contains the full article (150+ words) it is used directly; otherwise the article page is downloaded and the main text extracted with Mozilla Readability. Items with full text are charged as <code>full-text</code>; paywalled/blocked pages are marked in <code>fullTextStatus</code> and charged as a normal <code>item</code>.

## `includeContentHtml` (type: `boolean`):

Also return the item's HTML content from the feed (<code>content:encoded</code>, Atom <code>content</code> or JSON Feed <code>content_html</code>) in the <code>contentHtml</code> field.

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

Skip items whose link (ignoring tracking parameters) or GUID was already returned from another feed in this run.

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

Usually not needed. Enable Apify Proxy only if some sites block you (HTTP 403/429 errors).

## Actor input object example

```json
{
  "feedUrls": [
    "https://feeds.bbci.co.uk/news/world/rss.xml",
    "https://www.theverge.com/rss/index.xml",
    "https://lexfridman.com/feed/podcast/"
  ],
  "websiteUrls": [
    "https://techcrunch.com",
    "https://www.youtube.com/@LinusTechTips",
    "https://astralcodexten.substack.com",
    "https://github.com/nodejs/node"
  ],
  "discoveryMode": "main",
  "maxItemsPerFeed": 50,
  "onlyNewerThan": "7 days",
  "fullText": false,
  "includeContentHtml": false,
  "dedupe": true,
  "proxyConfiguration": {
    "useApifyProxy": false
  }
}
```

# Actor output Schema

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

All scraped items in the default dataset (JSON, CSV, Excel and more via the dataset export).

## `files` (type: `string`):

Records saved in the default key-value store, e.g. the run summary.

# 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://feeds.bbci.co.uk/news/world/rss.xml",
        "https://hnrss.org/frontpage"
    ],
    "websiteUrls": [
        "https://techcrunch.com"
    ],
    "maxItemsPerFeed": 10,
    "proxyConfiguration": {
        "useApifyProxy": false
    }
};

// Run the Actor and wait for it to finish
const run = await client.actor("openharvest/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://feeds.bbci.co.uk/news/world/rss.xml",
        "https://hnrss.org/frontpage",
    ],
    "websiteUrls": ["https://techcrunch.com"],
    "maxItemsPerFeed": 10,
    "proxyConfiguration": { "useApifyProxy": False },
}

# Run the Actor and wait for it to finish
run = client.actor("openharvest/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://feeds.bbci.co.uk/news/world/rss.xml",
    "https://hnrss.org/frontpage"
  ],
  "websiteUrls": [
    "https://techcrunch.com"
  ],
  "maxItemsPerFeed": 10,
  "proxyConfiguration": {
    "useApifyProxy": false
  }
}' |
apify call openharvest/rss-feed-reader --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,openharvest/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/KYQIN2toXJuiQRCKc/builds/ZZDHYOIJEMzdsbPaU/openapi.json
