# RSS Feed Reader: RSS, Atom & JSON Feed to JSON (`ataism/rss-feed-reader`) Actor

Read RSS, Atom, RDF and JSON Feed into clean JSON rows. Finds the feed from a site URL, only-new mode for schedules, emails removed. $0.50 per 1,000 items.

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

## Pricing

$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: RSS, Atom & JSON Feed to JSON

Turn **any RSS, Atom or JSON Feed into clean JSON rows**: one dataset row per item with title, link, id, published and updated dates, author name, a plain-text summary, categories, enclosures (podcast audio, images) and language. Give a feed URL, or just a site URL: the Actor finds the feed the page announces. No browser, no proxy, no key.

**Price: $0.50 per 1,000 items ($0.0005 per item row)**, plus Apify's default Actor-start event. Feeds, pages, feed discovery and error rows are free.

- **Every common format:** RSS 2.0 (and 0.9x), RSS 1.0 (RDF), Atom 1.0 (and 0.3) and JSON Feed 1.0/1.1, gzip and deflate, any character set the feed declares.
- **Finds the feed for you:** give `https://crawlee.dev/blog` and the Actor reads the `<link rel="alternate">` feed its page announces.
- **Only new items for schedules:** with **Only new items** on, each run returns only items it has not returned before (remembered per feed in a named store in your account), and asks the server "changed since last time?" so unchanged feeds cost almost nothing.
- **Clean text:** HTML is turned into plain text, summaries are capped at 1,000 characters, optional full text up to 20,000. **Email addresses are removed** from every text field, and the author's email is never output: only the published byline (name) is kept.
- **Quick start:** press *Start*. The prefilled input reads the 10 newest posts of the Apify blog feed (`https://blog.apify.com/rss/`): about 2 seconds and $0.005.

> **Polite by design.** robots.txt is obeyed for every page and feed request, `Crawl-delay` is honoured in full, at most one request per second per host, an honest User-Agent, and blocks (401, 403, 429, challenge pages) are reported as free rows, never worked around.

### What it does

