# Website RSS & Atom Feed Finder (`automation-lab/website-rss-feed-finder`) Actor

Find and validate public RSS, Atom and JSON Feed endpoints from website URLs. Export feed URLs, titles, entry counts and per-website status for ingestion setup.

- **URL**: https://apify.com/automation-lab/website-rss-feed-finder.md
- **Developed by:** [Automation Lab](https://apify.com/automation-lab) (community)
- **Categories:** Developer tools
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $0.81 / 1,000 website with validated feeds

This Actor is paid per event. You are not charged for the Apify platform usage, but only a fixed price for specific events.
Since this Actor supports Apify Store discounts, the price gets lower the higher subscription plan you have.

Learn more: https://docs.apify.com/actors/running/actors-in-store.md#pay-per-event

## What's an Apify Actor?

An Actor is a serverless cloud program that runs on the Apify platform. It has two run modes.
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.

Apify vocabulary and the platform model are defined once, in the agent quickstart at https://apify.com/agents.md.

## 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.

Do not guess an integration path. Every one of them is in the agent quickstart at https://apify.com/agents.md: the Apify MCP server, Agent Skills with the Apify CLI, the JavaScript and Python clients, the REST API, and the account-free path for an agent with no human to sign in. It also carries the rule on stating cost before the first paid run.

For examples already wired to this Actor's own input schema, see the [API](#api) section below.

Each client library has reference documentation the quickstart does not restate: [JavaScript/TypeScript](https://docs.apify.com/api/client/js/docs.md) (`npm install apify-client`) and [Python](https://docs.apify.com/api/client/python/docs.md) (`pip install apify-client`).

# README

## Website RSS & Atom Feed Finder

Resolve a public RSS website into validated RSS, Atom or JSON Feed endpoints. Supply website URLs and receive feed URLs, format, title, current entry count and per-input status. Use this endpoint inventory to set up ingestion pipelines—not to create feeds or download article bodies.

### Who is it for?

Research teams assembling source lists, content operations configuring readers, and developers maintaining ingestion jobs can reuse the same website list on scheduled runs. Results identify working endpoints and distinguish inaccessible sites from tested sites without feeds.

### Why use it?

A URL containing `rss` is not necessarily a feed. This Actor downloads each candidate and parses the document before accepting it. It follows redirects, resolves relative links, deduplicates final endpoints within each website, and exports source-attributed records. Empty but valid feeds are accepted with a zero entry count.

### Getting started

1. Open the Actor input editor.
2. Add one or more public website or direct feed URLs.
3. Leave the discovery limits at their defaults, or lower them for a quick lookup.
4. Run and open the dataset.
5. Filter `status=found` to obtain usable feed URLs.
6. Review error/status rows before adding the sources to your reader.

Example input:

```json
{
  "startUrls": [{"url": "https://www.nasa.gov/"}],
  "maxFeedsPerWebsite": 5,
  "maxCandidatesPerWebsite": 12,
  "probeCommonPaths": true
}
```

### Input parameters

| Field | Default | Behavior |
| --- | --- | --- |
| `startUrls` | Required | 1–100 public HTTP(S) website or direct feed URLs; URL strings or objects with `url` |
| `maxFeedsPerWebsite` | 5 | 1–10 distinct validated final feed URLs per supplied entry |
| `maxCandidatesPerWebsite` | 12 | 1–20 candidate fetches per website, excluding the initial page |
| `probeCommonPaths` | true | Try conventional paths after advertised links; shares the candidate limit |

Only GET requests are supported. Request-list objects may contain `url` and `method="GET"`; custom headers, payload and userData are rejected even if your editor or hosted MCP offers those generic request-list options.

Duplicate supplied inputs are checked separately and can each incur a successful-website event. There is no unlimited mode. Direct feed input returns one feed without common-path probing. Query parameters are preserved when fetching public URLs; avoid supplying secrets.

### How discovery works

First the initial URL is tested as a feed. Otherwise, an HTML document is inspected for alternate RSS/Atom/JSON links, HTTP `Link` headers, and anchors whose URLs resemble feed paths. Relative links honor a valid HTML base URL. Common-path discovery tries `feed/`, `rss.xml`, `atom.xml`, `feed.xml`, `feed.json` and `rss/` at the page directory and site root.

Candidates are visited in that order. Final URLs after redirects are deduplicated within each input. A feed shared by different supplied websites remains attributed to each website. Discovery does not recursively crawl internal pages, render JavaScript, log in or solve bot challenges.

### Output fields

Each validated feed produces one dataset row. If an input has no validated feed, it produces one uncharged status-only row with null feed fields.

| Field | Meaning |
| --- | --- |
| `inputUrl` | Normalized supplied URL |
| `siteUrl` | Final initial-page URL, null if unavailable |
| `feedUrl` | Final validated endpoint, null for status-only rows |
| `format` | `rss`, `atom`, `json`, or null |
| `title` | Feed title, up to 500 characters; nullable |
| `recordCount` | Entries in this downloaded feed document; nullable |
| `status` | `found`, `not_found`, or `error` |
| `httpStatus` | Feed response status for found rows; initial-page status otherwise |
| `discoveryMethod` | `direct`, `html_link`, `http_link`, `anchor`, `common_path`, or null |
| `candidatesChecked` | Candidate URLs attempted for the input; direct feed counts as one |
| `truncated` | Some candidates were not tested because a cap was reached |
| `error` | Bounded error code, or null |
| `checkedAt` | UTC check-start timestamp |
| `billingUnit` | True on first validated feed row per input; false on included additional feeds and status-only rows |

`recordCount` is not the site's total historical article count, subscriber count or count of new posts. No article records are exported.

### Output example

A representative NASA check returned this RSS endpoint and ten entries. Entry counts can change as publishers update their feeds.

```json
{
  "inputUrl": "https://www.nasa.gov/",
  "siteUrl": "https://www.nasa.gov/",
  "feedUrl": "https://www.nasa.gov/feed/",
  "format": "rss",
  "title": "NASA",
  "recordCount": 10,
  "status": "found",
  "httpStatus": 200,
  "discoveryMethod": "html_link",
  "candidatesChecked": 1,
  "truncated": true,
  "error": null,
  "billingUnit": true,
  "checkedAt": "2026-10-10T14:07:34.415Z"
}
```

This example used a one-feed cap; `truncated=true` means other candidates remained untested, not that the accepted feed was invalid.

### How much does it cost to find feeds on websites?

Pay-per-event pricing consists of one `start` event per valid run and one `item` event per supplied website with at least one validated feed. Additional feeds from that same input have no separate event charge. No-feed/error status rows are free of item charges; the start charge still applies. Apify platform usage may be charged separately according to your plan.

The start event is $0.0001. Successful-website unit prices by Apify Store spend tier are FREE $0.0015502, BRONZE $0.001348, SILVER $0.0010514, and GOLD/PLATINUM/DIAMOND $0.0008088. Tiers depend on qualifying aggregate monthly Store spend, not volume in this Actor. At BRONZE, illustrative totals are 1 × $0.001348 + $0.0001, 10 × $0.001348 + $0.0001, or 100 × $0.001348 + $0.0001. These are Actor-event estimates, not a platform-usage estimate.

Set a maximum total charge in Apify to control event spending. At that limit the Actor stops collection rather than emitting uncharged useful output, so later inputs may be absent. Downloaded source entry counts do not affect event pricing.

### Limits and errors

Each response is capped at 2 MiB. A request has at most five redirects, two attempts for transient network/429/5xx failures, a ten-second attempt timeout and a fifteen-second total request budget. Stable 4xx errors are not retried. Candidate scheduling stops after thirty seconds per website or 240 seconds per run; an already-running request may finish after that boundary. Remaining inputs receive `runtime_budget` status rows unless a billing cap stops the run first.

`not_found` only means no feed was validated in the tested scope; it does not prove the site publishes none. `truncated` flags untested candidates. `error` identifies unreachable pages, unsupported documents or incomplete candidate requests. If every supplied website errors, the run fails and retains its status rows. Mixed batches can succeed with errors; always inspect statuses.

Only anonymously reachable public websites are supported. Private/loopback/link-local addresses, embedded credentials and nonstandard ports are rejected, including redirect targets. DNS resolution is checked and pinned. DTDs and custom entity declarations are rejected; predefined and numeric XML entities in titles are safely decoded. Supported XML formats are RSS 2.0, RSS 1.0 with the RDF/RSS namespaces, and Atom with the Atom namespace. Non-UTF-8 or compressed responses that ignore normal uncompressed requests may not parse.

### Integrations

Export JSON or CSV from the dataset to feed readers, spreadsheet source inventories or ingestion services. Use `feedUrl` as a stable lookup key and retain `inputUrl` for provenance. A scheduled repeat run can reveal changed endpoints by comparing inventories downstream; this Actor itself has no history, diffing or notification state.

In Make or n8n, run this Actor, filter found rows, then hand endpoints to your feed ingestion step. Keep error rows in a review queue rather than deleting those sources automatically. Multiple feed rows from one website represent one successful lookup for billing.

### API use

Start a run and retain its run/storage IDs. Poll the same run until terminal, then read its dataset. Never restart merely because a client request timed out.

```bash
curl -X POST 'https://api.apify.com/v2/acts/automation-lab~website-rss-feed-finder/runs' \
  -H "Authorization: Bearer $APIFY_TOKEN" \
  -H 'Content-Type: application/json' \
  -d '{"startUrls":[{"url":"https://www.nasa.gov/"}]}'
```

JavaScript with the Apify client:

```javascript
import { ApifyClient } from 'apify-client';
const client = new ApifyClient({ token: process.env.APIFY_TOKEN });
const run = await client.actor('automation-lab/website-rss-feed-finder').call({
  startUrls: [{ url: 'https://www.nasa.gov/' }]
});
const page = await client.dataset(run.defaultDatasetId).listItems({ limit: 20 });
console.log(page.items);
```

Python:

```python
import os
from apify_client import ApifyClient
client = ApifyClient(os.environ['APIFY_TOKEN'])
run = client.actor('automation-lab/website-rss-feed-finder').call(
    run_input={'startUrls': [{'url': 'https://www.nasa.gov/'}]})
print(client.dataset(run['defaultDatasetId']).list_items(limit=20).items)
```

### MCP use

For authorized client use, select this stable Actor subset:

```bash
claude mcp add --transport http apify \
  'https://mcp.apify.com?tools=automation-lab/website-rss-feed-finder'
```

Equivalent Claude Desktop, Cursor and VS Code editor configuration:

```json
{"mcpServers":{"apify":{"url":"https://mcp.apify.com?tools=automation-lab/website-rss-feed-finder"}}}
```

Configure Apify authentication in your client. Discover actual tool names and input schemas with scoped `tools/list`; Actor selection also exposes run/dataset/KV/abort helpers, not exactly one tool. Example prompt: “Find the public RSS, Atom or JSON feeds for these websites, show statuses and validated endpoint URLs.”

Start once and retain the run ID. `call-actor` waits at most 45 seconds; if pending, check that same run with bounded backoff (2, 4, 8 seconds, capped at 10) and a 120-second consumer deadline. Set the client timeout longer than the selected wait plus transport margin. At deadline, report pending and the run ID rather than starting again.

Report terminal failures honestly: any available dataset rows are partial results, not a successful full inventory. On success, call `get-dataset-items` for the same returned `defaultDatasetId`, initially with `offset=0`, `limit=20`, and the needed `fields` projection (for example `inputUrl,feedUrl,format,title,recordCount,status,error,truncated,billingUnit`), using the argument shape from `tools/list`. Read at most 100 source rows and 64 KiB of serialized UTF-8 content admitted to model context across all pages, whichever comes first. Enforce byte limits host-side before model injection; omit or summarize oversized rows with disclosure. If your client cannot intercept oversized replies, do not claim a hard byte guarantee. Track source offsets and report partial/truncated results and the continuation offset. Keep full downloads downstream, outside model context. These consumer limits do not change Actor collection limits.

### Legality and privacy

Use only public URLs you are permitted to request. Respect publisher terms, applicable law and reasonable scheduling intervals. Public availability does not grant copyright or redistribution rights. Avoid placing tokens or private identities in URLs.

No AI model processes your input or source data in this Actor. There are no paid APIs or proxies. Results and logs use your Apify storage retention settings; delete the run and its storages in Console or via the API when no longer needed. There is no persistent source cache. For support, use the Actor's Store Issues tab.

Failed operations send sanitized diagnostic input, exceptions and Actor/build/run IDs to our private GlitchTip service for repair. Secret fields and URL queries are removed, and reports are retained for 30 days. Dataset output preserves supplied/public endpoint URLs for your use; treat your own exports appropriately.

### FAQ and troubleshooting

**Why does a website have no feed?** It may not advertise one, its path may not be among the bounded guesses, or feeds may be on another page. Try a blog URL or a known feed URL and review `truncated`.

**Does this create an RSS feed?** No. It discovers and validates existing published feeds.

**Can I read the articles?** No. This product exports endpoint metadata and current entry counts. Use a feed reader downstream.

**Why does a run fail even with dataset rows?** If every website errors, the status rows are diagnostic results, not useful feeds. Fix URLs or inaccessible sources; do not treat the run as a successful full inventory.

**Are empty feeds rejected?** No. A valid empty feed has `recordCount=0` and is usable as an endpoint.

**Can I use proxy credentials or cookies?** No. This version intentionally has no proxy, login or browser route.

### Related Actors

For a source-specific article feed workflow, see [Product Hunt Launch Feed Scraper](https://apify.com/automation-lab/product-hunt-launch-feed-scraper). This Actor's endpoint inventory is complementary: discovery comes before choosing an appropriate reader or source-specific extractor.

This utility is not affiliated with or endorsed by source publishers or Apify.

# Changelog

This Actor's version history is a separate document: https://apify.com/automation-lab/website-rss-feed-finder/changelog.md

# Actor input Schema

## `startUrls` (type: `array`):

Provide 1–100 public HTTP(S) websites or direct RSS, Atom or JSON Feed URLs. Only GET requests are supported. Object entries may contain url and method=GET; headers, payload and userData are rejected. Each entry is processed separately; duplicate inputs are not removed. Private networks, credentials in URLs and nonstandard ports are rejected.

## `maxFeedsPerWebsite` (type: `integer`):

Stop after this many distinct validated final feed URLs for each input website. Default 5; range 1–10. Redirect aliases are deduplicated within each website, not across inputs. A direct feed returns one row.

## `maxCandidatesPerWebsite` (type: `integer`):

Validate at most this many candidate URLs per website, excluding the initial page. Default 12; range 1–20. HTML alternate links, HTTP Link headers, feed-like anchors and common paths are tried in that order. Caps may leave feeds undiscovered; truncated marks untested candidates.

## `probeCommonPaths` (type: `boolean`):

After advertised links, try feed/, rss.xml, atom.xml, feed.xml, feed.json and rss/ at the page directory and origin root. These probes share the candidate limit. Disable to validate advertised feeds only. Does not affect direct-feed input.

## Actor input object example

```json
{
  "startUrls": [
    {
      "url": "https://www.nasa.gov/"
    }
  ],
  "maxFeedsPerWebsite": 5,
  "maxCandidatesPerWebsite": 12,
  "probeCommonPaths": true
}
```

# Actor output Schema

## `dataset` (type: `string`):

Validated feed rows or one status-only row when a website has no validated feed.

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

// Run the Actor and wait for it to finish
const run = await client.actor("automation-lab/website-rss-feed-finder").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 = { "startUrls": [{ "url": "https://www.nasa.gov/" }] }

# Run the Actor and wait for it to finish
run = client.actor("automation-lab/website-rss-feed-finder").call(run_input=run_input)

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

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

```

## CLI example

```bash
echo '{
  "startUrls": [
    {
      "url": "https://www.nasa.gov/"
    }
  ]
}' |
apify call automation-lab/website-rss-feed-finder --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,automation-lab/website-rss-feed-finder"
        }
    }
}
```

The hosted server signs you in with OAuth on first connect, so no API token belongs in this config. Clients without OAuth support can send an `Authorization: Bearer <APIFY_API_TOKEN>` header instead, using a token from API & Integrations in Apify Console (https://console.apify.com/settings/integrations).

## OpenAPI specification

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