
Company News
Socket Named Top Sales Organization by RepVue
Socket won two 2026 Reppy Awards from RepVue, ranking in the top 5% of all sales orgs. AE Alexandra Lister shares what it's like to grow a sales career here.
@osiris-ai/youtube-captions-sdk
Advanced tools
A JavaScript/TypeScript SDK for fetching YouTube video transcripts and captions without API keys or headless browsers
A modern JavaScript/TypeScript SDK for fetching YouTube video transcripts and captions. No API keys required, no headless browsers needed!
This SDK is inspired by the popular Python youtube-transcript-api and provides the same functionality for JavaScript/TypeScript applications.
npm install @osiris-ai/youtube-captions-sdk
yarn add @osiris-ai/youtube-captions-sdk
pnpm add @osiris-ai/youtube-captions-sdk
import { TranscriptList } from '@osiris-ai/youtube-captions-sdk';
// Fetch transcript for a YouTube video
const videoId = 'dQw4w9WgXcQ'; // Rick Astley - Never Gonna Give You Up
const transcriptList = await TranscriptList.fetch(videoId);
// Get the first available transcript
const transcript = transcriptList.find(['en', 'en-US']);
const fetchedTranscript = await transcript.fetch();
// Access the transcript data
console.log(fetchedTranscript.snippets);
/*
[
{
text: "Never gonna give you up",
start: 0.0,
duration: 3.5
},
{
text: "Never gonna let you down",
start: 3.5,
duration: 4.2
}
// ... more snippets
]
*/
The main entry point for fetching transcripts.
TranscriptList.fetch(videoId: string): Promise<TranscriptList>Fetches all available transcripts for a YouTube video.
const transcriptList = await TranscriptList.fetch('dQw4w9WgXcQ');
Parameters:
videoId (string): YouTube video ID (not the full URL)Returns: Promise resolving to a TranscriptList instance
transcriptList.find(languageCodes: string[], preferGenerated?: boolean): TranscriptFinds a transcript in the specified languages.
// Find English transcript (manual preferred)
const transcript = transcriptList.find(['en', 'en-US']);
// Find transcript, preferring auto-generated
const transcript = transcriptList.find(['en', 'en-US'], true);
Parameters:
languageCodes (string[]): Array of language codes to search forpreferGenerated (boolean, optional): Whether to prefer auto-generated transcriptsReturns: Transcript instance
Represents a single transcript in a specific language.
videoId (string): The YouTube video IDlanguage (string): Human-readable language namelanguageCode (string): Language code (e.g., 'en', 'es')isGenerated (boolean): Whether this is an auto-generated transcriptisTranslatable (boolean): Whether this transcript can be translatedtranscript.fetch(preserve?: boolean): Promise<FetchedTranscript>Fetches the actual transcript content.
const fetchedTranscript = await transcript.fetch();
// Preserve HTML formatting in transcript text
const fetchedTranscript = await transcript.fetch(true);
Parameters:
preserve (boolean, optional): Whether to preserve HTML formattingReturns: Promise resolving to a FetchedTranscript object
transcript.translate(languageCode: string): TranscriptTranslates the transcript to another language.
const englishTranscript = transcriptList.find(['en']);
const spanishTranscript = englishTranscript.translate('es');
const spanishContent = await spanishTranscript.fetch();
Parameters:
languageCode (string): Target language codeReturns: New Transcript instance for the translated content
The actual transcript content with timing information.
interface FetchedTranscript {
snippets: FetchedTranscriptSnippet[];
videoId: string;
language: string;
languageCode: string;
isGenerated: boolean;
}
interface FetchedTranscriptSnippet {
text: string;
start: number; // Start time in seconds
duration: number; // Duration in seconds
}
const transcriptList = await TranscriptList.fetch('dQw4w9WgXcQ');
// Try multiple languages in order of preference
try {
const transcript = transcriptList.find(['en', 'en-US', 'es', 'fr']);
const content = await transcript.fetch();
console.log(`Found transcript in: ${transcript.language}`);
} catch (error) {
console.log('No transcript found in preferred languages');
}
const transcriptList = await TranscriptList.fetch('dQw4w9WgXcQ');
for (const transcript of transcriptList) {
console.log(`${transcript.language} (${transcript.languageCode})`);
console.log(`Generated: ${transcript.isGenerated}`);
console.log(`Translatable: ${transcript.isTranslatable}`);
}
const transcriptList = await TranscriptList.fetch('dQw4w9WgXcQ');
const englishTranscript = transcriptList.find(['en']);
if (englishTranscript.isTranslatable) {
// Translate to Spanish
const spanishTranscript = englishTranscript.translate('es');
const spanishContent = await spanishTranscript.fetch();
console.log('Spanish transcript:', spanishContent.snippets);
}
const transcriptList = await TranscriptList.fetch('dQw4w9WgXcQ');
const transcript = transcriptList.find(['en']);
const content = await transcript.fetch();
// Get full text
const fullText = content.snippets.map(s => s.text).join(' ');
// Get text for a specific time range (e.g., first 30 seconds)
const first30Seconds = content.snippets
.filter(s => s.start < 30)
.map(s => s.text)
.join(' ');
// Format as SRT-style subtitles
const srtFormat = content.snippets
.map((snippet, index) => {
const start = formatTime(snippet.start);
const end = formatTime(snippet.start + snippet.duration);
return `${index + 1}\n${start} --> ${end}\n${snippet.text}\n`;
})
.join('\n');
function formatTime(seconds: number): string {
const h = Math.floor(seconds / 3600);
const m = Math.floor((seconds % 3600) / 60);
const s = Math.floor(seconds % 60);
const ms = Math.floor((seconds % 1) * 1000);
return `${h.toString().padStart(2, '0')}:${m.toString().padStart(2, '0')}:${s.toString().padStart(2, '0')},${ms.toString().padStart(3, '0')}`;
}
The SDK throws descriptive errors for common issues:
try {
const transcriptList = await TranscriptList.fetch('invalid_video_id');
} catch (error) {
if (error.message.includes('YouTube request failed')) {
console.log('Video not found or private');
}
}
try {
const transcript = transcriptList.find(['nonexistent_language']);
} catch (error) {
if (error.message.includes('Transcript not found')) {
console.log('No transcript available in requested language');
}
}
try {
const translated = transcript.translate('invalid_code');
} catch (error) {
if (error.message.includes('Translation unavailable')) {
console.log('Translation to this language is not supported');
}
}
The SDK is built with TypeScript and provides full type definitions:
import {
TranscriptList,
Transcript,
FetchedTranscript,
FetchedTranscriptSnippet
} from '@osiris-ai/youtube-captions-sdk';
// All types are automatically inferred
const transcriptList: TranscriptList = await TranscriptList.fetch('dQw4w9WgXcQ');
const transcript: Transcript = transcriptList.find(['en']);
const content: FetchedTranscript = await transcript.fetch();
const snippets: FetchedTranscriptSnippet[] = content.snippets;
The SDK supports all languages available on YouTube, including:
Common language codes:
en - Englishes - Spanishfr - Frenchde - Germanit - Italianpt - Portugueseru - Russianja - Japaneseko - Koreanzh - ChinesedQw4w9WgXcQ), not the full URLWe welcome contributions! Please see our Contributing Guide for details.
This project is licensed under the MIT License - see the LICENSE file for details.
Made with ❤️ by Osiris Labs
FAQs
A JavaScript/TypeScript SDK for fetching YouTube video transcripts and captions without API keys or headless browsers
We found that @osiris-ai/youtube-captions-sdk demonstrated a healthy version release cadence and project activity because the last version was released less than a year ago. It has 1 open source maintainer collaborating on the project.
Did you know?

Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.

Company News
Socket won two 2026 Reppy Awards from RepVue, ranking in the top 5% of all sales orgs. AE Alexandra Lister shares what it's like to grow a sales career here.

Security News
NIST will stop enriching most CVEs under a new risk-based model, narrowing the NVD's scope as vulnerability submissions continue to surge.

Company News
/Security News
Socket is an initial recipient of OpenAI's Cybersecurity Grant Program, which commits $10M in API credits to defenders securing open source software.