SFOLN

Catalogue / Documents & media

Podcast Scraper – Episodes & Transcripts

sfoln/podcast-scraper · AI, News, Automation On request

Get any podcast's episodes as JSON from its name, Apple Podcasts link or RSS feed: titles, dates, durations, audio URLs, show notes, episode and season numbers, plus a show profile with release cadence. Optional AI transcripts. $1 per 1,000 episodes.

About

What it does

Get any podcast's episodes as clean JSON from its name, an Apple Podcasts link or its RSS feed. For every show you get one row per episode (title, publication date, duration, audio file URL, show notes as text, the links in them, episode and season numbers, episode type, explicit flag, GUID) and one show profile with the owner's published contact, categories and release cadence. Optionally, the newest episodes are transcribed with AI (Mistral Voxtral). Built for podcast research, PR and guest booking, ad sales, media monitoring and AI agents that need what was said on a show. $1 per 1,000 episodes; transcripts $0.0105 per audio minute.

Price

Price per delivered record

EventPricePer 1,000Charged for
Podcast episode
episode
$0.001$1 / 1,000Charged once per podcast episode delivered (title, date, duration, audio URL, show notes, episode and season numbers).
Transcribed audio minute
transcription-minute
paid plans only
$0.0105$10.5 / 1,000Charged per started minute of audio transcribed for the transcription add-on (a 32 min 10 s episode = 33 events). Paid plans only.

Apify free plan: up to 10 items per run. Paid plans have no per-run cap; set maxTotalChargeUsd to cap spend.

Run

Call it from code, an agent or the Console

This API is private on Apify for now. Email us and we will publish it for you, usually within two working days. The calls below work once it is public. contact@sfoln.com

curl · synchronous run, rows in the response
curl -X POST "https://api.apify.com/v2/actors/sfoln~podcast-scraper/run-sync-get-dataset-items" \
  -H "Authorization: Bearer $APIFY_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"podcasts":["https://feeds.npr.org/510289/podcast.xml"],"maxEpisodesPerShow":5}'
mcp.json · hosted Apify MCP server
{
  "mcpServers": {
    "apify": {
      "type": "http",
      "url": "https://mcp.apify.com?tools=sfoln/podcast-scraper"
    }
  }
}
asynchronous run · for large batches
POST https://api.apify.com/v2/actors/sfoln~podcast-scraper/runs?maxTotalChargeUsd=1
GET  https://api.apify.com/v2/actor-runs/{runId}            # until status is SUCCEEDED
GET  https://api.apify.com/v2/datasets/{defaultDatasetId}/items?format=json

Authenticate with an Apify API token. MCP clients can instead sign in with OAuth when prompted. Example prompt for an agent: List the 5 latest episodes of the Planet Money podcast with their dates, durations and audio links.

Input

Input fields

Podcasts to read: show names, Apple Podcasts links or ids, RSS feed URLs or podcast websites. Each podcast gives one row per episode plus one show profile row, and optionally transcript rows.

