# RSS, Atom & JSON Feed Monitor (`xerophylous_mercy_0wn/feed-contract-monitor`) Actor

Monitor RSS, Atom, JSON Feed and website feeds. Get structured health records and only new or changed items with persistent state and HTTP caching.

- **URL**: https://apify.com/xerophylous\_mercy\_0wn/feed-contract-monitor.md
- **Developed by:** [Hryhory Sinenka](https://apify.com/xerophylous_mercy_0wn) (community)
- **Categories:** Agents, Automation, Developer tools
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $0.80 / 1,000 feed results

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/platform/actors/running/actors-in-store#pay-per-event

## What's an Apify Actor?

Actors are web data automations that power AI and operations. They run on the Apify platform to scrape websites, process data, connect APIs, and automate workflows.
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.
Actors are written with capital "A".

## 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.
The best way to integrate Actors is as follows.

- **AI agents and MCP clients** — the [Apify MCP server](https://docs.apify.com/integrations/mcp.md) at `https://mcp.apify.com` (remote, streamable HTTP, OAuth on first use).
- **Agentic workflows and local Actor development** — [Agent Skills](https://apify.com/.well-known/agent-skills/index.json) with the [Apify CLI](https://docs.apify.com/cli/docs.md): `npm install -g apify-cli`, then `apify login`.
- **JavaScript/TypeScript projects** — the official [JS/TS client](https://docs.apify.com/api/client/js/docs.md): `npm install apify-client`.
- **Python projects** — the official [Python client](https://docs.apify.com/api/client/python/docs.md): `pip install apify-client`.
- **Any other language** — the [REST API](https://docs.apify.com/api/v2.md).

For usage examples, see the [API](#api) section below.

For more details, see Apify documentation as [Markdown index](https://docs.apify.com/llms.txt) and [Markdown full-text](https://docs.apify.com/llms-full.txt).

# README

## RSS, Atom & JSON Feed Change Monitor for Agents

Use this RSS change monitor to turn RSS, Atom, JSON Feed, or ordinary website
URLs into a stateful, versioned change stream. Every run returns feed-health
evidence and only emits item records that are new or changed after the stored
baseline.

This Actor is designed for agents, scheduled automations, ETL jobs, and
monitoring systems that need stable JSON rather than another one-time feed
parser.

### Use from an MCP client

Connect only this Actor through Apify's remote MCP server:

```text
https://mcp.apify.com?tools=xerophylous_mercy_0wn/feed-contract-monitor
```

Authenticate with Apify OAuth or a bearer token. The scoped URL keeps tool discovery focused and exposes the Actor's input and output contracts to compatible agent clients.

### What it does

- Parses RSS 2.0, RSS 1.0/RDF, Atom 1.0, and JSON Feed 1.0/1.1.
- Discovers feeds from standard HTML `<link rel="alternate">` elements.
- Sends `If-None-Match` and `If-Modified-Since` on later runs when publishers
  provide `ETag` or `Last-Modified`.
- Stores a bounded baseline in a named Apify key-value store.
- Emits `new` and `changed` item records with deterministic fingerprints and
  delivery IDs.
- Reports malformed feeds, duplicate IDs, invalid dates, stale feeds,
  redirects, HTTP failures, and output limits with stable issue codes.
- Never scrapes linked article pages. Content comes only from the feed itself.
- Rejects private-network, loopback, link-local, authenticated, and non-HTTP
  targets.

### Quick start

Use a direct feed URL:

```json
{
  "feedUrls": ["https://www.nasa.gov/feed/"],
  "firstRunMode": "emit_recent",
  "maxInitialItems": 20
}
```

Or give it websites and let it discover their declared feeds:

```json
{
  "feedUrls": [
    "https://example.com/",
    "https://another.example/news"
  ],
  "discoverFromWebsites": true,
  "stateNamespace": "production-news"
}
```

For a clean monitoring baseline without historical output:

```json
{
  "feedUrls": ["https://example.com/feed.json"],
  "firstRunMode": "baseline_only"
}
```

Schedule later runs with the same `stateStoreName` and `stateNamespace`.

### Dataset contract

The default dataset contains two record types. Both are charged as visible
dataset results under Apify pay-per-event pricing.

#### Feed-health record

One health record is emitted for every checked feed. Website discovery adds one
additional discovery health record.

```json
{
  "schemaVersion": "feed-health/1.0",
  "recordType": "feed_health",
  "sourceUrl": "https://www.nasa.gov/feed/",
  "feedUrl": "https://www.nasa.gov/feed/",
  "feedTitle": "NASA",
  "feedFormat": "rss-2.0",
  "checkedAt": "2026-08-04T15:00:00.000Z",
  "status": "ok",
  "httpStatus": 200,
  "itemCounts": {
    "seen": 10,
    "new": 3,
    "changed": 0,
    "unchanged": 7,
    "emitted": 3,
    "deferred": 0,
    "remembered": 10
  },
  "conditionalRequest": {
    "etagUsed": true,
    "lastModifiedUsed": false,
    "notModified": false
  },
  "stale": false,
  "issues": []
}
```

#### Changed-item record

```json
{
  "schemaVersion": "feed-item/1.0",
  "recordType": "feed_item",
  "sourceUrl": "https://example.com/feed.json",
  "feedUrl": "https://example.com/feed.json",
  "feedTitle": "Example research feed",
  "feedFormat": "json-feed-1.1",
  "checkedAt": "2026-08-04T15:00:00.000Z",
  "status": "new",
  "changeType": "new",
  "deliveryId": "77248d...",
  "itemId": "paper-123",
  "url": "https://example.com/papers/123",
  "title": "A new result",
  "summary": "Publisher-supplied excerpt",
  "contentText": null,
  "authors": ["Example Author"],
  "tags": ["chemistry"],
  "publishedAt": "2026-08-04T13:00:00.000Z",
  "modifiedAt": null,
  "fingerprint": "f7b5ac...",
  "sourcePointer": "items[0]",
  "issues": []
}
```

The run summary is also stored as `SUMMARY` in the run's default key-value
store.

### Delivery semantics

Delivery is **at least once**. A process can stop after a dataset write but
before its baseline update, so downstream systems should deduplicate with
`deliveryId`. The ID is stable for the same feed URL, item ID, and item
fingerprint. A corrected item receives a new delivery ID and
`changeType: "changed"`.

Missing items are not reported as deletions because most feeds are rolling
windows. Items deferred by `maxItemsPerRun` remain eligible on a later run.

### Content modes

- `metadata`: IDs, links, titles, dates, authors, and tags only.
- `excerpts` (default): metadata plus a truncated publisher-supplied summary.
- `feed_content`: excerpts plus truncated text supplied inside the feed.

The Actor does not visit item links, bypass access controls, or retrieve
authenticated content.

### Persistent state

The default named store is `feed-contract-monitor-state`. Each feed has one
hashed state record containing:

- `ETag` and `Last-Modified` values;
- last successful and last checked timestamps;
- feed format and final URL;
- bounded item IDs, fingerprints, and seen timestamps.

Use `stateNamespace` to keep independent baselines for development,
production, or different consumers. State is capped by
`maxStateItemsPerFeed`; the most recently seen entries are retained.

### Stable issue codes

| Range | Meaning |
|---|---|
| `FCM001`–`FCM010` | URL, DNS, network, redirect, size, and encoding failures |
| `FCM100`–`FCM103` | Unsupported or malformed feed/discovery documents |
| `FCM110`–`FCM116` | Feed and item quality warnings |
| `FCM200`–`FCM202` | State or output-limit warnings |

Every issue includes `code`, `severity`, `message`, and an optional source
pointer. Codes remain stable within contract version 1.x.

### Cost controls

- 256 MB default memory and 512 MB hard maximum.
- Bounded response size, retries, redirects, state, output, and concurrency.
- Conditional requests when the publisher supports them.
- No browser runtime or proxy use.
- One visible health result per checked feed, even when no item changed.

Set a run maximum cost in Apify when using large URL batches. Publication uses
pay per event so the Actor remains available to API and agentic consumers.

### Current limitations

- HTML discovery uses declared alternate links; it does not execute JavaScript.
- Non-UTF-8 feeds may contain replacement characters.
- Publisher-specific formats outside RSS, Atom, RDF/RSS, and JSON Feed are not
  inferred.
- Feed removals are not treated as item deletions.
- Availability and correctness ultimately depend on the publisher's endpoint.

### Output and schema versions

- Feed items: `feed-item/1.0`
- Feed health: `feed-health/1.0`
- Persistent state: `feed-state/1.0`
- Run summary: `feed-monitor-run/1.0`

Minor releases may add optional fields or issue codes. Breaking field changes
require a new major contract version.

# Actor input Schema

## `feedUrls` (type: `array`):

Public HTTP(S) URLs. Private-network and authenticated URLs are rejected.

## `discoverFromWebsites` (type: `boolean`):

Follow standard HTML alternate links for RSS, Atom, and JSON Feed.

## `firstRunMode` (type: `string`):

Emit recent items on the first run, or create a baseline without emitting historical items.

## `contentMode` (type: `string`):

Metadata is smallest. Excerpts adds publisher summaries. Feed content adds truncated content supplied inside the feed; linked pages are never scraped.

## `maxInitialItems` (type: `integer`):

Limits the historical items emitted when firstRunMode is emit\_recent.

## `maxItemsPerRun` (type: `integer`):

Global output safety ceiling. Deferred items remain eligible on the next run.

## `maxStateItemsPerFeed` (type: `integer`):

Bounded deduplication history retained in the named key-value store.

## `maxExcerptChars` (type: `integer`):

Truncate publisher-supplied summaries after this many characters.

## `maxContentChars` (type: `integer`):

Truncate publisher-supplied feed content after this many characters when feed\_content is selected.

## `staleAfterDays` (type: `integer`):

Warn when the newest valid item date is older than this threshold.

## `stateStoreName` (type: `string`):

Named Apify key-value store used across runs.

## `stateNamespace` (type: `string`):

Change this to maintain an independent baseline for the same feed URLs.

## `requestTimeoutSecs` (type: `integer`):

Total deadline for each network request, including its response body.

## `maxResponseBytes` (type: `integer`):

Abort a response that exceeds this decompressed size.

## `maxRetries` (type: `integer`):

Retry timeouts, network failures, rate limits, and selected server errors with bounded backoff.

## `maxConcurrency` (type: `integer`):

Maximum number of top-level feed or website URLs processed concurrently.

## Actor input object example

```json
{
  "feedUrls": [
    "https://www.nasa.gov/feed/"
  ],
  "discoverFromWebsites": true,
  "firstRunMode": "emit_recent",
  "contentMode": "excerpts",
  "maxInitialItems": 50,
  "maxItemsPerRun": 1000,
  "maxStateItemsPerFeed": 5000,
  "maxExcerptChars": 2000,
  "maxContentChars": 20000,
  "staleAfterDays": 30,
  "stateStoreName": "feed-contract-monitor-state",
  "stateNamespace": "default",
  "requestTimeoutSecs": 20,
  "maxResponseBytes": 5000000,
  "maxRetries": 2,
  "maxConcurrency": 5
}
```

# Actor output Schema

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

Default dataset containing one health record per checked feed and item records for new or changed entries.

## `summary` (type: `string`):

Counts, completion status, and contract version for this run.

# 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 = {
    "feedUrls": [
        "https://www.nasa.gov/feed/"
    ]
};

// Run the Actor and wait for it to finish
const run = await client.actor("xerophylous_mercy_0wn/feed-contract-monitor").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 = { "feedUrls": ["https://www.nasa.gov/feed/"] }

# Run the Actor and wait for it to finish
run = client.actor("xerophylous_mercy_0wn/feed-contract-monitor").call(run_input=run_input)

# Fetch and print Actor results from the run's dataset (if there are any)
print("💾 Check your data here: https://console.apify.com/storage/datasets/" + run["defaultDatasetId"])
for item in client.dataset(run["defaultDatasetId"]).iterate_items():
    print(item)

# 📚 Want to learn more 📖? Go to → https://docs.apify.com/api/client/python/docs/quick-start

```

## CLI example

```bash
echo '{
  "feedUrls": [
    "https://www.nasa.gov/feed/"
  ]
}' |
apify call xerophylous_mercy_0wn/feed-contract-monitor --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "command": "npx",
            "args": [
                "mcp-remote",
                "https://mcp.apify.com/?tools=xerophylous_mercy_0wn/feed-contract-monitor",
                "--header",
                "Authorization: Bearer <YOUR_API_TOKEN>"
            ]
        }
    }
}

```

## OpenAPI specification

Download the OpenAPI definition: https://api.apify.com/v2/actors/TkDQFXLqy7pMOHBsh/builds/Wq24kBF9YDxVStz8k/openapi.json
