Skip to content
← All posts
TutorialJavaScript

How to Get a YouTube Transcript in JavaScript

Hussein Hakizimana··4 min read

Getting a YouTube transcript used to mean either relying on the official API (which is rate-limited and doesn't actually give you transcript text), scraping the page, or hacking together a workaround. This post shows how to do it properly with one fetch call.

We'll use Stophy. You send a video URL, you get back the transcript text and timestamps. No browser automation, no parsing HTML.

Setup

You need Node.js 18+ (fetch is built in) and a Stophy API key. Grab one from stophy.dev/dashboard.

Get the transcript

js
1async function getTranscript(videoUrl) {
2 const res = await fetch('https://api.stophy.dev/v1/video', {
3 method: 'POST',
4 headers: {
5 'Authorization': `Bearer ${process.env.STOPHY_API_KEY}`,
6 'Content-Type': 'application/json',
7 },
8 body: JSON.stringify({ videoUrl, type: 'transcript' }),
9 });
10
11 if (!res.ok) throw new Error(`Request failed: ${res.status}`);
12 const { data } = await res.json();
13 return data;
14}
15
16const data = await getTranscript('https://www.youtube.com/watch?v=YOUR_VIDEO_ID');
17console.log(data.text);

data.text is the full transcript as a single string — useful for passing directly to an LLM or writing to a file.

Working with timestamps

The segments array gives you each chunk of text with its start time. Handy for linking to specific moments or chunking for embeddings:

js
1for (const segment of data.segments) {
2 const minutes = Math.floor(segment.start / 60).toString().padStart(2, '0');
3 const seconds = Math.floor(segment.start % 60).toString().padStart(2, '0');
4 console.log(`[${minutes}:${seconds}] ${segment.text}`);
5}

Each segment has text, start (in seconds), and duration.

Check if it's auto-generated

js
1const { language } = data;
2console.log(language.isAutoGenerated); // true or false

Auto-generated captions are fine for most videos, but if you're processing something where exact wording matters — interviews, legal content, technical talks — it's good to know what you're working with.

Some videos have no transcript

The API returns a 200 with an empty field instead of throwing an error:

js
1if ('empty' in data) {
2 console.log('No transcript available:', data.empty.code);
3} else {
4 console.log(data.text);
5}

Full script

js
1async function getTranscript(videoUrl) {
2 const res = await fetch('https://api.stophy.dev/v1/video', {
3 method: 'POST',
4 headers: {
5 'Authorization': `Bearer ${process.env.STOPHY_API_KEY}`,
6 'Content-Type': 'application/json',
7 },
8 body: JSON.stringify({ videoUrl, type: 'transcript' }),
9 });
10
11 if (!res.ok) throw new Error(`Request failed: ${res.status}`);
12 const { data } = await res.json();
13
14 if ('empty' in data) return null;
15 return data.text;
16}
17
18const transcript = await getTranscript('https://www.youtube.com/watch?v=YOUR_VIDEO_ID');
19if (transcript) {
20 console.log(transcript);
21} else {
22 console.log('No transcript for this video.');
23}

The docs have the full response shape and the rest of the endpoints.