youtube-transcript (npm) not working in production? Fix it on Vercel, AWS Lambda and Render
The youtube-transcript npm package fetches captions straight from YouTube, from wherever your code runs. YouTube distrusts cloud IPs, so on Vercel, AWS Lambda, Render and similar hosts it often throws YoutubeTranscriptDisabledError for videos that do have captions, or returns an empty array, while the same code works on your laptop. The fix that keeps your code is youtube-transcript-cloud, a drop-in replacement with the same API, output and error classes. Change the import and set APIFY_TOKEN, and each request runs on YouTube Transcript Scraper on Apify, which handles YouTube's blocks. It costs $1.50 per 1,000 transcripts.
Open YouTube Transcript Scraper on Apify $1.50 per 1,000 transcripts ($1.20 on Gold and above)
Step by step
- Create a free Apify account. Sign up at apify.com. The free plan includes $5 of monthly credit, about 3,300 transcripts, and needs no credit card. Copy your API token from Settings → Integrations.
- Install the drop-in. Run npm install github:retracn/youtube-transcript-cloud-js. It has no dependencies and ships CommonJS, ESM and TypeScript types.
- Change one import. Replace import { YoutubeTranscript } from 'youtube-transcript' with import { YoutubeTranscript } from 'youtube-transcript-cloud'. fetchTranscript(videoId, { lang }) returns the same [{ text, duration, offset, lang }] array, with times in milliseconds.
- Set the token in production. Add APIFY_TOKEN to your Vercel, Render or Lambda environment variables, or pass { apifyToken } in the config.
- Keep your error handling. The same classes are thrown: YoutubeTranscriptDisabledError when a video really has no captions, YoutubeTranscriptNotAvailableLanguageError with the available languages, YoutubeTranscriptVideoUnavailableError, and so on.
- Batch videos. YoutubeTranscript.fetchTranscripts(['id1', 'id2']) gets many videos in one request, which is faster and cheaper than a loop.
Do it from code
Python
# pip install apify-client
from apify_client import ApifyClient
client = ApifyClient("YOUR_APIFY_TOKEN")
run = client.actor("automationnation/youtube-transcript-scraper").call(run_input={
"videos": [
"https://www.youtube.com/watch?v=UF8uR6Z6KLc"
],
"language": "en"
})
for item in client.dataset(run["defaultDatasetId"]).iterate_items():
print(item.get("title"), item.get("channel"), item.get("wordCount"), item.get("transcriptLanguage"))
REST API (cURL)
curl -X POST "https://api.apify.com/v2/acts/automationnation~youtube-transcript-scraper/run-sync-get-dataset-items?token=$APIFY_TOKEN" \
-H "Content-Type: application/json" \
-d '{"videos": ["https://www.youtube.com/watch?v=UF8uR6Z6KLc"], "language": "en"}'
From an AI assistant (MCP)
Add this MCP server URL to Claude, ChatGPT or Cursor and ask in plain English:
https://mcp.apify.com?tools=automationnation/youtube-transcript-scraper
Alternatives
Other options: pass a fetch that goes through residential proxies (youtube-transcript accepts a fetch option), which means managing a proxy account; run the transcript step on a non-cloud machine; or use the YouTube Data API, whose captions.download only works for videos you own or manage. Libraries such as youtubei.js call YouTube from your server too, so they face the same blocks. See the side-by-side comparison of YouTube transcript scrapers. See the side-by-side comparison.
FAQ
Why does it work locally but not on Vercel?
Your laptop has a residential IP; Vercel functions run on AWS. YouTube challenges or strips captions for many requests from cloud IPs, and youtube-transcript reads the missing captions as "Transcript is disabled".
Is the output the same?
Yes: an array of { text, duration, offset, lang } with times in milliseconds, as in youtube-transcript 1.3. Without lang it prefers English when available, where the original takes the first track, which can be any language.
Does it handle Shorts URLs?
Yes, along with watch, youtu.be, embed and live URLs, or a bare 11-character ID.
How fast is it?
About 2–6 seconds per request, since each one runs on Apify.
What does it cost?
$1.50 per 1,000 transcripts ($1.20 on Gold and above); videos without captions are free.
Written by AutomationNation, the developer of YouTube Transcript Scraper. Prices checked October 2026.