Disclosure: I'm the maker of the YouTube Transcript Scraper on the Apify Store used below. Other transcript tools exist; this post shows how to use ours, with real output.
If you've tried pulling YouTube transcripts in a script lately, you've probably hit one of these:
- the "official" route needs OAuth and only works for videos you own,
- the popular open-source libraries work on your laptop and then get blocked on a server,
- or, the sneakiest one, the call "succeeds" and returns an empty transcript.
That last one happens because the caption links YouTube serves to the desktop site now need a hidden proof-of-origin token and quietly return nothing without it. This post shows a way that works from a server, with one HTTP call, from Python, from curl, or from n8n.
The one-call version (curl)
Apify Actors can be called synchronously: you POST the input and get the results back in the same response.
curl -X POST \
"https://api.apify.com/v2/acts/scrapemole~youtube-transcript-scraper/run-sync-get-dataset-items" \
-H "Authorization: Bearer $APIFY_TOKEN" \
-H "Content-Type: application/json" \
-d '{"videos": ["https://youtu.be/jNQXAC9IVRw"], "languages": ["en"]}'
You get a free token by signing up at Apify (the free plan includes monthly credit). The response is a JSON array with one row per video. Trimmed, from a real run on 23 October 2026:
[{
"videoId": "jNQXAC9IVRw",
"status": "ok",
"title": "Me at the zoo",
"channelName": "jawed",
"language": "en",
"isAutoGenerated": false,
"transcriptText": "All right, so here we are, in front of the elephants ...",
"segments": [{ "start": 1.2, "duration": 2.16, "end": 3.36, "text": "All right, so here we are, in front of the elephants" }],
"segmentCount": 6,
"wordCount": 39
}]
transcriptText is the whole thing as one string, ready for an LLM. segments keeps the timestamps if you need to link back to a moment in the video. Watch links, youtu.be links, Shorts, live and embed URLs and bare IDs all work.
Python: summarize a list of videos
# pip install apify-client
import os
from apify_client import ApifyClient
client = ApifyClient(os.environ["APIFY_TOKEN"])
videos = [
"https://www.youtube.com/watch?v=aircAruvnKk",
"https://youtu.be/jNQXAC9IVRw",
]
run = client.actor("scrapemole/youtube-transcript-scraper").call(
run_input={"videos": videos, "languages": ["en"]}
)
for item in client.dataset(run["defaultDatasetId"]).iterate_items():
if item["status"] != "ok":
print(item["videoId"], item["errorCode"], item["errorMessage"])
continue
text = item["transcriptText"]
print(f'{item["title"]} ({item["wordCount"]} words)')
# hand `text` to the model of your choice here, e.g. "Summarize in 5 bullets"
Two things worth handling:
- Videos without captions come back as a row with
status: "error"anderrorCode: "NO_DATA", plus the list of languages that are available when there are some. They're not charged. If you need text for those, you need speech-to-text instead. - Other languages: pass
"languages": ["es", "pt-BR"]to prefer certain tracks, or"translateTo": "en"to get YouTube's own translation. The row'slanguageandisTranslatedfields tell you what you got.
n8n: transcript into any workflow
You don't need a community node. Use the built-in HTTP Request node:
- Method: POST
- URL:
https://api.apify.com/v2/acts/scrapemole~youtube-transcript-scraper/run-sync-get-dataset-items - Authentication: Header Auth, name
Authorization, valueBearer YOUR_APIFY_TOKEN - Body (JSON):
{"videos": ["{{ $json.videoUrl }}"], "languages": ["en"]}
Each output item is one video, so the next node (an OpenAI/Anthropic node, Notion, Google Sheets, a Slack message) can read {{ $json.transcriptText }} directly. A typical flow is: RSS feed of a channel, then this HTTP Request, then an LLM summary, then a post to your notes app. The same request works in Make's HTTP module.
If you were already calling another transcript Actor such as pintostudio/youtube-transcript-scraper from n8n or Make, you can keep your existing input (videoUrl, targetLanguage) and just change the Actor ID.
What it costs
You pay per transcript delivered: $0.004 on Apify's free plan, down to $0.002 on higher plans, so 1,000 transcripts is $2 to $4. Proxies are included, and failed, private or caption-less videos aren't charged. You can set a max cost per run and it stops cleanly at that limit.
Related
- YouTube Transcript Scraper on Apify
- YouTube Comments Scraper, if you want what viewers said too
- YouTube Channel Scraper, to list every video on a channel first
- All our Actors: apify.com/scrapemole
Questions or a video that doesn't work? Open an issue on the Actor page or email us and I'll look at it.