RSS Keyword Monitor — Only New Items & Webhooks avatar

RSS Keyword Monitor — Only New Items & Webhooks

Pricing

from $2.00 / 1,000 new items

Go to Apify Store
RSS Keyword Monitor — Only New Items & Webhooks

RSS Keyword Monitor — Only New Items & Webhooks

RSS feed monitor for keyword, regex, and exclusion filters across RSS, Atom, and RDF. Supports RSS-to-webhook delivery and JSON output, returning only new matching items per Task.

Pricing

from $2.00 / 1,000 new items

Rating

0.0

(0)

Developer

Telemark Digital

Telemark Digital

Maintained by Community

Actor stats

0

Bookmarked

1

Total users

1

Monthly active users

20 days ago

Last modified

Share

RSS Keyword Monitor is an RSS feed monitor for keyword and regex alerts. It monitors RSS, Atom, and RDF feeds on an Apify Schedule and returns only matching items that are new within the Task's deduplication window, as structured JSON and optional webhooks.

What RSS Keyword Monitor does

Give it a list of feed URLs and (optionally) keywords, regex patterns, and exclude terms. Run it on an Apify Schedule — hourly, every 15 minutes, daily, whatever. On each run it:

  • fetches every feed with If-None-Match / If-Modified-Since, so unchanged feeds can return 304 without item delivery or new-item event charges (the run still has the actor-start charge),
  • parses RSS 2.0, Atom 1.0 and RSS 1.0 (RDF), handling legacy encodings and broken feeds without crashing,
  • keeps a durable per-Task seen-set, so it suppresses repeat delivery within your configured dedup window,
  • filters by keyword / regex, drops your exclude terms, and
  • writes one clean JSON record per new matching item to the dataset; new-item charges apply only to those delivered records.

It turns a schedule (or an AI agent poll) into a cheap, recurring "what's new in my feeds" event stream. You can download the results as JSON, CSV, Excel or HTML, pull them from the API, wire them into n8n / Make / Zapier, or call it as an MCP tool.

When to use it

Use this Actor for scheduled monitoring of specific feeds when you need keyword or regex filtering, cross-run deduplication, and machine-readable delivery to a dataset or webhook. It is designed for automation pipelines and agents that consume new matching items rather than for browsing feeds in a reading UI or retrieving a one-off archive.

How much does it cost?

Every run has a $0.005 actor-start charge, including runs where every feed returns 304 or no item matches. A $0.002 new-item charge applies only to each delivered new matching item. Duplicates, excluded items, unchanged (304) feeds, and failed feeds do not create new-item charges.

Cost formula: runs*$0.005 + delivered new matching items*$0.002

2-minute quickstart

  1. Click Try for free.
  2. In Feed URLs, paste one or more feeds (defaults are prefilled so you can just hit Start).
  3. Optionally add Keywords (e.g. acquisition, funding round) — leave empty to get every new item.
  4. Click Start. The first run seeds the seen-set and returns matching items (up to Max items per run).
  5. Run it again — you'll get 0 new items (everything's already been delivered). That's the point.

Run it on a schedule (the whole point)

Cross-run dedup only makes sense on a Task + Schedule, because state is keyed by Task.

  1. Configure the input, then Create task ▸.
  2. Open the Task ▸ Schedule ▸ e.g. every hour.
  3. Add a Webhook URL (below) to get pushed only when there's something new.

Example Task input:

{
"feeds": [
"https://hnrss.org/frontpage",
"https://www.theverge.com/rss/index.xml",
"https://feeds.bbci.co.uk/news/rss.xml"
],
"keywords": ["acquisition", "funding round", "layoffs"],
"excludeTerms": ["rumor"],
"matchFields": ["title", "description"],
"onlyNew": true,
"webhookUrl": "https://your-endpoint.example.com/rss-hook"
}

Recipes

n8n

Add an HTTP Request node (or the Apify node) that runs this Actor. To receive pushed results, add a Webhook node and paste its URL into webhookUrl; it receives a POST only when there are new items.

Make (Integromat)

Run the Actor from your scenario and send filtered deltas to a Custom webhook module by placing that module's URL in webhookUrl.

Slack (or Discord / Teams)

Create an Incoming Webhook in Slack and put its URL in webhookUrl. Slack endpoints receive a concise text message with up to 10 item links. Other endpoints receive the raw JSON payload below.

Raw webhook payload

webhookUrl receives a POST (Content-Type: application/json) only when there are new items:

{
"summary": {
"newItemsDelivered": 2,
"feedsOk": 8,
"feedsNotModified": 20,
"feedsError": 0,
"onlyNew": true,
"chargeLimitReached": false,
"webhookDelivered": true,
"charge": { "actorStart": 1, "newItemEvents": 2, "newItemEventsAttempted": 2 }
},
"items": [
{
"feedUrl": "…",
"title": "…",
"link": "…",
"matchedTerms": ["acquisition"],
"firstSeenAt": "…",
"isNew": true
}
],
"itemsTruncated": false
}

items carries up to the 50 newest records; the full set is always in the dataset. A webhook failure is logged but never fails the run.

Use it from an AI agent (MCP)

Eligible paid Apify Actors can be exposed through mcp.apify.com when you add them to your MCP server configuration. The only-new semantics fit agent polling — "what's new in these feeds since I last asked?" Call this Actor with feeds + keywords; on a Task it remembers what it already returned within the dedup window.

