YouTube Transcript Scraper avatar

YouTube Transcript Scraper

Pricing

from $4.00 / 1,000 results

Go to Apify Store
YouTube Transcript Scraper

YouTube Transcript Scraper

Extracts full transcripts and metadata from YouTube videos. Supports single videos, channels, and playlists — returns timestamped segments, plain text, SRT, or VTT with video title, channel name, duration, and language info. No API key or proxy needed.

Pricing

from $4.00 / 1,000 results

Rating

0.0

(0)

Developer

Meherab Hossain

Meherab Hossain

Maintained by Community

Actor stats

0

Bookmarked

2

Total users

1

Monthly active users

3 days ago

Last modified

Share

An Apify Actor that extracts transcripts (captions/subtitles) from YouTube videos, channels, and playlists. It tries the lightweight YouTube Innertube/timedtext API first (HTTP-only, no browser), and falls back to Playwright headless browser when the API path fails.

Pricing: $0.01 per successfully extracted transcript (Pay-Per-Event).

Features

  • Video, channel, and playlist support — paste any YouTube URL
  • Timed segments — each transcript comes with start time, duration, and text
  • Multiple output formats — segments (default), plain text, SRT, VTT
  • Language preferences — specify preferred languages in order
  • Translation — fetch transcripts translated into another language via YouTube's tlang parameter
  • Auto-generated captions — optionally include or exclude ASR captions
  • Smart proxy strategy — starts without proxy, switches to residential proxy after 3 consecutive IP blocks
  • Browser fallback — Playwright Chromium used when the HTTP API path fails
  • PPE pricing — only charged on success, no charge for failures

Input

FieldTypeRequiredDefaultDescription
sourcestringyesYouTube video/channel/playlist URL or bare ID
sourceTypeenumnoautoForce source interpretation: auto, video, channel, playlist
maxVideosintegerno50Max videos for channels/playlists (0 = unlimited, capped at 500)
languagesstring[]no[]Ordered language preference (e.g. ["en", "es"])
translateTostringno""Translation target language code (e.g. "es")
formatenumnosegmentsOutput format: segments, plain, srt, vtt
includeAutoGeneratedbooleannotrueInclude ASR captions
useProxyenumnoautoProxy strategy: auto, always, never
useBrowserFallbackbooleannotrueEnable Playwright fallback

Example input

{
"source": "https://www.youtube.com/watch?v=dQw4w9WgXcQ",
"languages": ["en"],
"format": "segments"
}

Output

Each result is a JSON object with:

FieldTypeDescription
videoIdstring11-char YouTube video ID
videoUrlstringFull watch URL
titlestringVideo title
channelNamestringChannel/uploader name
channelIdstringChannel ID (UC...)
publishedAtstringISO 8601 publish date
durationSecondsintegerVideo duration in seconds
languagestringLanguage code of the fetched caption track
isAutoGeneratedbooleanTrue if ASR captions
isTranslatedbooleanTrue if a translation was fetched
transcriptstringFull transcript text (for plain/srt/vtt formats; empty for segments)
segmentsarrayTimed segments: {start, duration, text} (for segments format)
extractionMethodstringinnertube_api, playwright, or failed
errorstringError message if extraction failed

Example output

{
"videoId": "dQw4w9WgXcQ",
"videoUrl": "https://www.youtube.com/watch?v=dQw4w9WgXcQ",
"title": "Rick Astley - Never Gonna Give You Up (Official Video)",
"channelName": "Rick Astley",
"language": "en",
"isAutoGenerated": false,
"isTranslated": false,
"transcript": "",
"segments": [
{"start": 0.0, "duration": 4.5, "text": "We're no strangers to love"},
{"start": 4.5, "duration": 3.2, "text": "You know the rules and so do I"}
],
"extractionMethod": "innertube_api",
"error": ""
}

Architecture

Actor.main()
├─ 1. Parse & validate input
├─ 2. Resolve source → list of video IDs
│ ├─ video URL[1 video ID]
│ ├─ channel URL → scrape /videos → N video IDs
│ └─ playlist URL → scrape playlist → N video IDs
├─ 3. For each video ID:
│ ├─ TRY: Innertube API (HTTP-only)
│ │ ├─ Fetch watch page HTML
│ │ ├─ Extract ytInitialPlayerResponse
│ │ ├─ Parse captionTracks
│ │ ├─ Select best track (language pref)
│ │ └─ GET baseUrl → parse JSON3 → segments
│ ├─ IF API FAILS & browser fallback enabled:
│ │ └─ TRY: Playwright headless browser
│ └─ IF BOTH FAIL: output with extractionMethod=failed
├─ 4. Push results to dataset
└─ 5. Charge $0.01 per successful transcript (PPE)

Proxy Strategy

useProxyBehavior
auto (default)Start with direct requests. If 3 consecutive IP-block errors (403/429), switch to Apify residential proxy.
alwaysUse Apify residential proxy from the start.
neverNever use proxy. If IP is blocked, the video fails (browser fallback still tried without proxy).

Local Development

Install dependencies

pip install -r requirements.txt
playwright install --with-deps chromium

Run locally

# Single video
python -m src.main dQw4w9WgXcQ
# With JSON input
echo '{"source": "https://www.youtube.com/watch?v=dQw4w9WgXcQ", "format": "plain"}' | python -m src.main
# Run tests
pytest tests/ -v

Building for Apify

$apify push

Cost Estimation

ScenarioVideosSuccess rateCost
Single video195%~$0.01
Channel (50 videos)5080%~$0.40
Playlist (100 videos)10085%~$0.85

Tech Stack

  • Language: Python 3.12+
  • SDK: Apify SDK for Python (v2.x)
  • HTTP client: httpx
  • Browser: Playwright (Chromium) — fallback only
  • Base image: apify/actor-python:3.12