RSS Feed Scraper - Atom & JSON Feed Reader, New Item Monitor avatar

RSS Feed Scraper - Atom & JSON Feed Reader, New Item Monitor

Pricing

from $4.38 / 1,000 feed item returneds

Go to Apify Store
RSS Feed Scraper - Atom & JSON Feed Reader, New Item Monitor

RSS Feed Scraper - Atom & JSON Feed Reader, New Item Monitor

Give it feed URLs or plain website URLs. It finds the feed a site advertises, reads RSS 2.0, RSS 1.0/RDF, Atom and JSON Feed in any encoding, and returns one row per item with title, link, dates, author, summary, full text, categories, image and enclosures. Monitoring mode returns only new items.

Pricing

from $4.38 / 1,000 feed item returneds

Rating

0.0

(0)

Developer

NeverEmpty

NeverEmpty

Maintained by Community

Actor stats

0

Bookmarked

2

Total users

1

Monthly active users

2 days ago

Last modified

Share

RSS Feed Scraper — read RSS, Atom and JSON Feed, find a site's feed, watch for new items

Give it feed URLs, or plain website URLs. github.blog is enough.

For a website, it reads the feed the page itself advertises with <link rel="alternate" type="application/rss+xml"> (or Atom / JSON Feed). Then it returns one row per item: title, link, published and updated dates, author, summary, full text, categories, image, enclosures (podcast audio), duration, guid, and which feed it came from.

It reads RSS 2.0, RSS 1.0 / RDF, Atom and JSON Feed (1.0 and 1.1), in any character encoding.

Real feeds are messier than the specs

Measured on 2026-09-12 against more than 30 live feeds. Every case below is in this Actor's tests, using the real feed:

FeedWhat it doesWhat this Actor does
soumu.go.jp (Japanese government)Shift_JIS, and the server does not say so — only the XML declaration doesReads the XML declaration, returns clean Japanese
SlashdotDeclares ISO-8859-1Decoded as declared
kantei.go.jp (Japanese PM's office)Served as application/octet-stream. guids are positions (item_1item_25): tomorrow's item_1 is a different articleDetects the feed from its content. Identifies an item by guid and link, so a new item_1 is still new
abc.esLists the same article 20 times: one link for all of them, and the guid written both with and without a trailing slashA trailing slash does not make a new item, so it is returned once and charged once. Items that really differ are still kept apart
A feed that stops mid-wayThe server closes the connection, or a gzip body cannot be unpacked to the endThe item that was cut off is dropped, never returned and never charged. A free row says the body ended early
b.hatena.ne.jpEvery Japanese character in titles written as a hex entity (&#x4E2D;)Decoded
gov.ukDouble-encoded summaries (UK&amp;#39;s)UK's
blog.cloudflare.com, news.ycombinator.comThe page advertises the feed with a relative link (/rss/, rss)Resolved against the page
YouTube channel pagesThe feed link sits in <body>, not <head>Found anyway
NPR podcast2.1 MB, 355 episodes in one feedAll read. Size limit is adjustable, and a feed cut at the limit returns only complete items
Most news feedsDates as Fri, 11 Sep 2026 13:00:00 GMT, 11 Sep 2026 19:00:00 +0900, 2026-09-12T00:00:00+09:00Converted to UTC

We also ran the same 16 feeds and 10 website URLs through a second, independent XML parser. Item counts, links and titles matched on every feed we could compare. The check lives in verify/crosscheck.mjs, so you can run it again.

Dates are never guessed

  • publishedAt / updatedAt hold a UTC instant only when the feed states a time zone.
  • A time with no zone (2026-09-11 10:00) goes to publishedLocal / updatedLocal exactly as written. It is not treated as UTC, and it is not converted with the server's clock.
  • Abbreviations that mean more than one zone (IST, BST) are treated as unknown.
  • The raw text is always kept in published / updated.

Monitoring mode: only new items

Turn on Monitoring mode and the Actor remembers the items it returned for each feed.

  • The first run returns everything and remembers it.
  • Later runs return only items that were not returned before.
  • A quiet day returns a free row that says no-new-since-last-run. Nothing is charged. This is kept separate from no-results, which means the feed really lists nothing.
  • Only items that were actually returned are remembered. If a run stops at a limit, the rest arrive on the next run.
  • The memory is kept per feed and per filter setting, so two watches on the same feed with different keywords do not affect each other.
  • The memory holds the last 5,000 items per feed and filter setting. A feed that publishes more than 5,000 items between two runs can return an older item again.

What comes back

FieldWhat it is
title, linkThe item's title (plain text) and its absolute URL
publishedAt, updatedAtUTC instant, only when the feed states a time zone
publishedLocal, updatedLocalThe time as written, when the feed gives no zone
published, updatedThe raw date text from the feed
author, authorsAuthor names. Email addresses are removed (RSS writes authors as email (Name))
summaryThe description / summary as plain text
contentTextThe full content as plain text, when the feed carries it (content:encoded, Atom content, JSON Feed content_html / content_text)
contentHtmlThe same content as HTML, only with includeContentHtml. Relative links and images are made absolute
hasFullContentWhether the feed carried full content for this item
categoriesCategories, tags, dc:subject
imageUrlmedia:thumbnail, an image media:content or enclosure, or itunes:image. Only images the feed itself names
enclosureUrl, enclosureType, enclosureLength, enclosuresPodcast audio and other attachments. A stated length of 0 means unknown and comes back as null
durationSecondsFrom itunes:duration or JSON Feed attachments
commentsUrl, externalUrlRSS comments, JSON Feed external_url
guid, guidIsPermaLink, itemKeyThe feed's own id, and the key this Actor uses to recognise the item (guid + link)
position, feedItemCountThe item's place in the feed, and how many items the feed lists
feedTitle, feedLink, feedLanguage, feedType, feedEncodingAbout the feed: rss-2.0, rss-1.0-rdf, atom, json-feed-1.1, …, and the encoding it was decoded with
feedUrl, requestedUrl, foundViaThe feed actually read (after redirects), the URL you gave, and given / link-tag / common-path
status, reason, httpStatusok, or why a URL produced nothing

A field the feed does not state comes back as null. Nothing is filled in with a zero or a guessed date.

Input

FieldDefaultWhat it does
urlsFeed URLs or website URLs. If this and urlsText are both empty, two example URLs are read and a free row says so
urlsTextemptyThe same list as a block to paste, one URL per line
maxItemsPerFeed100Items per feed, in the feed's own order (newest first on almost every feed). 0 = all
maxItems1000Items across the whole run. URLs not reached get a free not-looked-up row. Must be at least 1: 0 is not "no limit" here, and a free row says so if you send it
discoverAllFeedsoffFrom a website URL, read every advertised feed instead of the first one
useCommonPathsonWhen a page advertises no feed, try /feed, /rss, /feed.xml, /rss.xml, /atom.xml, /index.xml, /feed.json
includeContentHtmloffAdd contentHtml
keywords, keywordMatch, excludeKeywordsempty / any / emptyMatch against title, summary, content, categories and author
publishedAfteremptyYYYY-MM-DD. An item with no date is kept, because unknown is not the same as old
timeoutSecs20Per request
maxFeedSizeMb20Stop downloading a feed after this many MB. Only complete items are returned
monitoringMode, resetMonitoringStateoffSee Monitoring mode

Pricing

Charged per item returned. The same item is never returned twice in one run, even when two feeds carry it or the same feed is reached twice. Two feeds count as carrying the same article when the guid and link match (a trailing slash is ignored) or when the title and publication time match. That second rule matters: Daring Fireball's Atom feed and its JSON Feed carry the same 48 posts under completely different guids and links, so reading both with discoverAllFeeds charges 48 items, not 96. A free row says how many items were folded that way.

Rows that explain why a URL produced nothing are not charged: bad address, blocked (blocked-to-us, for example a Cloudflare "checking your browser" page), not a feed, no feed found, empty feed, no match for the filters, nothing new in monitoring mode, an item already returned from another feed in the same run, a body that ended in the middle, or not reached because of a limit.

What it fetches

Only the URLs you give. For a website URL, it also fetches the feed that page advertises and, unless useCommonPaths is off, up to 14 common feed locations: the seven names in the page's own folder and the same seven at the site root. It does not follow links or crawl a site.

robots.txt is not read or obeyed. This Actor fetches only the URLs you ask for, the way a feed reader does (Google documents the same approach for its Feedfetcher).

Addresses inside a private network are refused, before and after a redirect: localhost, 127.0.0.1, 10.x, 172.16-31.x, 192.168.x and the cloud metadata address 169.254.169.254. If you put a user name and password in a URL (https://user:pw@example.com/feed), they are used to fetch the feed but are never written into feedUrl, requestedUrl or the log.

Notes

  • Character encoding comes from the byte-order mark, then the document's own declaration, then the HTTP header, then UTF-8. When the declaration and the header disagree, the declaration wins. The exception is valid UTF-8 bytes where either side says UTF-8, because a common server default adds charset=ISO-8859-1 to UTF-8 feeds.
  • gzip is detected from the first two bytes of the file, not from the .gz in the name.
  • Only http and https are accepted. feed:// addresses are read as http://.
  • Paged feeds (RFC 5005 rel="next") are not followed. A run returns what the feed currently lists.