SFOLN

Catalogue / Web toolkit for agents

RSS Feed Reader – Blogs, News & Newsletters

sfoln/rss-feed-reader · News, Automation, AI On request

Read RSS, Atom and JSON feeds, or paste any website, Substack, Ghost, Beehiiv or Medium URL and the feed is found for you. One clean JSON row per item: title, link, date, author, summary, full content, categories, image, podcast audio. Only-new mode for monitoring. $0.50 per 1,000 items.

About

What it does

Read any RSS, Atom or JSON feed as clean JSON, or just paste a website, blog or newsletter URL (Substack, Ghost, Beehiiv, Medium, WordPress, Blogger, YouTube channel) and the feed is found for you. You get one row per item with title, link, publication date, author, a plain-text summary, the full content (HTML and text), categories, image and podcast enclosure, newest first, plus one summary row per feed. Built for news monitoring, content curation, newsletter tracking, podcast catalogues and AI agents that need "what's new on this site?". $0.50 per 1,000 items, no start fee; feeds that cannot be found or read are free.

Price

Price per delivered record

EventPricePer 1,000Charged for
Feed item
feed-item
$0.0005$0.50 / 1,000Charged once per feed item (post, article, episode) delivered as a dataset row.

Apify free plan: up to 10 items per run. Paid plans have no per-run cap; set maxTotalChargeUsd to cap spend.

Run

Call it from code, an agent or the Console

This API is private on Apify for now. Email us and we will publish it for you, usually within two working days. The calls below work once it is public. contact@sfoln.com

curl · synchronous run, rows in the response
curl -X POST "https://api.apify.com/v2/actors/sfoln~rss-feed-reader/run-sync-get-dataset-items" \
  -H "Authorization: Bearer $APIFY_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"feedUrls":["https://blog.apify.com/rss/"],"maxItemsPerFeed":10}'
mcp.json · hosted Apify MCP server
{
  "mcpServers": {
    "apify": {
      "type": "http",
      "url": "https://mcp.apify.com?tools=sfoln/rss-feed-reader"
    }
  }
}
asynchronous run · for large batches
POST https://api.apify.com/v2/actors/sfoln~rss-feed-reader/runs?maxTotalChargeUsd=1
GET  https://api.apify.com/v2/actor-runs/{runId}            # until status is SUCCEEDED
GET  https://api.apify.com/v2/datasets/{defaultDatasetId}/items?format=json

Authenticate with an Apify API token. MCP clients can instead sign in with OAuth when prompted. Example prompt for an agent: Get the 10 latest posts from https://blog.apify.com/rss/ with their titles, links and publication dates.

Input

Input fields

Feed, website or newsletter URLs. Every feed gives one dataset row per item plus one summary row.

FieldTypeDefaultMeaning
feedUrls *arrayrequiredFeed, website or newsletter URLs
RSS, Atom or JSON Feed URLs, or any website, blog or newsletter URL (Substack, Ghost, Beehiiv, Medium, WordPress, Blogger, YouTube channel): the feed is discovered automatically. One per line. Accounts on the Apify free plan can process up to 10 feeds per run.
maxItemsPerFeedinteger100Max items per feed
Newest items delivered per feed (1–5,000). Each delivered item is one feed-item event. Range 1–5000.
sinceDaysinteger0Only items from the last N days
Only items published in the last N days (0 = no date filter). Items without a date are left out when this is set. Range 0–36500.
onlyNewbooleanfalseOnly new items (monitoring)
Deliver (and charge) only items that earlier runs of yours did not deliver. The first run returns the latest items and remembers everything the feed lists; later runs return only items published after it. The memory is kept in your account's key-value store "rss-feed-reader-memory" for 30 days after an item was last seen.
includeContentbooleantrueInclude full content
Add the full item content as published (contentHtml) and as plain text (contentText) when the feed carries it. Turn off for smaller rows.
maxFeedsinteger1000Max feeds
Safety cap on how many URLs are processed in this run; the rest are ignored and counted in the OUTPUT record. Range 1–10000.
concurrencyinteger5Concurrency
Feeds processed in parallel (1–10). Requests to one host are always limited to 2 per second. Range 1–10.
includeRawbooleanfalseInclude raw item
Attach the parsed source item (every namespace: iTunes, podcast, media, Dublin Core, …) as raw on each row.
Example input
{
  "feedUrls": [
    "https://blog.apify.com/rss/"
  ],
  "maxItemsPerFeed": 10
}

