RSS Feed Reader: RSS, Atom & JSON Feed to JSON
Pricing
$0.50 / 1,000 feed items
RSS Feed Reader: RSS, Atom & JSON Feed to JSON
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.
Pricing
$0.50 / 1,000 feed items
Rating
0.0
(0)
Developer
Kaizoku Data
Maintained by CommunityActor stats
0
Bookmarked
2
Total users
1
Monthly active users
3 days ago
Last modified
Categories
Share
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/blogand 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-delayis 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
- 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).
- 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 freeno-feedrow. - 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 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:
{"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:
{"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):
{"feeds": ["https://blog.apify.com/rss/", "https://www.ietf.org/blog/feed/"],"onlyNew": true,"stateName": "daily-digest","maxItemsPerFeed": 50}
Output
One row per item:
{"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"}
feedUrlis the feed the item comes from (after redirects; for a site URL, the feed its page announces).inputUrlis what you entered.feedFormatisrss,rdf,atomorjson.idis the item's own identifier (RSSguid, Atomid, JSON Feedid, RSS 1.0rdf:about), or the link when there is none.publishedandupdatedare ISO 8601 UTC (nullwhen absent or unreadable).summaryis 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.titleis at most 500.enclosureslists attached files (RSSenclosure, Atomrel="enclosure"links,media:content, JSON Feed attachments) withurl,type(MIME type ornull) andlength(bytes ornull). The files are not downloaded.categoriesare de-duplicated (at most 30).languageis the item's or the feed's language tag.
Problems are free rows with status: "error":
{"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'sETag/Last-Modifiedvalues: 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. A304 Not Modifiedanswer is free and nothing is downloaded (feedsNotModifiedin 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):
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"):
import osfrom apify_client import ApifyClientclient = 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):
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:
- Add a Schedule trigger (for example every hour).
- 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"}. - Send each new item (filter on
status=ok) to Slack, email, a sheet or an AI step.
Make:
- Add the Apify module Run an Actor, choose
ataism/rss-feed-reader, put your feed URLs in the input JSON (with"onlyNew": trueand a memory name for schedules) and set Run synchronously to Yes. - Add the Apify module Get Dataset Items and map the run's default dataset ID (one bundle per item).
- 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 becomesnull. 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 podcastitunes:ownername 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-actortargets 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 freeslow-hostrows. - 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.