# Podcast Transcript Scraper — Text, SRT & JSON (`northglasslabs/podcast-transcript-scraper`) Actor

Discover podcasts through iTunes or provide an RSS/Apple Podcasts URL, then extract episode metadata and Podcasting 2.0 transcript files. Export transcript text, SRT, or JSON when feeds publish transcript links.

- **URL**: https://apify.com/northglasslabs/podcast-transcript-scraper.md
- **Developed by:** [North Glass Labs](https://apify.com/northglasslabs) (community)
- **Categories:** Social media
- **Stats:** 2 total users, 0 monthly users, 96.7% 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/platform/actors/running/actors-in-store#pay-per-event

## What's an Apify Actor?

Actors are web data automations that power AI and operations. They run on the Apify platform to scrape websites, process data, connect APIs, and automate workflows.
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.
Actors are written with capital "A".

## 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.
The best way to integrate Actors is as follows.

In JavaScript/TypeScript projects, use official [JavaScript/TypeScript client](https://docs.apify.com/api/client/js/docs.md):

```bash
npm install apify-client
```

In Python projects, use official [Python client library](https://docs.apify.com/api/client/python/docs.md):

```bash
pip install apify-client
```

In shell scripts, use [Apify CLI](https://docs.apify.com/cli/docs.md):

````bash
# MacOS / Linux
curl -fsSL https://apify.com/install-cli.sh | bash
# Windows
irm https://apify.com/install-cli.ps1 | iex
```bash

In AI frameworks, you might use the [Apify MCP server](https://docs.apify.com/integrations/mcp.md).

If your project is in a different language, use the [REST API](https://docs.apify.com/api/v2.md).

For usage examples, see the [API](#api) section below.

For more details, see Apify documentation as [Markdown index](https://docs.apify.com/llms.txt) and [Markdown full-text](https://docs.apify.com/llms-full.txt).


# README

## Podcast Transcript Scraper — Text, SRT & JSON

Scrape **podcast episode transcripts** from any podcast's RSS feed. Search by keyword via the iTunes Search API or provide a direct podcast / RSS feed / Apple Podcasts URL. Export transcripts as **plain text**, **SRT subtitles**, or **structured JSON**. Includes full episode metadata — title, duration, publish date, season, episode number, and podcast name.

### What it does

The Podcast Transcript Scraper actor extracts full-episode transcripts from podcasts using the **iTunes Search API** (for podcast discovery) and standard **RSS feeds** (for episode listings and transcript files). It supports the Podcast Namespace 2.0 `<podcast:transcript>` tag — the modern standard for transcript distribution — and automatically downloads, parses, and formats transcripts in your preferred output format.

Each episode returned includes the episode title, full transcript text, transcript format descriptor, duration, publish date, podcast name, episode description (cleaned of HTML), audio URL, season and episode numbers, and the podcast's metadata (title, description, author, language, categories, and artwork URL). The actor prioritizes episodes that include `<podcast:transcript>` tags and processes those first.

Transcripts can be exported as **plain text** (stripped of timing data for NLP and search indexing), **SRT subtitles** (timestamped segments for video/audio captioning), or **JSON** (structured format with text fields for programmatic processing). The actor handles source transcripts in plain text, SRT, and WebVTT formats, converting between them as needed.

This makes the actor ideal for content repurposing (turn podcast episodes into blog posts, newsletters, or social media content), accessibility (generate SRT subtitles for audio/video content), NLP and AI training data collection, and building searchable transcript databases.

### Input parameters

| Parameter | Type | Required | Default | Description |
|-----------|------|----------|---------|-------------|
| `searchQuery` | string | No¹ | `""` | Search query to find podcasts via the iTunes Search API. Used when `podcastUrl` is not provided. |
| `podcastUrl` | string | No¹ | `""` | Direct URL to a podcast RSS feed, Apple Podcasts link (e.g. `podcasts.apple.com/.../id123456`), or episode page. Takes priority over `searchQuery`. |
| `maxEpisodes` | integer | No | `10` | Maximum number of episodes to scrape transcripts for (1–100). |
| `format` | string | No | `text` | Output format for transcripts: `text`, `srt`, or `json`. |

> ¹ **Either** `podcastUrl` **or** `searchQuery` must be provided — at least one is required. If `podcastUrl` is provided, it takes priority and `searchQuery` is ignored.

### Output fields

Each result item pushed to the dataset contains:

| Field | Type | Description |
|-------|------|-------------|
| `episodeTitle` | string \| null | Title of the podcast episode |
| `podcastName` | string \| null | Name of the podcast (from RSS feed / iTunes metadata) |
| `transcript` | string | Full transcript text in the requested format (`text`, `srt`, or `json`) |
| `transcriptFormat` | string | Format of the transcript field: `text`, `srt`, or `json` |
| `duration` | string \| null | Episode duration in `HH:MM:SS` or `MM:SS` format (from iTunes/RSS `itunes:duration` tag) |
| `durationSeconds` | integer \| null | Episode duration converted to total seconds (when parseable) |
| `publishDate` | string \| null | Episode publish date (from RSS `pubDate` tag) |
| `url` | string \| null | Direct URL to the episode page |
| `description` | string | Episode description / show notes (cleaned of HTML) |
| `audioUrl` | string \| null | Direct URL to the episode audio file (enclosure) |
| `season` | integer \| null | Season number (from `itunes:season` tag, when available) |
| `episodeNumber` | integer \| null | Episode number (from `itunes:episode` tag, when available) |
| `episodeGuid` | string \| null | Unique episode identifier (from RSS `guid` tag) |
| `episodeType` | string \| null | Episode type: `full`, `trailer`, or `bonus` (from `itunes:episodeType`) |

> **Note:** Podcast-level metadata fields (title, description, author, language, categories, image URL) are also included on each episode record when available.

### Use cases

- **Content repurposing** — turn podcast episodes into blog posts, newsletters, social media threads, or summary articles
- **Accessibility** — generate SRT subtitle files for audio and video content produced from podcast episodes
- **Search & indexing** — build a searchable transcript database so listeners can find content by keyword
- **Sentiment analysis** — analyze podcast discussions for brand mentions, opinions, and trending topics
- **AI training data** — collect high-quality podcast transcript text for fine-tuning NLP and LLM models
- **SEO** — publish transcripts alongside podcast episodes for improved search engine visibility and organic traffic

### How it works

The actor operates in a multi-stage pipeline using the **iTunes Search API** and **podcast RSS feeds**:

1. **Discovery** — If a `podcastUrl` is provided, the actor detects whether it's a raw RSS feed URL (ends in `.xml` / `.rss` or contains `/rss`), an Apple Podcasts link (extracts the `/id<number>` and looks up the feed URL via the iTunes Lookup API), or a generic page URL (fetches and checks the content type). If only a `searchQuery` is provided, the actor searches the iTunes Search API (`itunes.apple.com/search`) and uses the top result's `feedUrl`.

2. **RSS parsing** — The actor fetches and parses the podcast's RSS feed XML using Python's `ElementTree`. It extracts podcast-level metadata (title, description, author, language, image, categories) and iterates over all `<item>` elements to build a list of episodes with titles, descriptions, durations, audio URLs, episode numbers, and more.

3. **Transcript extraction** — For each `<item>`, the actor looks for `<podcast:transcript>` tags (from the Podcast Namespace 2.0 spec). These tags link to external transcript files in plain text, SRT, or WebVTT format. The actor prioritizes episodes with transcript tags and processes those first. For each transcript URL, it fetches the file, detects the source format, and converts it to your requested output format (`text`, `srt`, or `json`).

4. **Output** — Each episode record (with merged podcast metadata) is pushed to the Apify dataset. A polite 0.5-second delay is applied between episode-level requests.

> **Note:** Not all podcasts include `<podcast:transcript>` tags. Episodes without transcript links are still returned with their metadata and descriptions — the `transcript` field will be empty for those episodes. Popular podcasts like *Darknet Diaries*, *Acquired*, and others that adopt the Podcast Namespace 2.0 spec will have transcript data available.

### Example usage

#### Example input

```json
{
    "searchQuery": "Lex Fridman podcast",
    "maxEpisodes": 5,
    "format": "srt"
}
````

#### Example output (SRT format)

```json
{
    "episodeTitle": "Episode #412 — AI and the Future of Work",
    "podcastName": "Lex Fridman Podcast",
    "transcript": "1\n00:00:00 --> 00:00:10\nWelcome to the show. Today we're discussing AI and its impact.\n\n2\n00:00:10 --> 00:00:20\nLet me start by asking about your background in the field.\n",
    "transcriptFormat": "srt",
    "duration": "1:45:30",
    "durationSeconds": 6330,
    "publishDate": "Mon, 15 Jun 2025 14:00:00 GMT",
    "url": "https://lexfridman.com/episode-412",
    "description": "In this episode, we explore the future of work in the age of AI...",
    "audioUrl": "https://media.lexfridman.com/episode_412.mp3",
    "season": null,
    "episodeNumber": 412,
    "episodeGuid": "lex-episode-412"
}
```

#### Example output (text format)

When `format` is `text`, the transcript field contains plain, unsegmented text:

```json
{
    "episodeTitle": "Episode #412 — AI and the Future of Work",
    "podcastName": "Lex Fridman Podcast",
    "transcript": "Welcome to the show. Today we're discussing AI and its impact. Let me start by asking about your background in the field...",
    "transcriptFormat": "text"
}
```

### Pricing

This actor uses the **pay-per-event (PPE)** pricing model on Apify. You are charged a small fee for each successful actor run. The actor does not launch a browser — it uses pure HTTP requests to the iTunes API and RSS feeds, keeping runs fast and cost-efficient. A typical 10-episode scrape with transcripts takes about 10–20 seconds. Check the actor's Apify Store page for the current per-run pricing. Apify's free tier includes monthly platform credits that are sufficient for dozens of runs.

### Tips

- **Not all podcasts have transcripts** — the actor relies on `<podcast:transcript>` tags in RSS feeds (Podcast Namespace 2.0). If a podcast doesn't include these tags, episodes will still be returned with metadata and descriptions, but `transcript` will be empty. Search for popular tech podcasts that are more likely to include transcripts.
- **Use `podcastUrl` for reliability** — if you know the podcast's RSS feed URL (often found on the podcast's website), provide it directly in `podcastUrl` for the most reliable results. Apple Podcasts links (with `/id<number>`) are also supported and will be resolved to the correct feed automatically.
- **SRT segments are approximate** — when converting plain-text transcripts to SRT format, the actor uses fixed 10-second segments as a heuristic (real timestamp alignment requires audio processing). Use `text` or `json` format when precise timing is not needed.

# Actor input Schema

## `podcastUrl` (type: `string`):

Direct URL to a podcast RSS feed, Apple Podcasts link (with /id number), or individual episode. If provided, takes priority over searchQuery.

## `searchQuery` (type: `string`):

Search query for finding podcasts via the iTunes Search API. Used when podcastUrl is not provided.

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

Maximum number of episodes to scrape transcripts for.

## `format` (type: `string`):

Output format for transcripts: plain text, SRT subtitles, or structured JSON.

## Actor input object example

```json
{
  "podcastUrl": "",
  "searchQuery": "",
  "maxEpisodes": 10,
  "format": "text"
}
```

# Actor output Schema

## `results` (type: `string`):

Results stored in the default dataset

# 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 = {};

// Run the Actor and wait for it to finish
const run = await client.actor("northglasslabs/podcast-transcript-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 = {}

# Run the Actor and wait for it to finish
run = client.actor("northglasslabs/podcast-transcript-scraper").call(run_input=run_input)

# Fetch and print Actor results from the run's dataset (if there are any)
print("💾 Check your data here: https://console.apify.com/storage/datasets/" + run["defaultDatasetId"])
for item in client.dataset(run["defaultDatasetId"]).iterate_items():
    print(item)

# 📚 Want to learn more 📖? Go to → https://docs.apify.com/api/client/python/docs/quick-start

```

## CLI example

```bash
echo '{}' |
apify call northglasslabs/podcast-transcript-scraper --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "command": "npx",
            "args": [
                "mcp-remote",
                "https://mcp.apify.com/?tools=northglasslabs/podcast-transcript-scraper",
                "--header",
                "Authorization: Bearer <YOUR_API_TOKEN>"
            ]
        }
    }
}

```

## OpenAPI specification

```json
{
    "openapi": "3.0.1",
    "info": {
        "title": "Podcast Transcript Scraper — Text, SRT & JSON",
        "description": "Discover podcasts through iTunes or provide an RSS/Apple Podcasts URL, then extract episode metadata and Podcasting 2.0 transcript files. Export transcript text, SRT, or JSON when feeds publish transcript links.",
        "version": "0.0",
        "x-build-id": "LdZussyHhzJq3RWf5"
    },
    "servers": [
        {
            "url": "https://api.apify.com/v2"
        }
    ],
    "paths": {
        "/acts/northglasslabs~podcast-transcript-scraper/run-sync-get-dataset-items": {
            "post": {
                "operationId": "run-sync-get-dataset-items-northglasslabs-podcast-transcript-scraper",
                "x-openai-isConsequential": false,
                "summary": "Executes an Actor, waits for its completion, and returns Actor's dataset items in response.",
                "tags": [
                    "Run Actor"
                ],
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "$ref": "#/components/schemas/inputSchema"
                            }
                        }
                    }
                },
                "parameters": [
                    {
                        "name": "token",
                        "in": "query",
                        "required": true,
                        "schema": {
                            "type": "string"
                        },
                        "description": "Enter your Apify token here"
                    }
                ],
                "responses": {
                    "200": {
                        "description": "OK"
                    }
                }
            }
        },
        "/acts/northglasslabs~podcast-transcript-scraper/runs": {
            "post": {
                "operationId": "runs-sync-northglasslabs-podcast-transcript-scraper",
                "x-openai-isConsequential": false,
                "summary": "Executes an Actor and returns information about the initiated run in response.",
                "tags": [
                    "Run Actor"
                ],
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "$ref": "#/components/schemas/inputSchema"
                            }
                        }
                    }
                },
                "parameters": [
                    {
                        "name": "token",
                        "in": "query",
                        "required": true,
                        "schema": {
                            "type": "string"
                        },
                        "description": "Enter your Apify token here"
                    }
                ],
                "responses": {
                    "200": {
                        "description": "OK",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/runsResponseSchema"
                                }
                            }
                        }
                    }
                }
            }
        },
        "/acts/northglasslabs~podcast-transcript-scraper/run-sync": {
            "post": {
                "operationId": "run-sync-northglasslabs-podcast-transcript-scraper",
                "x-openai-isConsequential": false,
                "summary": "Executes an Actor, waits for completion, and returns the OUTPUT from Key-value store in response.",
                "tags": [
                    "Run Actor"
                ],
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "$ref": "#/components/schemas/inputSchema"
                            }
                        }
                    }
                },
                "parameters": [
                    {
                        "name": "token",
                        "in": "query",
                        "required": true,
                        "schema": {
                            "type": "string"
                        },
                        "description": "Enter your Apify token here"
                    }
                ],
                "responses": {
                    "200": {
                        "description": "OK"
                    }
                }
            }
        }
    },
    "components": {
        "schemas": {
            "inputSchema": {
                "type": "object",
                "properties": {
                    "podcastUrl": {
                        "title": "Podcast RSS feed or episode URL",
                        "type": "string",
                        "description": "Direct URL to a podcast RSS feed, Apple Podcasts link (with /id number), or individual episode. If provided, takes priority over searchQuery.",
                        "default": ""
                    },
                    "searchQuery": {
                        "title": "Search query",
                        "type": "string",
                        "description": "Search query for finding podcasts via the iTunes Search API. Used when podcastUrl is not provided.",
                        "default": ""
                    },
                    "maxEpisodes": {
                        "title": "Maximum episodes",
                        "minimum": 1,
                        "maximum": 100,
                        "type": "integer",
                        "description": "Maximum number of episodes to scrape transcripts for.",
                        "default": 10
                    },
                    "format": {
                        "title": "Transcript format",
                        "enum": [
                            "text",
                            "srt",
                            "json"
                        ],
                        "type": "string",
                        "description": "Output format for transcripts: plain text, SRT subtitles, or structured JSON.",
                        "default": "text"
                    }
                }
            },
            "runsResponseSchema": {
                "type": "object",
                "properties": {
                    "data": {
                        "type": "object",
                        "properties": {
                            "id": {
                                "type": "string"
                            },
                            "actId": {
                                "type": "string"
                            },
                            "userId": {
                                "type": "string"
                            },
                            "startedAt": {
                                "type": "string",
                                "format": "date-time",
                                "example": "2025-01-08T00:00:00.000Z"
                            },
                            "finishedAt": {
                                "type": "string",
                                "format": "date-time",
                                "example": "2025-01-08T00:00:00.000Z"
                            },
                            "status": {
                                "type": "string",
                                "example": "READY"
                            },
                            "meta": {
                                "type": "object",
                                "properties": {
                                    "origin": {
                                        "type": "string",
                                        "example": "API"
                                    },
                                    "userAgent": {
                                        "type": "string"
                                    }
                                }
                            },
                            "stats": {
                                "type": "object",
                                "properties": {
                                    "inputBodyLen": {
                                        "type": "integer",
                                        "example": 2000
                                    },
                                    "rebootCount": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "restartCount": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "resurrectCount": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "computeUnits": {
                                        "type": "integer",
                                        "example": 0
                                    }
                                }
                            },
                            "options": {
                                "type": "object",
                                "properties": {
                                    "build": {
                                        "type": "string",
                                        "example": "latest"
                                    },
                                    "timeoutSecs": {
                                        "type": "integer",
                                        "example": 300
                                    },
                                    "memoryMbytes": {
                                        "type": "integer",
                                        "example": 1024
                                    },
                                    "diskMbytes": {
                                        "type": "integer",
                                        "example": 2048
                                    }
                                }
                            },
                            "buildId": {
                                "type": "string"
                            },
                            "defaultKeyValueStoreId": {
                                "type": "string"
                            },
                            "defaultDatasetId": {
                                "type": "string"
                            },
                            "defaultRequestQueueId": {
                                "type": "string"
                            },
                            "buildNumber": {
                                "type": "string",
                                "example": "1.0.0"
                            },
                            "containerUrl": {
                                "type": "string"
                            },
                            "usage": {
                                "type": "object",
                                "properties": {
                                    "ACTOR_COMPUTE_UNITS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATASET_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATASET_WRITES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "KEY_VALUE_STORE_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "KEY_VALUE_STORE_WRITES": {
                                        "type": "integer",
                                        "example": 1
                                    },
                                    "KEY_VALUE_STORE_LISTS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "REQUEST_QUEUE_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "REQUEST_QUEUE_WRITES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATA_TRANSFER_INTERNAL_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATA_TRANSFER_EXTERNAL_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "PROXY_RESIDENTIAL_TRANSFER_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "PROXY_SERPS": {
                                        "type": "integer",
                                        "example": 0
                                    }
                                }
                            },
                            "usageTotalUsd": {
                                "type": "number",
                                "example": 0.00005
                            },
                            "usageUsd": {
                                "type": "object",
                                "properties": {
                                    "ACTOR_COMPUTE_UNITS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATASET_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATASET_WRITES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "KEY_VALUE_STORE_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "KEY_VALUE_STORE_WRITES": {
                                        "type": "number",
                                        "example": 0.00005
                                    },
                                    "KEY_VALUE_STORE_LISTS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "REQUEST_QUEUE_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "REQUEST_QUEUE_WRITES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATA_TRANSFER_INTERNAL_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATA_TRANSFER_EXTERNAL_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "PROXY_RESIDENTIAL_TRANSFER_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "PROXY_SERPS": {
                                        "type": "integer",
                                        "example": 0
                                    }
                                }
                            }
                        }
                    }
                }
            }
        }
    }
}
```