Output

One record per input item

Records land in the run's dataset; a synchronous call returns them directly. Each has a status (ok is charged; everything else is free) and a charged flag. The run's OUTPUT record totals items and charges.

FieldTypeMeaning
inputstring | objectInput
The feed, website or newsletter URL this record belongs to, as given.
recordTypestringRecord type
feed-item = one item of a feed (charged); summary = one record per input URL (never charged). e.g. "feed-item"
positionintegerPosition
feed-item: 1-based position of the item among the items delivered for its input (newest first).
feedUrlstring | nullFeed URL
The feed the item was read from (after redirects).
feedTitlestring | nullFeed title
guidstring | nullGUID
The item's id in the feed (RSS guid, Atom id, JSON Feed id), else its link.
titlestring | nullTitle
Item title as plain text (markup and entities decoded).
linkstring | nullLink
Absolute URL of the item's page.
publishedAtstring | nullPublished at
ISO 8601 (UTC) publication time; null when the feed gives no valid date.
updatedAtstring | nullUpdated at
ISO 8601 (UTC) last update, when the feed states one (Atom updated, JSON Feed date_modified).
authorstring | nullAuthor
Author or creator name as published.
summarystring | nullSummary
Plain-text summary (description / summary, else the start of the content), at most 1,000 characters.
contentHtmlstring | nullContent (HTML)
Full content as published in HTML (content:encoded, Atom content, content_html), at most 100,000 characters; only with includeContent.
contentTextstring | nullContent (text)
Full content as plain text (content_text, else derived from contentHtml), at most 100,000 characters; only with includeContent.
categoriesarrayCategories
Categories and tags of the item.
enclosureobject | nullEnclosure
{ url, type, length } of the item's first enclosure (podcast audio, video, attachment).
imageUrlstring | nullImage URL
Media thumbnail, iTunes image, image enclosure or the first image of the content.
durationSecsinteger | nullDuration (s)
Media duration in seconds (podcasts, videos), when stated.
inputUrlstring | nullInput URL
summary: the input normalized to an absolute URL.
feedFormatstring | nullFeed format
summary: rss | atom | rdf | json.
siteUrlstring | nullSite URL
summary: the website the feed belongs to.
feedDescriptionstring | nullFeed description
feedLanguagestring | nullFeed language
feedImageUrlstring | nullFeed image URL
feedUpdatedAtstring | nullFeed updated at
summary: ISO 8601 time the feed says it was last built or updated.
discoveredViastring | nullDiscovered via
summary: direct (the URL is a feed) | platform (Substack, Medium, …) | link (<link rel="alternate"> on the page) | probe (a common feed path).
platformstring | nullPlatform
summary: substack | medium | ghost | beehiiv | wordpress | blogger | tumblr | youtube, when recognised.
otherFeedsarrayOther feeds
summary: further feeds the page announces (e.g. a comments feed).
itemsInFeedinteger | nullItems in feed
summary: items the feed lists.
itemsOutsideDateWindowinteger | nullItems outside sinceDays
summary: items older than sinceDays (not delivered, not charged).
onlyNewboolean | nullOnly new
summary: present when onlyNew was on.
firstRunboolean | nullFirst run
summary (onlyNew): true when no earlier run remembered this feed.
itemsAlreadySeeninteger | nullItems already seen
summary (onlyNew): items skipped because an earlier run delivered them.
resultsDeliveredinteger | nullItems delivered
summary: feed-item rows delivered (and charged) for this input.
stopReasonstring | nullStop reason
summary: limit (maxItemsPerFeed reached) | end (no more items) | budget | free_plan | aborted.
statusstringStatus
ok | not_found | error | skipped_invalid | skipped_budget | skipped_free_plan | skipped_unmetered e.g. "ok"
chargedbooleanCharged
true on every feed-item row (one feed-item event each); summary records are never charged.
chargedEventstringCharged event
feed-item on item rows.
chargedCountintegerEvents charged
Events actually charged when a charge came back short (present only then).
sourcestringSource
Always "feed" (fetched from the publisher by the Actor).
fetchedAtstringFetched at
ISO timestamp.
errorobjectError
{ code, message, provider?, status? } when status is not ok. Codes: not_a_feed (no feed found), malformed_feed, invalid_url, not_found, http_error, timeout, network, dns_not_found, blocked_url, too_large, unexpected_type, plus the runtime codes budget_exhausted, free_plan_limit, unmetered, aborted, charge_failed, record_too_large, invalid_record, dataset_push_failed.
warningsarrayWarnings
Notes about this record (lenient parsing, undated items, budget or free-plan caps).
rawobject | nullRaw item
The parsed source item with every namespace (only with includeRaw).
Example record
[
  {
    "input": "https://blog.apify.com/rss/",
    "recordType": "feed-item",
    "position": 1,
    "feedUrl": "https://blog.apify.com/rss/",
    "feedTitle": "Apify Blog",
    "guid": "654c99deca26d10001cb6b14",
    "title": "How to do question answering from a PDF with Python and RAG",
    "link": "https://blog.apify.com/how-to-do-question-answering-from-a-pdf/",
    "publishedAt": "2026-10-14T08:16:08.000Z",
    "updatedAt": null,
    "author": "Jane Example",
    "summary": "Build a Python pipeline that answers questions from PDFs and links each answer to its page, then check the citations before you trust them.",
    "contentHtml": "<p>A cited page lets you check an answer from a PDF …</p>",
    "contentText": "A cited page lets you check an answer from a PDF …",
    "categories": [
      "AI",
      "Data processing and analysis",
      "Tutorial"
    ],
    "enclosure": null,
    "imageUrl": "https://blog.apify.com/content/images/2026/10/question-answering-from-a-pdf-feature-image.webp",
    "durationSecs": null,
    "status": "ok",
    "charged": true,
    "chargedEvent": "feed-item",
    "source": "feed",
    "fetchedAt": "2026-10-14T10:00:00.000Z"
  },
  {
    "input": "https://blog.apify.com/rss/",
    "inputUrl": "https://blog.apify.com/rss/",
    "feedUrl": "https://blog.apify.com/rss/",
    "feedTitle": "Apify Blog",
    "feedFormat": "rss",
    "siteUrl": "https://blog.apify.com/",
    "feedDescription": "Apify is the largest marketplace of tools for AI.",
    "feedLanguage": null,
    "feedImageUrl": "https://blog.apify.com/favicon.png",
    "feedUpdatedAt": "2026-10-14T17:13:34.000Z",
    "discoveredVia": "direct",
    "platform": null,
    "otherFeeds": [],
    "itemsInFeed": 15,
    "itemsOutsideDateWindow": 0,
    "recordType": "summary",
    "resultsDelivered": 10,
    "stopReason": "limit",
    "status": "ok",
    "charged": false,
    "source": "feed",
    "fetchedAt": "2026-10-14T10:00:01.000Z"
  }
]

FAQ

Questions

Do I need the exact feed URL?
No. Paste a website, blog or newsletter URL and the Actor finds the feed: the page's `<link rel="alternate">` feeds first, then the usual feed paths (/feed, /rss, /feed.xml, /atom.xml, /index.xml, /feed.json). Substack, Ghost, Beehiiv, Medium, WordPress.com, Blogger, Tumblr and YouTube channel URLs are mapped to their feeds directly. The summary row says how the feed was found (discoveredVia) and lists other feeds the page announces.
How does onlyNew work for monitoring?
With onlyNew on, the Actor remembers which items it delivered to you (hashed ids only, in your account's key-value store "rss-feed-reader-memory", one record per feed). The first run returns the latest items and remembers everything the feed lists; every later run returns, and charges, only items that were not delivered before. Schedule it hourly or daily and attach a webhook to get new posts pushed to you. Delete the store to start over.
Which feed formats are supported?
RSS 0.9x, 1.0 (RDF) and 2.0, Atom 0.3 and 1.0, and JSON Feed 1.0 and 1.1, including the content, Dublin Core, Media RSS and iTunes podcast extensions. Malformed feeds (unescaped ampersands, a cut-off file, stray control characters) are repaired and read leniently, with a warning.

Machine-readable

This page for agents