# Podcast RSS Scraper — Episodes, Audio & Transcript Links (`funny_ground/podcast-rss-episodes-scraper`) Actor

Export podcast episodes from public RSS, Atom or Apple Podcasts show URLs: audio links, dates, durations, show notes and published transcript/chapter links. Per-episode fees and separate Apify usage apply.

- **URL**: https://apify.com/funny_ground/podcast-rss-episodes-scraper.md
- **Developed by:** [Coor Yu](https://apify.com/funny_ground) (community)
- **Categories:** Marketing, Developer tools
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $0.50 / 1,000 podcast episodes

This Actor is paid per event and usage. You are charged both the fixed price for specific events and for Apify platform usage.

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

## Podcast RSS Scraper — Episodes, Audio & Transcript Links

Podcast RSS Scraper exports episodes from **public RSS/Atom feeds or Apple Podcasts show URLs**: titles, dates, audio URLs, durations, show notes and published transcript/chapter links. Use it for podcast directories, episode research and content catalogs.

**Metadata and links only—not transcript text.** No media/transcript/chapter downloads or speech-to-text. No publisher login or paid proxy is needed; private/paywalled feeds are unsupported.

### Quick start

1. Replace the demo with your public feed or Apple Podcasts show URL and set a limit.
2. Click **Start**. Open **Episodes** for rows and **Run summary and errors** for diagnostics.
3. Export JSON, CSV or Excel, or read the dataset through the Apify API.

```json
{
  "feedUrls": ["https://feeds.transistor.fm/build-your-saas"],
  "maxEpisodesPerFeed": 10,
  "maxEpisodes": 100,
  "includeDescription": true,
  "sortOrder": "newest"
}
```

`{}` selects the paid Build Your SaaS demo, requesting up to 10 episodes. **10 saved episodes = $0.005 in event fees, plus Apify usage**. Results/tags depend on the current feed; no affiliation with sample publishers is implied.

#### Apple Podcasts show input

```json
{
  "feedUrls": ["https://podcasts.apple.com/us/podcast/planet-money/id290783428"],
  "maxEpisodesPerFeed": 5
}
```

Apple Podcasts/iTunes links resolve via Apple's public lookup API. Apple episode links select the **show's feed**, not one episode. Ordinary websites, Spotify and YouTube are unsupported inputs; no show search or website feed discovery is performed.

#### Date and keyword filtering

```json
{
  "feedUrls": ["https://feeds.twit.tv/sn.xml"],
  "publishedAfter": "2026-01-01",
  "keywords": ["security", "privacy"],
  "maxEpisodesPerFeed": 20,
  "sortOrder": "newest"
}
```

Dates are inclusive **UTC calendar dates**; unknown dates are excluded when either bound is set. Any keyword can match a case-insensitive substring in the title or included notes. `includeDescription: false` searches titles only. Notes are truncated before matching.

Filters/sorting run **before** the per-feed limit. Feeds run in input order; sorting is per feed, not global. Unknown dates sort last.

### Input reference

| Field | Default | Purpose |
|---|---|---|
| `feedUrls` | Demo feed | 1–20 absolute public HTTPS RSS, Atom or Apple Podcasts show URLs |
| `maxEpisodesPerFeed` | 10 | Matching episodes per feed, 1–5,000 |
| `maxEpisodes` | 200 | Global saved-episode cap, 1–10,000 |
| `includeDescription` | true | Plain-text show notes, up to 20,000 characters |
| `keywords` | \[] | Up to 20 nonempty keywords, each at most 100 characters; match any |
| `publishedAfter` | unset | Inclusive earliest date, `YYYY-MM-DD` |
| `publishedBefore` | unset | Inclusive latest date, `YYYY-MM-DD` |
| `sortOrder` | `newest` | `newest`, `oldest` or publisher `feed` order |
| `failOnFeedError` | false | Stop and fail at the first feed error |

Duplicate input/final feed URLs are skipped. Within a feed, repeated GUIDs or selected media URLs are deduplicated. Across inputs, identical media URLs or GUID + podcast-website pairs are not saved twice; first-source metadata wins. This cannot identify every possible duplicate. New runs bill saved rows again.

### Output and billing unit

One dataset row is one episode with a title and supported media enclosure. Items missing either are skipped; error and summary objects are not episode rows.

| Fields | Meaning |
|---|---|
| `id`, `guid` | Hash of final feed URL + GUID (or media URL); publisher GUID |
| `podcastTitle`, `podcastAuthor`, `podcastUrl`, `feedUrl` | Show metadata and feed URL |
| `sourceUrl`, `applePodcastId` | Original input and Apple show ID, if applicable |
| `title`, `episodeUrl`, `publishedAt`, `updatedAt` | Title/page; valid dates normalized to ISO timestamps |
| `audioUrl`, `mediaType`, `audioLengthBytes`, `enclosures` | Published media links/types and declared sizes |
| `duration`, `durationSeconds` | Original duration and recognized duration converted to integer seconds |
| `season`, `episodeNumber`, `episodeType`, `explicit` | Publisher episode metadata when available |
| `description`, `descriptionTruncated` | Plain-text notes and truncation indicator |
| `transcriptUrl`, `transcriptLinks`, `chaptersLinks` | First/all published transcript links and external chapter links |
| `imageUrl`, `language`, `categories`, `scrapedAt` | Artwork, show metadata and collection time |

Missing values stay `null` or empty arrays. `audioUrl` prefers audio but can be video. Sizes/durations are publisher-declared, not measured. Linked files/tracking redirects are not checked for playability. IDs can change with the final feed URL or GUID.

`OUTPUT` contains per-feed counts, invalid/duplicate items, warnings, errors and stop reasons. JSON preserves nested arrays; CSV/Excel may stringify them.

### Current pricing

Current USD rates; see the [Pricing tab](https://apify.com/funny_ground/podcast-rss-episodes-scraper/pricing) and run Usage report.

| Charge | Current rate |
|---|---|
| `apify-default-dataset-item` | **$0.0005 per saved episode — $0.50 per 1,000** |
| Actor startup event | **None configured** |
| Published transcript/chapter links and show notes | Included in the episode event |
| Apify compute, transfer and storage | **Billed separately to the running user** at their Apify plan rates |

This is **pay per event + platform usage**, not an all-inclusive total or zero-cost demo. Saved rows are billed automatically, without manual duplicate charges. No paid upstream Actor, browser, proxy or data API is used; Apple inputs use its public lookup.

Duplicates, exclusions and failed/empty sources incur no episode fee, but usage can cost money. Saved rows remain billable after later failure. Event allowance is checked before each source/batch. `maxEpisodes` and the event-charge budget limit episode events, **not platform usage**, and cannot guarantee completeness.

### Limits and reliability

- Public HTTPS/443 only, without URL credentials. No private-feed authentication/cookie/token field. Literal-IP hosts, private/local DNS and unsafe redirects are rejected.
- RSS 2.0/Atom media enclosures, namespace aliases and inherited `xml:base` are supported. Atom text/HTML notes work; embedded XHTML notes are not extracted.
- Invalid XML, HTML pages, custom entities/document types and nonempty feeds without valid enclosures fail. Empty feeds or zero filter matches can succeed without rows.
- Safety limits: 8 MiB decoded per HTTP response, 10,000 source items and 50,000 opening tags per feed, 20 input feeds and 80 total HTTP requests.
- Fixed 256 MB memory; two-minute collection deadline; 180-second default run timeout. No new processing/batch starts after the deadline; in-flight calls may finish later. One HTTP 429/502/503/504 retry, without access-control bypass.
- Source failures normally allow other feeds to continue; all feeds failing fails the run. `failOnFeedError: true` stops at the first error; saved rows stay billable.

Only episodes **currently in the feed** are accessible; publishers may omit older entries. Check `OUTPUT` for limits/errors and follow publisher terms/copyright. No redistribution rights are granted.

### FAQ

**Can I get podcast transcripts?**\
You get published Podcasting 2.0 transcript links when present—not transcript text or generated transcripts. Chapter links likewise require publisher tags.

**Can I retrieve every historical episode?**\
Only feed-visible episodes. `oldest` sorts them; it cannot recover an omitted archive.

### API usage and related Actor

Use `funny_ground/podcast-rss-episodes-scraper` with the same JSON via Apify API/SDK. Read its default dataset and key-value store `OUTPUT`. API calls require your private Apify token.

For website contacts and social links, use [Website Contact & Social Scraper](https://apify.com/funny_ground/website-contact-social-scraper) separately from RSS export.

# Actor input Schema

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

Paste 1–20 public HTTPS feed URLs or Apple Podcasts show links containing id123456. Do not enter ordinary website homepages, private feeds, credentials or access tokens. Apple episode links resolve to the show's feed, not one specific episode. Duplicate feeds/episodes are not billed again within the same run.

## `maxEpisodesPerFeed` (type: `integer`):

Applied after date/keyword filters and sorting. The default 10 episodes cost $0.005 in event fees. Set a higher value for an archive export; only episodes currently present in the publisher's feed are available.

## `maxEpisodes` (type: `integer`):

Global cap after deduplication. Sources are processed in input order. The Actor also respects the event-charge budget, 8 MiB per-feed decoded size limit and two-minute collection deadline. This is an event limit, not a cap on separately billed platform usage.

## `includeDescription` (type: `boolean`):

Include clean descriptions, limited to 20,000 characters per episode. No extra event fee. With this turned off, keywords search episode titles only. The Actor returns transcript links, not transcript text.

## `keywords` (type: `array`):

Case-insensitive substring matching. At least one keyword must occur in the title or included description. Leave empty to return all episodes that match the dates.

## `publishedAfter` (type: `string`):

Optional inclusive UTC date bound. Episodes with no valid publication date are excluded when either date bound is set. Example: 2026-01-01.

## `publishedBefore` (type: `string`):

Optional inclusive UTC date bound. Leave blank for no upper date limit.

## `sortOrder` (type: `string`):

Sort before the per-feed cap. Newest is ideal for recent releases; oldest for feed archive exports. Unknown dates sort last. This does not globally sort episodes across different shows.

## `failOnFeedError` (type: `boolean`):

By default, continue with other feeds and report per-feed errors in OUTPUT. If all feeds fail, the run fails. When enabled, stop at the first feed error; any already saved episodes remain billable and available.

## Actor input object example

```json
{
  "feedUrls": [
    "https://feeds.transistor.fm/build-your-saas"
  ],
  "maxEpisodesPerFeed": 10,
  "maxEpisodes": 200,
  "includeDescription": true,
  "keywords": [],
  "sortOrder": "newest",
  "failOnFeedError": false
}
```

# Actor output Schema

## `episodes` (type: `string`):

Unique podcast episodes with dates, durations, audio URLs and publisher-provided transcript links. Export JSON, CSV or Excel.

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

Per-feed status, counts, invalid/duplicate items, limits and errors. This summary is not billed as an episode.

# 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://feeds.transistor.fm/build-your-saas"
    ],
    "maxEpisodesPerFeed": 10,
    "maxEpisodes": 200,
    "includeDescription": true,
    "keywords": [],
    "sortOrder": "newest",
    "failOnFeedError": false
};

// Run the Actor and wait for it to finish
const run = await client.actor("funny_ground/podcast-rss-episodes-scraper").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://feeds.transistor.fm/build-your-saas"],
    "maxEpisodesPerFeed": 10,
    "maxEpisodes": 200,
    "includeDescription": True,
    "keywords": [],
    "sortOrder": "newest",
    "failOnFeedError": False,
}

# Run the Actor and wait for it to finish
run = client.actor("funny_ground/podcast-rss-episodes-scraper").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 '{
  "feedUrls": [
    "https://feeds.transistor.fm/build-your-saas"
  ],
  "maxEpisodesPerFeed": 10,
  "maxEpisodes": 200,
  "includeDescription": true,
  "keywords": [],
  "sortOrder": "newest",
  "failOnFeedError": false
}' |
apify call funny_ground/podcast-rss-episodes-scraper --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,funny_ground/podcast-rss-episodes-scraper"
        }
    }
}
```

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/ghSham4ERGqeuOcMf/builds/SkO8BV7pPwhl3CFaL/openapi.json
