# YouTube Transcript Scraper — Timestamps, No API Key (`themineworks/youtube-transcript-scraper`) Actor

Get timestamped YouTube transcripts and captions as clean JSON with segments, fullText and char count. No API key, no login. Feed video transcripts straight into RAG, LLMs and AI agents via Claude, ChatGPT and any MCP server.

- **URL**: https://apify.com/themineworks/youtube-transcript-scraper.md
- **Developed by:** [The Mine Works](https://apify.com/themineworks) (community)
- **Categories:** Videos, AI, MCP servers
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $0.60 / 1,000 transcripts

This Actor is paid per event. You are not charged for the Apify platform usage, but only a fixed price for specific events.
Since this Actor supports Apify Store discounts, the price gets lower the higher subscription plan you have.

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.

- **AI agents and MCP clients** — the [Apify MCP server](https://docs.apify.com/integrations/mcp.md) at `https://mcp.apify.com` (remote, streamable HTTP, OAuth on first use).
- **Agentic workflows and local Actor development** — [Agent Skills](https://apify.com/.well-known/agent-skills/index.json) with the [Apify CLI](https://docs.apify.com/cli/docs.md): `npm install -g apify-cli`, then `apify login`.
- **JavaScript/TypeScript projects** — the official [JS/TS client](https://docs.apify.com/api/client/js/docs.md): `npm install apify-client`.
- **Python projects** — the official [Python client](https://docs.apify.com/api/client/python/docs.md): `pip install apify-client`.
- **Any other language** — 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

## 📝 YouTube Transcript Scraper: Captions to Clean JSON (No API Key)

> **Part of the Social & Market Research MCP.** This actor's data is also available to AI agents through our [Social & Market Research MCP server](https://apify.com/themineworks/social-research-mcp) — eight social, news and search-interest tools behind one endpoint. No result, no charge.

> ⚡ 16/16 runs succeeded in the last 30 days · no API key, no OAuth, no quota.

> 💸 You're only charged for delivered results. Empty searches, failed pages and duplicate listings are never billed.

### Overview

YouTube Transcript Scraper pulls timestamped transcripts and captions from any public YouTube video and returns them as clean, structured JSON, ready to drop straight into a RAG pipeline, a vector store, or an LLM prompt. Give it a list of video URLs (or bare IDs) and get back per-video segments, a joined `fullText`, the caption language, and a character count.

No API key, no OAuth, no quota. It works on any public video, including auto-generated captions.

✅ No login required | ✅ No API key | ✅ Pay only for delivered transcripts | ✅ MCP-ready for AI agents

### Features

Structured JSON output. Per-segment `{ start, dur, text }` plus a joined `fullText`.
Any URL shape. `watch?v=`, `youtu.be`, `/shorts/`, `/embed/`, or bare 11-char IDs.
Language preference with fallback. Prefer `en`, `es`, `hi` and fall back to the default track.
Auto vs. human captions flagged. `isAutoGenerated` tells you which you got.
Free failure handling. Videos with captions disabled return `no-captions` and are never billed.

### How it works

The official YouTube Data API caption endpoints require OAuth, channel ownership, and a daily quota. You effectively cannot download the caption text of videos you do not own. This scraper reads the same public caption tracks YouTube already serves to any viewer's player. No key, no OAuth, no quota.

For each video, the actor resolves the canonical ID, reads available caption tracks from the watch page, and pulls the timed-text XML for the preferred language (falling back if that language is missing). Segments are cleaned into `{ start, dur, text }` items in seconds and joined into a readable `fullText`. Videos with captions disabled return `status: no-captions` and are not billed.

### 🧾 Input configuration

```json
{
  "videoUrls": [
    "https://www.youtube.com/watch?v=dQw4w9WgXcQ",
    "https://youtu.be/9bZkp7q19f0",
    "kJQP7kiw5Fk"
  ],
  "language": "en",
  "includeTimestamps": true,
  "proxy": { "useApifyProxy": true }
}
```

### 📤 Output format

```json
{
  "videoId": "dQw4w9WgXcQ",
  "url": "https://www.youtube.com/watch?v=dQw4w9WgXcQ",
  "title": "Rick Astley, Never Gonna Give You Up (Official Video)",
  "language": "en",
  "isAutoGenerated": false,
  "segments": [
    { "start": 18.8, "dur": 3.2, "text": "We're no strangers to love" },
    { "start": 22.0, "dur": 3.36, "text": "You know the rules and so do I" }
  ],
  "fullText": "We're no strangers to love You know the rules and so do I ...",
  "charCount": 1542,
  "segmentCount": 84,
  "status": "ok",
  "scrapedAt": "2026-07-10T09:15:00.000Z"
}
```

Every transcript record contains these fields:

| Field | Description |
| --- | --- |
| 🆔 `videoId` | 11-character YouTube video ID |
| 🔗 `url` | Canonical watch URL |
| 🏷️ `title` | Video title (null if unparsable) |
| 🌐 `language` | Language code of the caption track used |
| 🤖 `isAutoGenerated` | True for auto (ASR) captions, false for human/uploaded |
| ⏱️ `segments` | Ordered `{ start, dur, text }` items in seconds |
| 📝 `fullText` | All segment text joined into one readable string |
| 🔢 `charCount` | Character length of `fullText` |
| 📊 `segmentCount` | Number of transcript segments |
| 🚦 `status` | `ok`, `no-captions`, or `error` |
| 🕒 `scrapedAt` | ISO 8601 timestamp of the fetch |

The run also pushes a final `status: "summary"` record with counts (`transcriptsScraped`, `noCaptions`, `errored`, `chargedFor`).

### 💼 Common use cases

**RAG and vector search**
Chunk `fullText`, embed it, and let an LLM answer questions grounded in video content.
Chain into the rag-crawler to index entire channels.

**Video summarization**
Pipe transcripts to an LLM for TL;DRs, chapter markers, or highlight reels.
Batch process a channel to produce weekly digests.

**Content repurposing**
Turn webinars, podcasts, and tutorials into articles, show notes, and social posts.
Feed the `segments[]` array into a subtitle or translation workflow.

**Research and dataset building**
Mine spoken content across many videos for topics, keywords, and tone.
Assemble timestamped speech-to-text corpora for fine-tuning or analysis.

### 🚀 Getting started

1. Open the actor in Apify Console (or call it via API or MCP).
2. Under YouTube video URLs or IDs, paste one or more videos: watch URLs, `youtu.be` links, `/shorts/`, `/embed/`, or bare IDs.
3. Set preferred caption language (e.g. `en`, `es`, `hi`). The actor falls back to the default track if that language is missing.
4. Toggle Include timestamps on for `{ start, dur, text }` segments, or off for `fullText` only.
5. Click Save and Start, then download the dataset as JSON, CSV, or Excel, or pull via API or MCP.

### 💵 Pricing

One pay-per-event charge: **`transcript-scraped`** — charged when a transcript comes back with `status: "ok"`.

Apify applies a discount tier to your account. Price per transcript at each tier:

| Apify tier | Per transcript | Per 1,000 transcripts |
| --- | --- | --- |
| FREE | $0.001 | $1.00 |
| BRONZE | $0.00084 | $0.84 |
| SILVER | $0.00071 | $0.71 |
| GOLD | $0.0006 | $0.60 |
| PLATINUM | $0.0006 | $0.60 |
| DIAMOND | $0.0006 | $0.60 |

At the FREE tier that is **$1.00 per 1,000 transcripts**. Your tier is shown on your Apify billing page.

Pay-per-event, no subscription and no monthly minimum. Videos with captions disabled (`status: "no-captions"`), errored videos, and failed or empty runs are never billed — you only pay for a transcript actually returned.

### ⏰ Run it on a schedule

Transcribing a channel's new uploads as they publish is the natural recurring use — the transcripts land in one growing dataset ready for a RAG index or a weekly digest.

1. On this actor's page, click **⋯ → Schedule actor** (or Console → **Schedules → Create new**).
2. Pick a frequency — `@weekly` fits most channel digests; `@daily` for high-volume channels.
3. Your saved input is reused on every run; each run appends to a named dataset.
4. Wire the dataset to Google Sheets, Slack, or a webhook via the actor's **Integrations** tab so new records reach you automatically.

### FAQ

**Do I need a YouTube API key or account?**
No. The scraper reads public caption tracks directly from the watch page and the public `timedtext` endpoint. No API key, no OAuth, no login, and no quota.

**What video URL formats are supported?**
Full `watch?v=` URLs, `youtu.be/…` short links, `/shorts/…`, `/embed/…`, and bare 11-character video IDs. Each resolves to the canonical video automatically.

**What happens if a video has no captions?**
The record comes back with `status: "no-captions"` and is not charged. Only videos that return an actual transcript are billed.

**Can I choose the caption language?**
Yes. Set preferred caption language to a two-letter code (e.g. `en`, `es`, `hi`, `fr`). The actor prefers an exact match, then a language-prefix match (`en` matches `en-US`), then the video's default track, then the first available, and reports what it used in `language`.

**Are auto-generated (ASR) captions supported?**
Yes. When only auto captions exist, the actor returns them and sets `isAutoGenerated: true`, so you can tell human captions apart from machine ones.

**How is it priced?**
Pay per result: one charge per transcript actually returned. There is no free tier. Videos with captions disabled, and failed or empty runs, are never charged.

**Can I use it inside an AI agent?**
Yes. It is exposed as an MCP tool. See below.

**How do I get YouTube transcripts in bulk without the API?**
Paste every video into `videoUrls` in a single run — there is no per-video copy-and-paste and no OAuth handshake. The actor reads the same public caption tracks YouTube serves to any viewer, so a list of hundreds of videos becomes one dataset you can export as JSON, CSV, or Excel, or pull straight into an agent over MCP.

**Can I download the transcript of a video I don't own?**
Yes, for any public video that has captions. This is the main gap this actor fills: YouTube's official Data API caption-download endpoints are scoped to channels you own, so they cannot return the caption text of someone else's video. Reading the public caption track has no such restriction.

**Can I get the transcript with timestamps?**
Yes. Leave `includeTimestamps` on and every record carries a `segments` array of `{ start, dur, text }` items in seconds, alongside the joined `fullText`. Turn it off if you only want the plain text block.

### Use in Claude, ChatGPT & any MCP agent

```
https://mcp.apify.com/?tools=themineworks/youtube-transcript-scraper
```

Or call it programmatically with the Apify client:

```js
import { ApifyClient } from 'apify-client';

const client = new ApifyClient({ token: 'YOUR_APIFY_TOKEN' });

const run = await client.actor('themineworks/youtube-transcript-scraper').call({
  videoUrls: ['https://www.youtube.com/watch?v=dQw4w9WgXcQ'],
  language: 'en',
  includeTimestamps: true,
});

const { items } = await client.dataset(run.defaultDatasetId).listItems();
console.log(items);
```

### 🛠️ Complete your YouTube pipeline

Pair the transcript scraper with the rest of the video suite:

- **[YouTube Channel Scraper](https://apify.com/themineworks/youtube-channel)**: subscribers, video list, and channel stats, no API key.
- **[RAG Crawler](https://apify.com/themineworks/rag-crawler)**: index entire sites for LLM retrieval.
- **[Reddit Scraper](https://apify.com/themineworks/reddit-scraper)**: pull public posts and comment trees for training data.

Typical flow: youtube-channel discovers the videos, youtube-transcript-scraper turns them into text, the RAG crawler assembles the wider corpus.

Found a bug or have a feature request? Open an issue on the actor's Apify Console page or reach out through the Apify profile.

# Actor input Schema

## `videoUrls` (type: `array`):

List of YouTube videos to fetch transcripts for. Accepts full watch URLs (https://www.youtube.com/watch?v=...), youtu.be short links, /shorts/ URLs, /embed/ URLs, or bare 11-character video IDs.

## `language` (type: `string`):

Two-letter language code for the caption track to prefer (e.g. 'en', 'es', 'hi', 'fr'). If a track in this language is not available, the actor falls back to the video's default/first available track.

## `includeTimestamps` (type: `boolean`):

When enabled, each segment includes its start time and duration (in seconds). The joined fullText is always returned regardless of this setting.

## `proxy` (type: `object`):

Optional proxy. Apify Proxy (datacenter) is usually sufficient for the public YouTube caption endpoints. Use RESIDENTIAL only if you hit rate limits.

## Actor input object example

```json
{
  "videoUrls": [
    "https://www.youtube.com/watch?v=dQw4w9WgXcQ"
  ],
  "language": "en",
  "includeTimestamps": true,
  "proxy": {
    "useApifyProxy": true
  }
}
```

# Actor output Schema

## `results` (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 = {
    "videoUrls": [
        "https://www.youtube.com/watch?v=dQw4w9WgXcQ"
    ],
    "language": "en",
    "proxy": {
        "useApifyProxy": true
    }
};

// Run the Actor and wait for it to finish
const run = await client.actor("themineworks/youtube-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 = {
    "videoUrls": ["https://www.youtube.com/watch?v=dQw4w9WgXcQ"],
    "language": "en",
    "proxy": { "useApifyProxy": True },
}

# Run the Actor and wait for it to finish
run = client.actor("themineworks/youtube-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 '{
  "videoUrls": [
    "https://www.youtube.com/watch?v=dQw4w9WgXcQ"
  ],
  "language": "en",
  "proxy": {
    "useApifyProxy": true
  }
}' |
apify call themineworks/youtube-transcript-scraper --silent --output-dataset

```

## MCP server setup

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

```

## OpenAPI specification

Download the OpenAPI definition: https://api.apify.com/v2/acts/uvZqKi1CJjtKfLgV3/builds/SKb6IhH0Ac5Iiv3da/openapi.json
