# Podcast Scraper (`mina_safwat/podcast-scraper`) Actor

Finds podcasts on Apple Podcasts and returns show details plus recent episodes with audio links

- **URL**: https://apify.com/mina_safwat/podcast-scraper.md
- **Developed by:** [Mina](https://apify.com/mina_safwat) (community)
- **Categories:** For creators, Marketing, News
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $2.00 / 1,000 results

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

Scrape **Apple Podcasts** for **show details and recent episodes**: name, author, genres, artwork, explicit rating and RSS feed, plus each episode's date, duration in seconds, description and direct audio link.

### What does Podcast Scraper do?

Podcast Scraper searches [Apple Podcasts](https://podcasts.apple.com) by keyword, pulls a country's **top podcast charts**, or looks up exact shows by their Apple ID. For each podcast you get the name, author, genres, artwork, episode count, explicit rating, the date of the newest episode, and links to both its Apple page and its RSS feed.

Switch on **Include episodes** and every show also carries its most recent episodes: title, publication date, duration (as written and in seconds), description, direct audio link and file size.

It needs no account, no API key and no proxy. Running it on Apify adds an API, scheduling, integrations (Google Sheets, Slack, Zapier, Make, S3) and run monitoring.

### Why use Podcast Scraper?

- **Podcast discovery and directories**: build a searchable list of shows in a niche.
- **Advertising and sponsorship research**: find active shows in a category and see how often they publish.
- **Competitive analysis**: track what rival shows release and how often.
- **Media monitoring**: watch for new episodes on topics you care about.
- **AI and transcription pipelines**: the audio links are direct and durations come in seconds, so the output feeds speech-to-text and recommendation systems as-is.

### How to use Podcast Scraper to get Apple Podcasts data

1. Choose **What to get**: Search, Top charts, or Look up by ID.
2. Enter **Search terms** (or **Podcast IDs**) and a two-letter **Country** code.
3. Turn on **Include episodes** if you want each show's recent episodes.
4. Click **Start**, then open the **Output** tab. Results appear as they arrive.

### Input

Set everything on the **Input** tab. The same input as JSON, for the API:

```json
{
  "mode": "search",
  "search_terms": ["true crime"],
  "country": "us",
  "max_podcasts": 10,
  "include_episodes": true,
  "max_episodes_per_podcast": 5
}
```

| Field | Description |
| --- | --- |
| `mode` | `search`, `top_charts` or `lookup` (Look up by ID). |
| `search_terms` | Keywords or show names, one per line. Results from several terms are merged without duplicates. |
| `podcast_ids` | Apple Podcasts show IDs (`1379959217` or `id1379959217`) or show links (`https://podcasts.apple.com/us/podcast/morbid/id1379959217`). Publisher (`/artist/`) links are not show IDs. |
| `country` | Two-letter code such as `us`, `gb` (United Kingdom, not `uk`) or `de`. Charts and availability differ by country. |
| `max_podcasts` | Stops after this many shows in the whole run, not per search term or ID, so with several terms the later ones may add nothing. Apple returns at most 200 per search term or chart. |
| `include_episodes`, `max_episodes_per_podcast` | Adds each show's most recent episodes. |

### Output

One row per podcast. Here is a real row, trimmed to one episode with a shortened description and audio link:

```json
{
  "podcast_id": 1379959217,
  "name": "Morbid",
  "author": "Ash Kelley & Alaina Urquhart",
  "url": "https://podcasts.apple.com/us/podcast/morbid/id1379959217",
  "feed_url": "https://feeds.simplecast.com/ohmVlJZQ",
  "primary_genre": "True Crime",
  "genres": ["True Crime", "Comedy"],
  "episode_count": 907,
  "country": "US",
  "latest_episode_date": "2026-10-01T07:00:00Z",
  "explicit": true,
  "content_rating": "Explicit",
  "artwork": "https://is1-ssl.mzstatic.com/image/thumb/Podcasts211/v4/78/e9/0e/78e90ee0-567d-1ad8-17a0-17d7c988c4bd/mza_8425901783365617933.jpg/600x600bb.jpg",
  "episodes": [
    {
      "title": "The Eddy Brothers and the High Life Ski Club",
      "published_at": "2026-10-01T07:00:00+00:00",
      "duration": "00:46:12",
      "duration_seconds": 2772,
      "episode_number": 832,
      "season": null,
      "description": "In the early-to-mid 1870s, as interest in Spiritualism swept the United States...",
      "audio_url": "https://dts.podtrac.com/redirect.mp3/stitcher.simplecastaudio.com/d4d5c1a0-121c-450d-8aed-1ebd2f4dddf0/episodes/0041f647-b86a-43c0-a688-77def7eb5afd/audio/128/default.mp3",
      "audio_bytes": 44368261,
      "explicit": true,
      "guid": "4ef3b66f-52f8-4552-8d88-6536bb461c59"
    }
  ]
}
```

You can download the dataset in various formats such as JSON, HTML, CSV, or Excel.

#### Data fields

| Field | Description |
| --- | --- |
| `podcast_id`, `name`, `author` | The show's Apple ID, title and publisher. |
| `url`, `feed_url` | The show's Apple Podcasts page and its RSS feed. |
| `artwork` | Cover art, 600×600. |
| `primary_genre`, `genres` | How Apple categorises the show. |
| `episode_count` | How many episodes Apple lists. |
| `latest_episode_date` | Apple's date for the newest episode. |
| `explicit`, `content_rating` | `true` / `Explicit` when Apple rates the show explicit. `content_rating` is empty when Apple gives the show no rating. |
| `country` | The two-letter store the data came from, as you entered it. |
| `episodes` | With **Include episodes** on: `title`, `published_at`, `duration`, `duration_seconds`, `description`, `audio_url`, `audio_bytes`, `explicit` and `guid` for each recent episode. |

Episodes also carry `episode_number` and `season` when the publisher's feed numbers them; many feeds don't, and then they are `null`. In **Top charts** mode every row also has `chart_rank` (1 = top), and rows arrive in chart order.

### How much does it cost to scrape Apple Podcasts?

The Actor uses pay-per-event pricing, and you pay only for podcasts it delivers:

- **$0.002 per podcast** in the dataset, so **about $2.00 per 1,000 results**.
- **$0.00005 per run** for starting the Actor. That is one charge per GB of memory, and the default is 1 GB.

Episodes ride inside their show's row, so turning them on costs nothing extra. A search term or ID that finds nothing is never billed as a row.

| Run | Podcasts | Approximate cost |
| --- | --- | --- |
| 1 search × 25 shows | 25 | $0.05 |
| Top 200 chart, with episodes | 200 | $0.40 |
| 10 searches × 100 shows | 1,000 | $2.00 |

Apify's free plan includes $5 of monthly credit, which covers roughly 2,500 podcasts.

### Tips

- **Search terms match show names and authors**, so a network's name pulls its whole slate.
- **Charts are per country.** Run several countries to compare markets.
- **`episode_count` next to `latest_episode_date`** tells an active show from a dormant one, which helps when picking sponsorship targets.
- **Episodes add one request per show**, because they come from each show's own feed. Leave them off when you only need show details; the run then finishes in seconds.
- **Keep `max_episodes_per_podcast` small** for monitoring; you rarely need more than the latest few.

### FAQ, disclaimers and support

**Does it need an account or API key?** No. It reads Apple's public podcast directory and the publishers' public RSS feeds.

**Why did a show come back without episodes?** Episodes are not in Apple's data. They live in each show's RSS feed on the publisher's host, and some feeds are offline, moved or malformed. Those shows still come through, with an `episodes_error` field that says what went wrong.

**Why only recent episodes?** Many feeds carry only a rolling window of recent episodes. `max_episodes_per_podcast` caps what is kept; the feed decides how far back it goes.

**Why is `latest_episode_date` sometimes empty or a few days old?** It is Apple's index date. Apple occasionally lists a date that hasn't happened yet, which matches no real episode, so the Actor leaves it empty. Apple's index can also lag the feed by a few days; with episodes on, `published_at` comes straight from the feed.

**What if a search or ID finds nothing?** It isn't billed. It is listed with the reason in the `FAILED_INPUTS` record of the run's key-value store, and the run's status message gives the counts. That covers searches with no matches, IDs that aren't podcasts (a publisher, episode or song ID), entries that are neither an ID nor a link, and country codes Apple has no store for. The run fails only when Apple could not be reached for any input.

**Is it legal to scrape Apple Podcasts?** The Actor collects only publicly available directory data and public RSS feeds, and no personal data beyond the publisher names shown on each show. Episode audio, artwork and descriptions remain the publishers' copyright, so indexing and analysing them is normal, but redistributing them may not be. You are responsible for complying with Apple's terms and applicable law. Consult a lawyer if you are unsure.

Found a bug or need a field that's missing? Open an issue on the Actor's **Issues** tab. Custom podcast-data solutions are available on request.

# Actor input Schema

## `mode` (type: `string`):

Search finds podcasts by keyword. Top charts lists the most popular shows in a country. Look up by ID fetches exact podcasts.

## `search_terms` (type: `array`):

Words or show names to search for, one per line. Results from several terms are merged.

## `podcast_ids` (type: `array`):

Apple Podcasts IDs or show links, e.g. 1200361736 or https://podcasts.apple.com/us/podcast/the-daily/id1200361736. Used by Look up by ID.

## `country` (type: `string`):

Two-letter country code, e.g. us, gb (United Kingdom) or de. Charts and availability differ by country.

## `max_podcasts` (type: `integer`):

Stops after this many shows in the whole run, not per search term or ID: shows past this count are left out.

## `include_episodes` (type: `boolean`):

Also fetch each show’s recent episodes — titles, dates, durations, descriptions, and audio links. This reads the show’s own RSS feed, so it adds a request per podcast.

## `max_episodes_per_podcast` (type: `integer`):

How many recent episodes to keep for each show.

## Actor input object example

```json
{
  "mode": "search",
  "search_terms": [
    "true crime"
  ],
  "podcast_ids": [],
  "country": "us",
  "max_podcasts": 10,
  "include_episodes": true,
  "max_episodes_per_podcast": 5
}
```

# Actor output Schema

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

No description

# 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 = {
    "search_terms": [
        "true crime"
    ],
    "max_podcasts": 10,
    "include_episodes": true,
    "max_episodes_per_podcast": 5
};

// Run the Actor and wait for it to finish
const run = await client.actor("mina_safwat/podcast-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 = {
    "search_terms": ["true crime"],
    "max_podcasts": 10,
    "include_episodes": True,
    "max_episodes_per_podcast": 5,
}

# Run the Actor and wait for it to finish
run = client.actor("mina_safwat/podcast-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 '{
  "search_terms": [
    "true crime"
  ],
  "max_podcasts": 10,
  "include_episodes": true,
  "max_episodes_per_podcast": 5
}' |
apify call mina_safwat/podcast-scraper --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,mina_safwat/podcast-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/ty3ZtJxbmP6kyHZkw/builds/gPe8vlXEhEndq5cna/openapi.json
