Podcast Transcripts Scraper avatar

Podcast Transcripts Scraper

Pricing

from $2.88 / 1,000 transcribed audio minutes

Go to Apify Store
Podcast Transcripts Scraper

Podcast Transcripts Scraper

Discover new episodes from public podcast RSS feeds and export searchable transcripts, timestamped segments and SRT/VTT subtitles with bounded local speech recognition.

Pricing

from $2.88 / 1,000 transcribed audio minutes

Rating

0.0

(0)

Developer

Automation Lab

Automation Lab

Maintained by Community

Actor stats

0

Bookmarked

2

Total users

1

Monthly active users

22 days ago

Last modified

Categories

Share

Turn the newest episodes in public RSS feeds into searchable podcast transcripts. Supply the feeds once instead of enumerating audio URLs: receive episode metadata, plain text, timestamped segments, and optional SRT/VTT subtitle files.

Built for researchers indexing recurring shows, editorial teams searching interviews, and knowledge pipelines collecting newly published speech. Recognition runs locally on CPU using Whisper tiny; no transcription API key is required.

What it does

  1. Downloads public RSS 2.0 feeds with audio enclosures.
  2. Applies an optional publication cutoff and previously indexed GUID exclusions.
  3. Selects the newest eligible episodes, deduplicating GUIDs and audio URLs.
  4. Downloads bounded audio, checks duration, and transcribes without clipping.
  5. Saves one episode record and optional subtitle artifacts in run storage.

This is not a podcast search engine. It does not resolve Apple Podcasts or Spotify landing pages, authenticate to private feeds, or fetch an entire historical archive.

Who is it for?

Research teams building a public-interview corpus, editors reviewing recent show episodes, and data engineers maintaining searchable episode indexes. It is not suitable for confidential recordings or a verbatim legal transcript.

Why use it?

A direct-media transcriber needs individual file URLs. This Actor discovers those URLs from your feeds and preserves the episode identity alongside each transcript. Date and GUID filters make recurring indexing explicit and reproducible without hidden cross-run state.

Outputs are machine-readable and can be joined to your own episode index. Speech recognition is approximate: manually verify quotations, names, numbers, and consequential interpretations.

Getting started

  1. Copy the public RSS feed URL from the show's publisher.
  2. Start with one episode and a duration bound suitable for the show.
  3. Run the Actor and open Episode transcripts in the output tab.
  4. Download subtitles from the links in subtitleUrls.
  5. Save successful GUIDs externally for the next indexing run.
{
"feedUrls": ["https://feeds.npr.org/500005/podcast.xml"],
"maxItems": 1,
"episodesPerFeed": 1,
"maxDurationMinutes": 10,
"language": "en",
"outputFormats": ["srt", "vtt"]
}

The example uses a public, frequently updated short news feed; episode identity changes over time.

Inputs

FieldDefaultBehavior
feedUrlsRequired1–5 public RSS 2.0 URLs; strings, no credentials or query strings
maxItems1Global selected episode cap, 1–10
episodesPerFeed1Eligible newest episodes selected per feed, 1–10
publishedAfterUnsetStrictly later than a UTC ISO timestamp ending in Z
excludeGuids[]Exact, case-sensitive GUID exclusions, up to 1000
maxFileSizeMb50Hard per-audio bound, 1–100 MiB
maxDurationMinutes10Hard per-episode duration bound, 1–30 minutes
languageautoAutomatic detection or a supported two-letter Whisper code
outputFormats["srt","vtt"]Either/both formats; [] disables artifacts

