@namaki/youtube-transcript-ts
v1.0.4
Published
Fetch YouTube video transcripts via the Innertube API
Maintainers
Readme
youtube-transcript-ts
Fetch YouTube video transcripts via the Innertube API. TypeScript port of jdepoix/youtube-transcript-api.
Install
npm install @namaki/youtube-transcript-tsUsage
Fetch a transcript
import { getTranscript } from "@namaki/youtube-transcript-ts"
const result = await getTranscript({ videoId: "dQw4w9WgXcQ" })
if (result.ok) {
console.log(result.language) // "en"
console.log(result.autoGenerated) // true
console.log(result.data)
// [{ text: "Never gonna give you up", start: 18.0, duration: 3.2 }, ...]
}Accept full URLs
videoId accepts raw 11-character IDs or full YouTube URLs:
await getTranscript({ videoId: "https://www.youtube.com/watch?v=dQw4w9WgXcQ" })
await getTranscript({ videoId: "https://youtu.be/dQw4w9WgXcQ" })
await getTranscript({ videoId: "https://www.youtube.com/shorts/dQw4w9WgXcQ" })Request a specific language
const result = await getTranscript({ videoId: "dQw4w9WgXcQ", lang: "es" })Text only (no timestamps)
const result = await getTranscript({ videoId: "dQw4w9WgXcQ", timestamps: false })
// result.data = [{ text: "Never gonna give you up" }, ...]List available languages
import { listAvailableLanguages } from "@namaki/youtube-transcript-ts"
const result = await listAvailableLanguages("dQw4w9WgXcQ")
if (result.ok) {
console.log(result.data)
// [{ code: "en", name: "English", autoGenerated: true }, ...]
}Parse raw json3 data
If you already have cached or proxied json3 caption data:
import { parseJson3 } from "@namaki/youtube-transcript-ts"
const segments = parseJson3(json3Data, true)
// [{ text: "Hello", start: 1.0, duration: 2.0 }, ...]Extract a video ID from a URL
import { parseVideoId } from "@namaki/youtube-transcript-ts"
parseVideoId("https://www.youtube.com/watch?v=dQw4w9WgXcQ") // "dQw4w9WgXcQ"
parseVideoId("https://youtu.be/dQw4w9WgXcQ") // "dQw4w9WgXcQ"
parseVideoId("bad-input") // nullError handling
This library uses result unions instead of thrown exceptions. Every function returns { ok: true, ... } on success or { ok: false, code, message } on failure. TypeScript's type narrowing guides you to handle all cases:
const result = await getTranscript({ videoId: "dQw4w9WgXcQ" })
if (!result.ok) {
switch (result.code) {
case "INVALID_VIDEO_ID":
// The input wasn't a valid video ID or YouTube URL
break
case "NO_CAPTIONS":
// The video has no caption tracks
break
case "LANG_NOT_AVAILABLE":
// The requested language doesn't exist for this video
break
case "FETCH_FAILED":
// Network error or unexpected HTTP status
break
}
return
}
// result.ok is true — result.data, result.language, result.autoGenerated are availableAPI
getTranscript(options): Promise<TranscriptResult>
| Option | Type | Default | Description |
|---|---|---|---|
| videoId | string | required | Video ID or full YouTube URL |
| lang | string | first available | Language code (e.g. "en", "es") |
| timestamps | boolean | true | Include start and duration on segments |
listAvailableLanguages(videoId): Promise<LanguageListResult>
Returns available caption tracks for a video. Each entry has code, name, and autoGenerated.
parseJson3(data, timestamps): TranscriptSegment[]
Parses YouTube's json3 caption format into transcript segments.
parseVideoId(input): string | null
Extracts an 11-character video ID from a raw ID or YouTube URL. Returns null if invalid.
Types
type TranscriptSegment = {
text: string
start?: number
duration?: number
}
type TranscriptSuccess = {
ok: true
code: "TRANSCRIPT_FOUND"
data: TranscriptSegment[]
language: string
autoGenerated: boolean
}
type TranscriptError = {
ok: false
code: "NO_CAPTIONS" | "LANG_NOT_AVAILABLE" | "FETCH_FAILED" | "INVALID_VIDEO_ID"
message: string
}
type LanguageInfo = {
code: string
name: string
autoGenerated: boolean
}Disclaimer
This library uses YouTube's internal Innertube API, which is not a publicly documented or supported API. It may break without notice if YouTube changes its internal endpoints or data formats.
This project is not affiliated with, endorsed by, or sponsored by YouTube or Google. Use of this library may be subject to YouTube's Terms of Service. It is your responsibility to ensure that your use complies with all applicable terms, policies, and laws — including copyright and data protection regulations.
This library is provided "as is" with no warranty. The authors are not liable for any damages or legal consequences arising from its use. Use at your own risk.
License
MIT