Input

FieldTypeDefaultNotes
feedsstring[]Apify blog + BBC samplesRSS/Atom/RDF URLs, 1–500. Replace the samples with the feeds you want to monitor.
keywordsstring[][]Case-insensitive substrings, OR-matched. Empty = deliver every new item.
regexPatternsstring[][]OR-matched with keywords (case-insensitive). Invalid pattern fails the run with a clear error.
excludeTermsstring[][]Drop matched items containing any of these. Applied before charging.
matchFieldsstring[]["title","description"]Any of title, description, content, categories.
onlyNewbooleantrueOff = plain filtered read of the current feeds (still charged per item).
maxItemsPerRuninteger200Hard billing ceiling. In only-new mode, validators are held so overflow is retried on the next run.
dedupWindowinteger45Days an item stays in the seen-set (7–365).
includeContentbooleantrueInclude content:encoded HTML per item when present. No article-page fetching.
webhookUrlstringPOSTed only when there are new items.
resetStatebooleanfalseWipe this Task's seen-set + HTTP validators. Use once, then turn off.

Output

One dataset record per new matching item:

{
"feedUrl": "https://hnrss.org/frontpage",
"feedTitle": "Hacker News: Front Page",
"feedType": "rss",
"itemKey": "guid:https://news.ycombinator.com/item?id=44861023",
"guid": "https://news.ycombinator.com/item?id=44861023",
"title": "EU AI Act enforcement begins for foundation models",
"link": "https://example.com/eu-ai-act",
"author": "tosh",
"publishedAt": "2026-07-11T08:14:02.000Z",
"firstSeenAt": "2026-07-11T08:30:11.412Z",
"categories": ["ai", "regulation"],
"description": "Enforcement of the EU AI Act's obligations…",
"content": "<p>Full content:encoded HTML when the feed provides it…</p>",
"matchedTerms": ["eu ai act"],
"isNew": true
}

A per-run summary (per-feed statuses, counts, attempted and actually charged event counts, and spending-limit status) is written to the run's key-value store under OUTPUT — the dataset stays clean for pipelines. firstSeenAt is our server clock at first delivery. publishedAt is the feed's untrusted claim: it is never used as a time cursor, but it is part of the hash fallback when an item has neither GUID nor link.

How the "only new" state works

  • Keyed by Task. State lives under your Task ID, so editing keywords or feeds never resets history — no fragile manual snapshot key to fat-finger. Ad-hoc (non-Task) runs share a persistent per-user scope; create a Task for isolated recurring monitoring.
  • Sharded per feed in a named key-value store, pruned on writes, capped at 20,000 identity keys/feed (oldest evicted). GUID items can use two keys. Eviction degrades to occasional re-delivery, not failure.
  • dedupWindow controls how long an item is remembered. Feeds that legitimately re-surface an item older than the window will re-deliver it.
  • Redirects: we follow up to 5; on a permanent (301) redirect we log the new URL and recommend you update it — state stays on the URL you configured, so renaming never orphans history.
  • resetState: true fully wipes this Task's seen-set and stored validators for a clean start.

Feed handling & reliability

  • Formats: RSS 2.0, Atom 1.0, RSS 1.0 (RDF). (JSON Feed is not yet supported — it returns a clear per-feed error, not a crash.)
  • Encodings: respects the Content-Type / XML-declaration charset with an iconv fallback for legacy JP/CN encodings; strips BOMs; tolerates leading whitespace; detects HTML error pages instead of choking on them.
  • Per-feed isolation: each network attempt has a hard timeout and every response has a 10 MB cap; one dead, hostile or malformed feed becomes a single error row in the summary. The run still succeeds, and that feed creates no new-item charge; the run's actor-start charge still applies.
  • Politeness: a descriptive User-Agent, gzip accepted, conditional GET on delta polls, bounded retries, and sequential requests for feeds configured on the same host. Redirects are bounded and revalidated. WAF-fronted feeds may still block cloud egress.

Concurrent runs sharing the same state scope are serialized by the exclusive state lease. A contender is rejected before state mutation, delivery, or charging and can be retried after the active run finishes.

FAQ

What does the first run return? Everything currently matching (up to maxItemsPerRun), and it seeds the seen-set. Subsequent runs return only what's new since. To seed silently, set a low maxItemsPerRun on the first run.

A feed has no GUIDs — will I get duplicates? No. When guid is absent we key on link, and if that's missing too, on a stable hash of feedUrl + title + pubDate. We also guard against WordPress-style GUID rotation (same link+title, new guid → treated as already seen).

A feed keeps re-surfacing old items. They're suppressed while within dedupWindow. If they resurface after it, they re-deliver — raise the window if that's unwanted.

Does editing keywords or feeds reset my history? No — state is keyed by Task, not by your config.

Why did a run "succeed" with a dead feed? Per-feed isolation: the dead feed is an error row in the run summary and creates no new-item charge; the rest of the run proceeds. The run's actor-start charge still applies. Check the OUTPUT record for per-feed detail.

Can it fetch the full article text? No — it returns what the feed provides (content:encoded when present). Article-page extraction is a different, costlier job.

JSON Feed? Not yet — it returns a clear per-feed error rather than failing the run.

Support

Found a bad feed or an edge case? Open an issue on the Actor's Issues tab with the feed URL — feed pathology is exactly what this Actor is built to handle well, and reports make it better.