FieldTypeDefaultMeaning
podcasts *arrayrequiredPodcasts
One podcast per line: a show name (the best Apple Podcasts match is used), an Apple Podcasts link or id, an RSS feed URL, or the show's website. Accounts on the Apify free plan can process up to 10 podcasts per run (20 episodes each).
maxEpisodesPerShowinteger50Max episodes per show
Newest episodes to return per show (1–5,000). Range 1–5000.
sinceDaysinteger0Only episodes from the last N days
Keep only episodes published in the last N days (0 = all episodes, up to the maximum above). Range 0–36500.
countrystring"us"Apple Podcasts country
Two-letter storefront for show names and Apple ids, e.g. us, gb, de (an Apple Podcasts link's own country is used for that link).
transcribeLatestinteger0Transcribe the latest N episodes
Paid add-on: transcribe the newest N delivered episodes of each show with Mistral Voxtral ($0.0105 per audio minute, paid Apify plans only). Before the audio is sent, the remaining maximum cost per run must cover the longest the audio file can last (its real size at 32 kbps, at most 3 hours); only the minutes transcribed are charged. 0 = no transcription. Range 0–10.
maxMinutesPerEpisodeinteger90Max minutes per transcribed episode
Episodes longer than this (by the feed's duration, else the audio file's size) are not transcribed and not charged (1–180). Range 1–180.
transcriptionLanguagestring—Transcription language
ISO 639-1 code of the spoken language (e.g. en, de, es) to help the transcription; empty = detected automatically.
timestampsbooleanfalseTranscript timestamps
Add timed segments ({ start, end, text }) to each transcript.
maxShowsinteger100Max podcasts
Safety cap on how many podcasts are processed in this run; the rest are ignored and counted in the OUTPUT record. Range 1–1000.
concurrencyinteger3Concurrency
Podcasts processed in parallel (1–5). Apple's directory is asked at most about 20 times per minute per run. Range 1–5.
includeRawbooleanfalseInclude raw data
Attach each episode's parsed feed item (all namespaces) and the Apple directory record of the show (larger output).
Example input
{
  "podcasts": [
    "https://feeds.npr.org/510289/podcast.xml"
  ],
  "maxEpisodesPerShow": 5
}

Output

One record per input item

Records land in the run's dataset; a synchronous call returns them directly. Each has a status (ok is charged; everything else is free) and a charged flag. The run's OUTPUT record totals items and charges.

FieldTypeMeaning
inputstring | objectInput
The podcast this record belongs to, as given.
recordTypestringRecord type
episode = one episode (charged); transcript = one transcribed episode (charged per audio minute); summary = the show profile, one per podcast (free). e.g. "episode"
positionintegerPosition
episode: 1-based position among the episodes delivered for the podcast (newest first).
showTitlestring | nullShow
The podcast's title.
feedUrlstring | nullFeed URL
The show's RSS feed (after redirects).
appleIdstring | nullApple id
The show's Apple Podcasts id, when it was looked up there.
guidstring | nullGUID
episode / transcript: the episode's GUID in the feed.
titlestring | nullEpisode title
episode: the episode's title.
publishedAtstring | nullPublished at
episode / transcript: ISO 8601 publication time.
durationSecsnumber | nullDuration (s)
episode: length in seconds as the feed states it; transcript: the audio length Mistral reports.
durationstring | nullDuration
episode: length as h:mm:ss.
audioUrlstring | nullAudio URL
episode / transcript: the audio file (the feed's enclosure).
audioTypestring | nullAudio type
episode: MIME type of the audio file.
audioSizeBytesinteger | nullAudio size
episode: size of the audio file in bytes, as the feed states it.
episodeNumberinteger | nullEpisode number
episode: itunes:episode (or podcast:episode).
seasonNumberinteger | nullSeason number
episode: itunes:season (or podcast:season).
episodeTypestring | nullEpisode type
episode: full | trailer | bonus.
explicitboolean | nullExplicit
Explicit content flag (an episode without its own flag inherits the show's).
linkstring | nullEpisode page
episode: the episode's web page.
imageUrlstring | nullImage
episode: the episode artwork; summary: the show artwork.
descriptionstring | nullDescription
episode: the show notes as plain text (at most 20,000 characters); summary: the show's description.
linksarray | nullShow-note links
episode: the links in the show notes (at most 50).
transcriptsarray | nullPublished transcripts
episode: transcripts the show publishes itself (podcast:transcript) as [{ url, type, language }].
chaptersUrlstring | nullChapters
episode: the podcast:chapters file, when the show publishes one.
peoplearray | nullPeople
episode: hosts and guests the feed credits (podcast:person) as [{ name, role, group }].
appleEpisodeIdstring | nullApple episode id
episode: Apple's episode id (only for episodes taken from Apple's directory).
appleEpisodeUrlstring | nullApple episode URL
episode: the Apple Podcasts page of the episode (only for episodes taken from Apple's directory).
episodeTitlestring | nullEpisode title
transcript: the transcribed episode's title.
textstring | nullTranscript
transcript: the transcribed text.
segmentsarray | nullSegments
transcript: timed segments [{ start, end, text, speaker }] (with timestamps).
billedMinutesinteger | nullBilled minutes
transcript: started minutes of audio charged (transcription-minute events).
wordCountinteger | nullWords
transcript: words of the transcript.
modelstring | nullModel
transcript: the transcription model.
podcaststring | nullPodcast
summary: the podcast as given.
resolvedViastring | nullResolved via
summary: search | apple_id | feed_url | website.
episodesSourcestring | nullEpisodes from
summary: feed (the show's RSS feed) | apple (Apple's directory, when the show has no readable feed).
authorstring | nullAuthor
summary: itunes:author, else Apple's artist name.
ownerNamestring | nullOwner name
summary: itunes:owner name as published in the feed.
ownerEmailstring | nullOwner e-mail
summary: itunes:owner e-mail as published in the feed.
languagestring | nullLanguage
summary: the feed's language; transcript: the detected spoken language.
categoriesarray | nullCategories
summary: iTunes categories ("Business > Investing").
appleGenresarray | nullApple genres
summary: Apple's genres for the show.
showTypestring | nullShow type
summary: episodic | serial.
completeboolean | nullComplete
summary: the show has ended (itunes:complete).
websitestring | nullWebsite
summary: the show's website (the feed's link).
newFeedUrlstring | nullNew feed URL
summary: the feed the show moved to (itunes:new-feed-url).
copyrightstring | nullCopyright
summary: the feed's copyright line.
podcastGuidstring | nullPodcast GUID
summary: Podcasting 2.0 podcast:guid.
fundingUrlsarray | nullFunding links
summary: podcast:funding links.
appleUrlstring | nullApple Podcasts URL
summary: the show's Apple Podcasts page.
appleEpisodeCountinteger | nullApple episode count
summary: episodes Apple lists for the show.
episodesInFeedinteger | nullEpisodes in feed
summary: episodes the feed (or Apple) lists.
firstEpisodeAtstring | nullFirst episode
summary: date of the oldest listed episode.
latestEpisodeAtstring | nullLatest episode
summary: date of the newest episode.
averageDurationSecsinteger | nullAverage duration (s)
summary: average episode length.
medianIntervalDaysnumber | nullRelease cadence (days)
summary: median days between the latest 20 episodes.
episodesLast30Daysinteger | nullEpisodes, last 30 days
summary: episodes published in the last 30 days.
episodesLast90Daysinteger | nullEpisodes, last 90 days
summary: episodes published in the last 90 days.
episodesOutsideDateWindowinteger | nullEpisodes outside sinceDays
summary: episodes left out by sinceDays (not charged).
otherMatchesarray | nullOther matches
summary (name search): other Apple Podcasts matches [{ appleId, title, author, feedUrl, episodeCount }]; give one's appleId to read it instead.
transcriptionobject | nullTranscription
summary: { requested, delivered, minutesBilled, episodes: [{ guid, title, status, minutes?, reason? }] } when transcribeLatest is set on a paid plan.
resultsDeliveredinteger | nullEpisodes delivered
summary: episode rows delivered (and charged) for this podcast.
stopReasonstring | nullStop reason
summary: limit (maxEpisodesPerShow reached) | end (no more episodes) | budget | free_plan | aborted.
statusstringStatus
ok | not_found | error | skipped_invalid | skipped_budget | skipped_free_plan | skipped_unmetered e.g. "ok"
chargedbooleanCharged
episode and transcript rows: true (charged before they were written); summary rows: false.
chargedEventstringCharged event
episode on episode rows; transcription-minute on transcript rows (billedMinutes events).
chargedCountintegerEvents charged
Events actually charged when a charge came back short (present only then).
sourcestringSource
podcast: the show's RSS feed and Apple's podcast directory (transcripts by Mistral Voxtral).
fetchedAtstringFetched at
ISO timestamp.
errorobjectError
{ code, message, provider?, status? } when status is not ok: invalid_input, podcast_not_found, not_a_feed, malformed_feed, not_found, http_error, rate_limit (Apple throttling), timeout, network, blocked_url; runtime codes: budget_exhausted, free_plan_limit, unmetered, aborted, charge_failed, record_too_large, invalid_record, dataset_push_failed.
warningsarrayWarnings
Notes about this record (caps, Apple fallback, transcripts not included and why).
rawobject | nullRaw data
episode: the parsed feed item; summary: Apple's show record (only with includeRaw).
Example record
Example record
[
  {
    "input": "https://feeds.npr.org/510289/podcast.xml",
    "recordType": "episode",
    "position": 1,
    "showTitle": "Planet Money",
    "feedUrl": "https://feeds.npr.org/510289/podcast.xml",
    "appleId": null,
    "guid": "b297c28a-87e4-4b96-92e0-e64b7b581948",
    "title": "Wanna slow down AI? These biologists can help.",
    "publishedAt": "2026-10-14T21:30:18.000Z",
    "durationSecs": 1750,
    "duration": "29:10",
    "audioUrl": "https://play.podtrac.com/npr-510289/npr.simplecastaudio.com/episodes/fe8692b3/audio/128/default.mp3",
    "audioType": "audio/mpeg",
    "audioSizeBytes": 28012130,
    "episodeNumber": null,
    "seasonNumber": null,
    "episodeType": "full",
    "explicit": false,
    "link": "https://www.npr.org/2026/10/14/nx-s1-6002910/ai-scientific-regulation-conference-asilomar",
    "imageUrl": "https://npr.brightspotcdn.com/dims3/default/strip/false/crop/3377x1900+0+0/resize/1280/quality/66/format/jpg/",
    "description": "Fifty years ago, scientists pioneering a terrifying gene-splicing technology figured out a way to collectively hit pause. Can we do it again with AI? …",
    "links": [
      "https://kilkenomics.com/",
      "https://www.npr.org/newsletter/indicator"
    ],
    "transcripts": [],
    "chaptersUrl": null,
    "people": [],
    "appleEpisodeId": null,
    "appleEpisodeUrl": null,
    "status": "ok",
    "charged": true,
    "chargedEvent": "episode",
    "source": "podcast",
    "fetchedAt": "2026-10-15T09:00:02.000Z"
  },
  {
    "input": "https://feeds.npr.org/510289/podcast.xml",
    "recordType": "transcript",
    "guid": "b297c28a-87e4-4b96-92e0-e64b7b581948",
    "episodeTitle": "Wanna slow down AI? These biologists can help.",
    "showTitle": "Planet Money",
    "publishedAt": "2026-10-14T21:30:18.000Z",
    "audioUrl": "https://play.podtrac.com/npr-510289/npr.simplecastaudio.com/episodes/fe8692b3/audio/128/default.mp3",
    "language": "en",
    "text": "This is Planet Money from NPR. …",
    "durationSecs": 1750.4,
    "billedMinutes": 30,
    "wordCount": 4630,
    "model": "voxtral-mini-2602",
    "status": "ok",
    "charged": true,
    "chargedEvent": "transcription-minute",
    "source": "podcast",
    "fetchedAt": "2026-10-15T09:01:10.000Z"
  },
  {
    "input": "https://feeds.npr.org/510289/podcast.xml",
    "podcast": "https://feeds.npr.org/510289/podcast.xml",
    "resolvedVia": "feed_url",
    "episodesSource": "feed",
    "showTitle": "Planet Money",
    "author": "NPR",
    "ownerName": "NPR",
    "ownerEmail": "podcasts@npr.org",
    "description": "Wanna see a trick? Give us any topic and we can tie it back to the economy. …",
    "language": "en",
    "categories": [
      "Business",
      "News"
    ],
    "appleGenres": [],
    "explicit": false,
    "showType": "episodic",
    "complete": null,
    "website": "https://www.npr.org/podcasts/510289/planet-money",
    "feedUrl": "https://feeds.npr.org/510289/podcast.xml",
    "newFeedUrl": null,
    "imageUrl": "https://media.npr.org/assets/img/2022/10/24/pm_new_tile_2022_sq.jpg",
    "copyright": "Copyright 2015-2026 NPR - For Personal Use Only",
    "podcastGuid": null,
    "fundingUrls": [
      "https://plus.npr.org/"
    ],
    "appleId": null,
    "appleUrl": null,
    "appleEpisodeCount": null,
    "episodesInFeed": 355,
    "firstEpisodeAt": "2023-06-16T18:28:34.000Z",
    "latestEpisodeAt": "2026-10-14T21:30:18.000Z",
    "averageDurationSecs": 1635,
    "medianIntervalDays": 2.9,
    "episodesLast30Days": 9,
    "episodesLast90Days": 28,
    "episodesOutsideDateWindow": 0,
    "transcription": {
      "requested": 1,
      "delivered": 1,
      "minutesBilled": 30,
      "episodes": [
        {
          "guid": "b297c28a-87e4-4b96-92e0-e64b7b581948",
          "title": "Wanna slow down AI? These biologists can help.",
          "status": "delivered",
          "minutes": 30
        }
      ]
    },
    "recordType": "summary",
    "resultsDelivered": 20,
    "stopReason": "limit",
    "status": "ok",
    "charged": false,
    "source": "podcast",
    "fetchedAt": "2026-10-15T09:01:10.000Z"
  }
]

FAQ

Questions

What can I give as a podcast?
A show name or search term (the best match in Apple Podcasts is used, other matches are listed in the summary), an Apple Podcasts link or id (https://podcasts.apple.com/us/podcast/…/id290783428, or 290783428), an RSS feed URL, or the show's website (its feed is found from the page). Spotify links have no public feed, so give the show's name instead.
Where does the data come from?
From the show's own RSS feed, which every podcast publishes for directories: episode titles, dates, durations, audio files, show notes, iTunes episode and season numbers and Podcasting 2.0 tags (transcript and chapter links, people). The show is looked up in Apple's public podcast directory to find the feed. Shows without a public feed (some Apple-exclusive shows) get Apple's latest 200 episodes with fewer fields.
How does the transcription add-on work?
Set transcribeLatest to transcribe the newest delivered episodes of each show with Mistral Voxtral (paid Apify plans). Each transcript is a separate row (recordType transcript) and costs $0.0105 per started minute of audio. Episodes longer than maxMinutesPerEpisode, or whose audio file's size cannot be checked, are skipped rather than charged, and before any audio is sent the longest the file can last (its real size at 32 kbps) is checked against your maximum cost per run; only the minutes Mistral reports are charged. Many shows also publish their own transcripts: see the transcripts field of each episode (free).
What is in the show profile?
The summary row of each show: title, author, owner name and e-mail as published in the feed, description, language, categories, explicit flag, show type, website, artwork, Apple id and genres, plus publishing statistics: episodes in the feed, first and latest episode dates, average duration, the median number of days between episodes and the episodes of the last 30 and 90 days.

Machine-readable

This page for agents