# Sitemap & RSS to JSON — URL inventory and feed items (`opencrawl/sitemap-rss-to-json`) Actor

Turn sitemap.xml or any RSS/Atom feed into clean JSON. Point it at a site: it finds the sitemap via robots.txt, follows sitemap indexes, and returns one item per URL with lastmod and priority. Point it at a feed: normalised entries with titles, links, dates and authors.

- **URL**: https://apify.com/opencrawl/sitemap-rss-to-json.md
- **Developed by:** [Andy Wang](https://apify.com/opencrawl) (community)
- **Categories:** SEO tools, Developer tools, News
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

$1.00 / 1,000 urls

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/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

## Sitemap & RSS to JSON — URL inventory and feed items

Point it at a website and get its **whole URL inventory** as JSON. Point it at a
feed and get **normalised RSS/Atom items**. No proxies, no browser, pay per URL.

This is the unglamorous part of SEO, RAG ingestion and content monitoring: finding
out what a site publishes, when each page changed, and what its feed says. Most
scrapers skip sitemaps entirely and miss pages that are never linked.

### What you get

For a site:

```json
{ "source": "https://example.com/sitemap.xml",
  "url": "https://example.com/pricing",
  "lastmod": "2026-10-01", "changefreq": "weekly", "priority": "0.8" }
```

For a feed:

```json
{ "source": "https://example.com/feed", "kind": "feed-item",
  "title": "First post", "link": "https://example.com/1", "id": "g1",
  "published": "Mon, 19 Oct 2026 10:00:00 GMT",
  "summary": "Plain-text summary, HTML stripped", "author": null, "categories": ["news"] }
```

### How it finds the sitemap

1. Reads `/robots.txt` and uses every `Sitemap:` directive — the polite way, and
   the only way to find sitemaps that are not at the default path.
2. Falls back to `/sitemap.xml` if robots.txt lists none.
3. Follows a `<sitemapindex>` one level deep (configurable) and merges children.

### Input

| Field | Default | What it does |
|---|---|---|
| `startUrls` | — | A site URL, a sitemap URL, or an RSS/Atom URL. Mixed lists are fine |
| `maxUrls` | `1000` | Hard cap on emitted items (max 20,000) |
| `followSitemapIndex` | `true` | Fetch child sitemaps of an index |
| `tryDefaultSitemap` | `true` | Fall back to `/sitemap.xml` |

### Notes and limits

- **Sitemaps only list what the site declares.** Pages behind a sitemap you cannot
  reach (404, auth, robots-blocked) come back as an error item with the status code.
- One level of sitemap index nesting; deeper trees need a second run.
- No JavaScript execution — feeds and sitemaps are XML, so this is not a problem in
  practice.
- Respects `robots.txt` for discovery, sends a descriptive user-agent, and never
  hammers a host: requests are sequential per source.

### Pricing

One charge per emitted URL or feed item. A 5,000-page site costs a few dollars; a
single feed costs a fraction of a cent.

# Actor input Schema

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

A site (we discover its sitemap) or a direct sitemap.xml / RSS / Atom URL.

## `maxUrls` (type: `integer`):

Hard cap on emitted items per run (1–20000).

## `followSitemapIndex` (type: `boolean`):

When a sitemap index is found, fetch its child sitemaps one level deep.

## `tryDefaultSitemap` (type: `boolean`):

Fall back to /sitemap.xml if robots.txt lists no sitemaps.

## Actor input object example

```json
{
  "startUrls": [
    "https://example.com"
  ],
  "maxUrls": 1000,
  "followSitemapIndex": true,
  "tryDefaultSitemap": true
}
```

# Actor output Schema

## `items` (type: `string`):

Sitemap URLs with lastmod, changefreq and priority, or normalised feed entries with title, link, published date, author and categories. A URL that could not be parsed carries an error field instead.

# 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": [
        "https://example.com"
    ]
};

// Run the Actor and wait for it to finish
const run = await client.actor("opencrawl/sitemap-rss-to-json").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": ["https://example.com"] }

# Run the Actor and wait for it to finish
run = client.actor("opencrawl/sitemap-rss-to-json").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": [
    "https://example.com"
  ]
}' |
apify call opencrawl/sitemap-rss-to-json --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,opencrawl/sitemap-rss-to-json"
        }
    }
}
```

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/ba6xqzHgmaujv5JjM/builds/JB2skBpRQBanO5NL8/openapi.json