Feed downloads are capped at 2 MiB. Only audio/* enclosures are selected. Missing GUIDs use the enclosure URL. Duplicate feeds are removed.

Selection and recurring indexing

Filters apply before per-feed limits. Entries are newest-first by RSS publication date; undated entries follow dated entries in feed order. With publishedAfter, undated entries are excluded. The cutoff is strictly greater than, not equal to, the supplied timestamp.

Per-feed selections are combined, deduplicated by GUID and enclosure URL, sorted newest-first across all feeds, then capped by maxItems. Failed episodes consume a selected slot; the Actor does not silently substitute older episodes. GUID collisions across shows are deduplicated too.

The Actor saves no cross-run cursor. Store successful GUIDs and a publication watermark in your own database. On the next run pass them back as exclusions/cutoff. Feeds may remove old entries; increasing limits does not recover an archive. There are no built-in change alerts.

Output data

FieldMeaning
feedUrl, showTitleFeed identity and RSS channel title
guid, episodeTitle, episodeUrlEpisode identity, title and optional page link
publishedAt, audioUrlISO publication date (nullable) and public audio enclosure URL
statussucceeded or failed
transcriptRecognized plain text; null on failure
segments{id,start,end,text} records; times in seconds
language, languageProbabilityRecognition language and confidence; null on failure
durationSeconds, modelDecoded duration and tiny model
subtitleUrlsRequested format download links; empty when disabled/failed
processedAt, errorProcessing timestamp and safe error explanation

A successful local NPR episode produced the opening text “This is NPR News Now. The latest headlines every hour.”, with segment 0 covering 0–4.44 seconds. Later recognition included errors in names, illustrating why tiny-model output needs review. Dataset records contain the full episode transcript rather than just this excerpt.

{
"showTitle": "NPR News Now",
"status": "succeeded",
"model": "tiny",
"language": "en",
"segments": [{"id": 0, "start": 0, "end": 4.44, "text": "This is NPR News Now."}]
}

This is an excerpt, not a complete output record. Dataset exports support JSON, CSV and other Apify formats. Keep nested segments in JSON when you need timestamps.

Subtitle artifacts

SRT and VTT files use the recognized segment timing. Keys follow EPISODE_001.SRT and EPISODE_001.VTT; links are returned in each successful record. Files live in the run's default key-value store. Download before your storage retention period expires. There is no separate subtitle event charge.

How much does it cost to transcribe podcast episodes?

Pay-per-event pricing consists of a $0.005 start fee, charged once for the first successfully recognized episode, plus rounded-up decoded audio minutes. Each episode rounds separately; 61 seconds counts as two minutes. Download/recognition failures, silent audio and oversized episodes have no audio-minute charge. Required charges are verified before transcript or subtitle output is exposed. A billing or subsequent storage failure is fatal; a storage failure can leave charges for recognized audio without a complete dataset row. Inspect the failed run before retrying.

BRONZE price: $0.0048 per audio minute. A five-minute episode costs approximately $0.029 including the start event; ten minutes costs $0.053. Each episode rounds independently.

Spend tierPrice per audio minute
FREE$0.00552
BRONZE$0.0048
SILVER$0.003744
GOLD$0.00288
PLATINUM$0.00288
DIAMOND$0.00288

Spend tiers reflect qualifying aggregate monthly Apify Store spend, not private per-Actor volume discounts. Prices are estimates, not a guaranteed invoice; the applicable live tier and maximum-charge budget govern the run. Storage/platform terms also apply. Refunds, disputes, fraud, taxes, corrections, and contractual clawbacks can affect finalized revenue or payouts.

A maximum-charge budget can stop output before ASR for the next complete episode if its combined start (when needed) and full minute charge cannot be covered; the final log explicitly says budget-limited and any returned dataset is partial. Avoid setting a budget too small for the requested duration.

Limits and failure behavior

Audio is processed sequentially in bounded 60-second recognition chunks with episode-wide timestamps. A chunk boundary can split a phrase; the text remains approximate. Automatic language detection uses the first chunk with recognized speech and reuses that language for the episode. Downloads are bounded by bytes and a two-minute deadline across redirects. Recognition has a per-file timeout. There is no proxy or browser fallback and no automatic retry loop; retry a transient source failure in a new authorized run.

Over-duration or unknown-duration files fail, rather than returning a silently clipped transcript. Bad feeds fail discovery. Episode failures create uncharged error records and mark the run FAILED after preserving any successful transcripts. Billing or output-storage errors are fatal. A failed run can contain useful partial results: inspect status, never assume full completion.

Integrations

  • Research index: upsert successful records keyed by feed URL plus GUID; index transcript text and retain segments for playback citations.
  • Editorial workflow: export JSON to a review queue, download SRT/VTT, and manually correct quotations.
  • Scheduled collection: use Apify schedules with your own watermark/GUID state. Schedules do not automatically update input state.
  • Data pipelines: use a completion webhook to fetch the dataset and send it to your warehouse or search engine. Handle failed runs as partial.

API usage

Start a run asynchronously and keep the returned run ID:

curl -X POST 'https://api.apify.com/v2/acts/automation-lab~podcast-feed-episode-transcripts/runs' \
-H "Authorization: Bearer $APIFY_TOKEN" -H 'Content-Type: application/json' \
-d '{"feedUrls":["https://feeds.npr.org/500005/podcast.xml"],"maxItems":1}'

JavaScript with the Apify client:

import { ApifyClient } from 'apify-client';
const client = new ApifyClient({ token: process.env.APIFY_TOKEN });
const run = await client.actor('automation-lab/podcast-feed-episode-transcripts')
.call({ feedUrls: ['https://feeds.npr.org/500005/podcast.xml'], maxItems: 1 });
const result = await client.dataset(run.defaultDatasetId).listItems({ limit: 10 });
console.log(run.status, result.items);

Python:

import os
from apify_client import ApifyClient
client = ApifyClient(os.environ['APIFY_TOKEN'])
run = client.actor('automation-lab/podcast-feed-episode-transcripts').call(
run_input={'feedUrls': ['https://feeds.npr.org/500005/podcast.xml'], 'maxItems': 1})
rows = client.dataset(run['defaultDatasetId']).list_items(limit=10).items
print(run['status'], rows)

MCP usage

Select this stable Actor subset:

claude mcp add --transport http apify \
"https://mcp.apify.com?tools=automation-lab/podcast-feed-episode-transcripts"

Equivalent Claude Desktop, Cursor, and VS Code setup configuration (use each client's supported HTTP MCP configuration):

{"mcpServers":{"apify":{"url":"https://mcp.apify.com?tools=automation-lab/podcast-feed-episode-transcripts"}}}

Discover actual names and argument schemas with scoped tools/list. Actor selection also includes get-actor-run, get-dataset-items, get-key-value-store-record, and abort-actor-run; discovery alone does not authorize a run or abort.

Example prompt: “Transcribe the newest episode from this public RSS feed, then give me the transcript and subtitle links. Show any recognition uncertainty.”

For an authorized invocation, start once and retain the run/storage IDs; they are metadata, not results. call-actor waits at most 45 seconds (default 30). If nonterminal, check the same run with 2/4/8-second backoff capped at 10 seconds and a 120-second consumer deadline. Client timeout should exceed server wait plus transport margin. On timeout recover the known run, never restart merely to poll. At the deadline report pending with its ID.

Report terminal failures honestly: any available rows are partial, not a successful full result. Once successful, call the discovered get-dataset-items helper with explicit limit, offset, and fields (a comma-separated string). For example:

{"datasetId":"<defaultDatasetId from the same run>","limit":20,"offset":0,"fields":"guid,showTitle,episodeTitle,publishedAt,status,transcript,subtitleUrls,error"}

Request segments only when timestamps are needed. Fetch pages of 20 source rows from offset 0, at most 100 rows and 64 KiB of serialized UTF-8 data admitted to model context, whichever comes first. Process pages host-side; omit/summarize an oversized row with disclosure. If your client cannot intercept oversized responses, do not claim a hard byte ceiling. Track source offsets; report partial/truncated status and continuation offset. Keep full transcripts in storage outside model context when needed. Discovery transport and caching do not guarantee token savings.

AI and data handling

Whisper tiny via faster-whisper/CT2 runs on the Actor's CPU, with int8 inference. No media or transcript is sent to an external transcription/LLM provider, no model training occurs, and no diarization, translation or professional-grade accuracy is promised. Model weights are fetched during image construction, not from customer audio. Different languages, accents, music, crosstalk and noise can reduce accuracy.

Feed metadata, public audio URLs, recognized speech and subtitles are stored in your Apify run storage. Audio/WAV working files are deleted in normal cleanup; abrupt termination relies on container disposal. Output links follow Apify storage access rules; share them only deliberately. Apify retention depends on your account/settings; delete datasets, key-value records and logs through your account when no longer needed. We do not maintain an additional transcript archive.

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. Do not submit secrets, private feed tokens or confidential audio. Public enclosures may contain publisher tracking query parameters and remain visible in your output URL.

Legality and responsible use

Use only publicly available feeds/audio you are authorized to process. Public availability does not grant redistribution rights. Respect copyright, personal-data obligations and publisher terms; avoid sensitive recordings. Human review is required before consequential use. This Actor is independent of podcast publishers, NPR, Apple, Spotify and Apify; no affiliation or endorsement is implied. Apify's standard user terms apply.

FAQ and troubleshooting

Can I paste a show page? No. Obtain the publisher's public RSS URL. Query-bearing feed URLs and credentials are rejected to reduce private-feed risk; this can also exclude some legitimate public feeds.

Why is the result empty? The feed may have no audio enclosures, the cutoff/exclusions may remove all entries, or your charge budget may be insufficient. Legitimately empty discovery is successful and uncharged.

Why did a long episode fail? Set the duration cap appropriately, up to 30 minutes. Longer episodes are outside the supported contract; the Actor never clips them silently.

Can it identify speakers or search across all podcasts? No. Use your downstream index for search; speaker diarization and podcast-directory discovery are not included.

How do I report a problem? Open an issue in this Actor's Apify Issues tab. Share the run ID and non-sensitive reproduction input, not secrets or private recordings.