1. For each URL you enter, the Actor checks robots.txt, then downloads the document (at most 15 MB, or 10 MB when the run has less than 512 MB of memory).
2. **A feed** (RSS, RDF, Atom or JSON Feed, recognised by its content, not its URL) is parsed. **An HTML page** is searched for feed links in its `<head>` (`<link rel="alternate" type="application/rss+xml">`, Atom, RDF or JSON Feed); the first one is read. A page without such a link gives a free `no-feed` row.
3. Items are sorted newest first (when every item has a date; otherwise the feed's own order), filtered by **Published on or after** and **Only new items**, and the newest **Max items per feed** become rows. The run stops at **Max items in total** or your max charge.

Social-media, video and Google feeds are **never contacted**: YouTube (including `youtube.com/feeds`), Reddit (including `.rss` URLs), X/Twitter, Facebook, Instagram, Threads, TikTok, LinkedIn, Vimeo, SoundCloud, Spotify (including its `anchor.fm` podcast host), Twitch, Dailymotion, Google domains (including FeedBurner and Blogger/Blogspot), and the front-ends that republish platform content as RSS (Nitter, RSSHub). Such URLs, and redirects to them, give a free row with `errorCode: "platform"`.

### Input

| Field | What it does |
|---|---|
| **Feed or site URLs** (`feeds`) | Up to 100. A feed URL is read directly; a site or page URL is opened once and the first feed its head announces is read. `feed://` URLs and bare hosts (`blog.apify.com/rss/`) are accepted. |
| **Max items per feed** (`maxItemsPerFeed`) | The newest items taken from each feed. Default 100, maximum 1,000 (at most the first 1,000 items of a feed are read). |
| **Max items in total** (`maxItems`) | Item rows for the whole run. Default 2,000, hard cap 50,000. The run stops cleanly when it is reached (`stoppedBy: "max-items"`). |
| **Published on or after** (`onlyNewSince`) | Optional date, `YYYY-MM-DD` or a full date-time with zone. Keeps items whose published date (or updated date, if there is no published date) is on or after it. **Items without any date are dropped while this is set.** |
| **Only new items** (`onlyNew`) | Default off. On: return only items this memory has not returned before. See [Only new items](#only-new-items). |
| **Only-new memory name** (`stateName`) | A plain label (for example `news-digest`) that keeps the memories of different tasks apart. Empty = `default`. |
| **Include full text** (`includeContent`) | Default off. On: adds `contentText`, the item's full content as plain text (up to 20,000 characters, emails and phone numbers removed). Below 512 MB of memory, at most 200 items per feed are taken with full text (a log line says so). |

#### Example inputs

**1. A few feeds, newest 20 items each:**

```json
{
  "feeds": ["https://blog.apify.com/rss/", "https://crawlee.dev/blog/atom.xml", "https://www.jsonfeed.org/feed.json"],
  "maxItemsPerFeed": 20
}
```

**2. Find the feed from a site URL, only posts since a date, with full text:**

```json
{
  "feeds": ["https://crawlee.dev/blog"],
  "onlyNewSince": "2026-09-01",
  "includeContent": true
}
```

**3. A daily schedule that returns only new items (save it as a task and schedule it):**

```json
{
  "feeds": ["https://blog.apify.com/rss/", "https://www.ietf.org/blog/feed/"],
  "onlyNew": true,
  "stateName": "daily-digest",
  "maxItemsPerFeed": 50
}
```

### Output

One row per item:

```json
{
  "feedUrl": "https://blog.apify.com/rss/",
  "feedTitle": "Apify Blog",
  "feedFormat": "rss",
  "inputUrl": "https://blog.apify.com/rss/",
  "title": "AI data collection: how to feed your LLM",
  "link": "https://blog.apify.com/ai-data-collection/",
  "id": "67adb95fd310cc0001157bad",
  "published": "2026-10-26T09:00:00.000Z",
  "updated": null,
  "author": "Egop Gogo-Job",
  "summary": "Collect web data for an LLM, check that key details survive extraction, and keep the data fresh with scheduled crawls.",
  "categories": ["AI", "Tutorial", "Data processing and analysis"],
  "enclosures": [{ "url": "https://storage.ghost.io/c/f2/6e/f26ec999-9a90-4aee-a0d4-9b3ca2bb668f/content/images/2026/10/ai-data-collection-feed-your-llm.webp", "type": null, "length": null }],
  "language": null,
  "status": "ok"
}
```

- `feedUrl` is the feed the item comes from (after redirects; for a site URL, the feed its page announces). `inputUrl` is what you entered. `feedFormat` is `rss`, `rdf`, `atom` or `json`.
- `id` is the item's own identifier (RSS `guid`, Atom `id`, JSON Feed `id`, RSS 1.0 `rdf:about`), or the link when there is none. `published` and `updated` are ISO 8601 UTC (`null` when absent or unreadable).
- `summary` is the description or summary as plain text (else the start of the content), at most 1,000 characters. `contentText` (only with **Include full text**) is the full content, at most 20,000. `title` is at most 500.
- `enclosures` lists attached files (RSS `enclosure`, Atom `rel="enclosure"` links, `media:content`, JSON Feed attachments) with `url`, `type` (MIME type or `null`) and `length` (bytes or `null`). The files are not downloaded.
- `categories` are de-duplicated (at most 30). `language` is the item's or the feed's language tag.

Problems are **free rows** with `status: "error"`:

```json
{
  "feedUrl": "https://www.example.org/news/",
  "inputUrl": "https://www.example.org/news/",
  "status": "error",
  "errorCode": "no-feed",
  "message": "The page is HTML and announces no feed (no <link rel=\"alternate\"> of type RSS, Atom or JSON Feed in its head). Give the feed URL itself.",
  "httpStatus": null
}
```

#### Error codes

| `errorCode` | Meaning |
|---|---|
| `platform` | A social-media, video or Google host, or a feed host they run (also when reached by a redirect). Never contacted. |
| `invalid-url`, `ssrf` | Not an http(s) URL, or a private, loopback or internal address. |
| `dns`, `network`, `timeout`, `redirects` | Host not found, connection failed, no data for 30 s or a document took over 60 s, more than 5 redirects. |
| `http` | Any other non-2xx answer (`httpStatus` says which, for example 404). |
| `refused` | 401, 403, 429, 503, 999 or a bot challenge. Not retried, not worked around. After 2 refusals the host's other feeds are skipped (`host-skipped`). |
| `robots-blocked` | robots.txt disallows the page or feed for this Actor. Not requested. |
| `robots-unavailable` | robots.txt answered 5xx or 429, or could not be reached, twice. Nothing of that site is fetched without its rules (RFC 9309). A 4xx robots.txt means "no rules". |
| `slow-host` | robots.txt asks for a `Crawl-delay` over 30 s, or honouring the delays would take more than 5 minutes of waiting in this run. Skipped; **the delay is never shortened**. |
| `no-feed` | An HTML page that announces no feed. |
| `not-feed` | Not a feed: another XML document, a JSON file without a JSON Feed `version`, an empty file, or a page whose announced feed is itself HTML. |
| `malformed-xml`, `malformed-json` | The feed is broken or ends early. Items read completely before the problem are kept (and charged); the message says how many. |
| `gzip-error`, `too-large` | A damaged `.gz` file; a document over the size limit (15 MB, or 10 MB below 512 MB of memory), also after decompression (gzip bombs stop here). |
| `parse-timeout`, `too-complex` | The document took over 20 s or more than 96 MB of memory to parse (a hostile or extreme file). |
| `row-too-large` | One item too large to store (not expected: every field is capped). Skipped, free. |
| `internal` | An unexpected error in this Actor, not a problem with the feed. |

#### RUN_SUMMARY (key-value store record)

Item rows and charged events, error rows, inputs, pages read, feeds discovered from pages, feeds read by format, feeds not modified (only-new), items read, duplicates in a feed, items already seen, items filtered by date or over the per-feed limit, bytes downloaded (and the part that led to no item row), seconds spent waiting for `Crawl-delay`, errors by code, and `stoppedBy`: `finished`, `max-items`, `max-charge`, `unpaid-work-cap`, `time-limit`, `migrating`, `aborted` or `error`.

### Only new items

For scheduled runs (a saved task with a schedule, or n8n/Make), turn on **Only new items** and give the task its own **Only-new memory name**:

- The memory is a named key-value store in **your** Apify account, `rss-feed-reader-state`, with one record per memory name and feed. It holds only 24-character hashes of item ids or links and the feed's `ETag`/`Last-Modified` values: no item text. An item stays remembered while the feed still lists it, and for 120 days after it leaves the feed (at most 3,000 per feed). You can delete the store at any time; the next run then starts from scratch.
- **Remembered:** items delivered and charged, and items your own filters skipped (older than **Published on or after**, or beyond **Max items per feed**), so the first run sets a baseline. **Not remembered:** items not delivered because the run hit your max charge or **Max items in total**; they come in the next run.
- When a feed was handled completely, the next run sends `If-None-Match`/`If-Modified-Since`. A `304 Not Modified` answer is free and nothing is downloaded (`feedsNotModified` in RUN_SUMMARY).
- A run with no new items charges no item events. Apify's Actor-start event still applies to every run.

### Pricing

Pay per event: **$0.0005 per item row** (event `feed-item`), plus Apify's standard Actor-start event. No other fee from this Actor.

| Item rows | Cost |
|---|---|
| 10 (prefilled example) | $0.005 |
| 1,000 | $0.50 |
| 2,000 (default Max items in total) | $1.00 |
| 10,000 | $5.00 |
| 50,000 (hard cap) | $25.00 |

**Free:** feeds and pages downloaded, feed discovery, robots.txt, error rows, items filtered by date, already seen, beyond your limits, and feeds that did not change. Set **Max items in total**, or **Max total charge** in the run options, to cap spending: the run checks the budget before each request and each write, and never writes a row it cannot charge. Apify subscription discounts apply on top.

To keep free work bounded, a run stops (`stoppedBy: "unpaid-work-cap"`) after 25 failed feeds or pages, or 100 MB downloaded for documents that gave no item row. Everything found up to then is saved. With **Only new items**, feeds without new items count toward the 100 MB too when their server does not answer `304`: a schedule of many large podcast feeds can stop there before its last feeds, so split such lists over several tasks.

### Use it via API, n8n or Make

Get an API token in Apify Console under *Settings*, *API & Integrations*, and keep it in an environment variable (`APIFY_TOKEN` below). Never paste it into shared code.

**cURL** (starts a run, waits and returns the rows; the synchronous endpoint waits up to 5 minutes, so use it for small runs and the clients below for big ones):

```bash
curl -X POST "https://api.apify.com/v2/acts/ataism~rss-feed-reader/run-sync-get-dataset-items?token=$APIFY_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"feeds": ["https://blog.apify.com/rss/"], "maxItemsPerFeed": 20}'
```

**Python** (`pip install "apify-client>=3"`):

```python
import os
from apify_client import ApifyClient

client = ApifyClient(os.environ["APIFY_TOKEN"])
run = client.actor("ataism/rss-feed-reader").call(run_input={
    "feeds": ["https://blog.apify.com/rss/", "https://crawlee.dev/blog"],
    "onlyNew": True,
    "stateName": "python-digest",
})
for row in client.dataset(run.default_dataset_id).iterate_items():
    if row["status"] == "ok":
        print(row["published"], row["title"], row["link"])
```

(With apify-client versions before 3.0, `call()` returns a dict: use `run["defaultDatasetId"]`.)

**JavaScript** (`npm install apify-client`):

```js
import { ApifyClient } from 'apify-client';

const client = new ApifyClient({ token: process.env.APIFY_TOKEN });
const run = await client.actor('ataism/rss-feed-reader').call({
    feeds: ['https://blog.apify.com/rss/'],
    onlyNewSince: '2026-10-01',
});
const { items } = await client.dataset(run.defaultDatasetId).listItems();
for (const row of items.filter((r) => r.status === 'ok')) console.log(row.published, row.title, row.link);
```

**n8n:**

1. Add a Schedule trigger (for example every hour).
2. Add the **Apify** node, operation **Run an Actor and get dataset**, Actor `ataism/rss-feed-reader`, input `{"feeds": ["https://blog.apify.com/rss/"], "onlyNew": true, "stateName": "n8n-digest"}`.
3. Send each new item (filter on `status` = `ok`) to Slack, email, a sheet or an AI step.

**Make:**

1. Add the **Apify** module **Run an Actor**, choose `ataism/rss-feed-reader`, put your feed URLs in the input JSON (with `"onlyNew": true` and a memory name for schedules) and set *Run synchronously* to *Yes*.
2. Add the **Apify** module **Get Dataset Items** and map the run's default dataset ID (one bundle per item).
3. Send the items to Google Sheets, Airtable, Notion, a database or a webhook.

### Privacy and terms

- The Actor reads robots.txt, the feeds you enter and, for site URLs, the one page that announces the feed. It never opens the item links or downloads enclosures.
- **Email addresses are removed** from titles, summaries, full text, categories, ids and feed titles (also `%40`-encoded ones and addresses split by HTML tags), and phone numbers that carry a cue (a leading `+`, or a word such as "phone", "tel" or "call") are removed from text. Plain numbers (prices, order numbers, dates) stay. Links and enclosure URLs that carry an email address lose their query string.
- **Author:** RSS feeds often write the author as `email (Name)`. Only the name, the byline the site publishes, is kept; the address is never output, and an author given only as an address becomes `null`. The author is whatever name the feed publishes: in a comments feed, that is the commenter's name or nickname. Feeds can still contain other personal data in their text (names, quotes); that is what the site published. Channel-level contact fields (`managingEditor`, `webMaster`, the podcast `itunes:owner` name and email) are never read or output.
- Nothing is sent to any AI or third-party service. No logins, no proxies, no CAPTCHA solving.
- Your dataset and the only-new memory belong to your Apify account and follow your retention settings.
- **You are responsible for having the right to read and use the feeds you enter** (their terms and copyright, your agreement with the publisher). Feeds are published for readers and the Actor obeys robots.txt, but it does not know your agreement with the site.
- User-Agent: `rss-feed-reader-actor/0.1 (https://apify.com/ataism/rss-feed-reader)`. In robots.txt, `User-agent: rss-feed-reader-actor` targets this Actor (exact match; otherwise the `*` group applies).

### Safety

Only `http` and `https` to **public** addresses: private, loopback, link-local and internal addresses and other schemes are blocked, also after every redirect (at most 5) and at connection time. Each document is capped at 15 MB downloaded and 15 MB decompressed (10 MB below 512 MB of memory) and 60 seconds; robots.txt at 512 KB. Parsing runs in a separate worker thread with a 20-second time limit and a 96 MB memory limit. The XML parser is a flat scanner: it builds no tree (deep nesting costs nothing), never expands DTD entities (no "billion laughs"), and caps every tag and value.

### Limits and honest caveats

- Limits: 100 feed or site URLs, 1,000 items read per feed, 50,000 item rows and 30 minutes per run.
- **Default memory is 256 MB.** Below 512 MB, documents are capped at 10 MB and **Include full text** takes at most 200 items per feed (with a log line). For feeds up to 15 MB or full text for up to 1,000 items per feed, start the run with **512 MB**.
- A site URL gives the **first** feed its page announces (usually the main feed; WordPress lists the comments feed second). For another feed, enter its URL directly.
- Items are sorted newest first only when every item has a date; otherwise the feed's order is kept.
- With **Published on or after** set, items without a date are dropped.
- Up to one request per second per host, slower when robots.txt asks for a `Crawl-delay` (honoured in full up to 30 s; at most 5 minutes of such waiting per run). Many feeds on one slow host therefore take long, or end in free `slow-host` rows.
- Rows are written after each feed (and every 500 rows or 30 s). If the platform migrates the run, buffered rows are written and progress is saved; the resumed run reads the dataset and never writes or charges an item twice.

### FAQ

**Do I pay for feeds that have no new items?** No. Only item rows (`status: "ok"`) are charged. With **Only new items**, an unchanged feed whose server supports conditional requests (`ETag` or `Last-Modified`) is answered with `304 Not Modified` and nothing is downloaded; other servers send the feed again, which is read and not charged.

**The site has a feed but I get `no-feed`.** Its page does not announce the feed in its HTML head. Enter the feed URL itself (often `/feed`, `/rss.xml` or `/atom.xml`).

**Why is a feed `robots-blocked`?** The site's robots.txt disallows that path for crawlers in general or for this Actor. The Actor respects that.

**Can I read YouTube or Reddit feeds?** No. Social-media, video and Google feeds are refused by design (`platform`).

**Does the default run work without setup?** Yes. It reads the 10 newest posts of `https://blog.apify.com/rss/` (2 requests, about 2 seconds, $0.005).

### Open-source components

The Actor uses the **Apify SDK** (`apify` 3.7.2, Apache-2.0). The feed parser, HTML-to-text conversion, robots.txt parser and fetching are plain code in this Actor, with no other dependencies.

# Actor input Schema

## `feeds` (type: `array`):

One per line, up to 100. A feed URL (RSS, Atom, RDF or JSON Feed) is read directly. A site or page URL is opened once and the first feed its HTML head announces (<link rel="alternate" type="application/rss+xml">, Atom or JSON Feed) is read. feed:// URLs and bare hosts are accepted. Social-media, video and Google hosts (YouTube, Reddit, FeedBurner and similar) are refused.

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

The newest items taken from each feed (each item row is charged). Default 100, maximum 1,000; at most the first 1,000 items of a feed are read.

## `maxItems` (type: `integer`):

Upper limit of item rows for the whole run. Default 2,000, hard cap 50,000. The run stops cleanly when it is reached.

## `onlyNewSince` (type: `string`):

Optional date (YYYY-MM-DD, or a full date-time with zone). Keeps items whose published date (or updated date, when there is no published date) is on or after it. Items without any date are dropped while this is set. Dropped items are not charged.

## `onlyNew` (type: `boolean`):

For scheduled runs: return only items this memory has not returned before (remembered per feed while the feed lists them, plus 120 days, in a named key-value store in your account, rss-feed-reader-state). Items delivered and charged are remembered, and so are items your own filters skipped (older than Published on or after, or over Max items per feed); items not delivered because of the budget or Max items in total are not.

## `stateName` (type: `string`):

A plain label you choose, nothing private: it names the memory that Only new items uses. Use a different name for each saved task or schedule to keep their memories apart (for example "news-digest"). Leave empty to use the memory called "default". Only used with Only new items.

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

Add contentText: the item's full content (content:encoded, Atom content or JSON Feed content) as plain text, up to 20,000 characters, with email addresses and phone numbers removed. Off by default (the summary is always included).

## `mode` (type: `string`):

Internal: "selfTest" runs the maintainer health check and saves no items.

## Actor input object example

```json
{
  "feeds": [
    "https://blog.apify.com/rss/"
  ],
  "maxItemsPerFeed": 10,
  "maxItems": 2000,
  "onlyNew": false,
  "includeContent": false,
  "mode": "run"
}
```

# Actor output Schema

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

One item per feed entry (feedUrl, title, link, id, published, updated, author, summary, categories, enclosures, language), plus free error rows (JSON, CSV, Excel or XML).

## `runSummary` (type: `string`):

Item rows and charges, feeds and pages read, feeds found from site URLs, items already seen or filtered, feeds not modified, bytes downloaded, errors by code and why the run stopped.

# 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 = {
    "feeds": [
        "https://blog.apify.com/rss/"
    ],
    "maxItemsPerFeed": 10
};

// Run the Actor and wait for it to finish
const run = await client.actor("ataism/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 = {
    "feeds": ["https://blog.apify.com/rss/"],
    "maxItemsPerFeed": 10,
}

# Run the Actor and wait for it to finish
run = client.actor("ataism/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 '{
  "feeds": [
    "https://blog.apify.com/rss/"
  ],
  "maxItemsPerFeed": 10
}' |
apify call ataism/rss-feed-reader --silent --output-dataset

```

## MCP server setup

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