> ## Documentation Index
> Fetch the complete documentation index at: https://docs.transcriptmagic.com/llms.txt
> Use this file to discover all available pages before exploring further.

# YouTube

> POST any YouTube URL — Shorts, long-form, live replays — and get back a JSON transcript with per-line timing.

```http theme={null}
POST https://api.transcriptmagic.com/api/youtube/transcript
```

Works on watch URLs, `youtu.be` short links, `/shorts/` paths, and `m.youtube.com` mobile URLs.

## Request

<CodeGroup>
  ```bash cURL theme={null}
  curl -X POST https://api.transcriptmagic.com/api/youtube/transcript \
    -H "Authorization: Bearer YOUR_API_KEY" \
    -H "Content-Type: application/json" \
    -d '{"url":"https://www.youtube.com/watch?v=dQw4w9WgXcQ"}'
  ```

  ```python Python theme={null}
  import requests

  response = requests.post(
      "https://api.transcriptmagic.com/api/youtube/transcript",
      headers={"Authorization": "Bearer YOUR_API_KEY"},
      json={"url": "https://www.youtube.com/watch?v=dQw4w9WgXcQ"},
  )

  data = response.json()
  # transcript is an array of timed segments
  for seg in data["transcript"]:
      print(seg["startTimeText"], seg["text"])
  ```

  ```javascript JavaScript theme={null}
  const response = await fetch("https://api.transcriptmagic.com/api/youtube/transcript", {
    method: "POST",
    headers: {
      "Authorization": "Bearer YOUR_API_KEY",
      "Content-Type": "application/json",
    },
    body: JSON.stringify({ url: "https://www.youtube.com/watch?v=dQw4w9WgXcQ" }),
  });

  const data = await response.json();
  // transcript is an array of timed segments
  for (const seg of data.transcript) {
    console.log(seg.startTimeText, seg.text);
  }
  ```

  ```go Go theme={null}
  package main

  import (
  	"bytes"
  	"encoding/json"
  	"fmt"
  	"net/http"
  )

  func main() {
  	body, _ := json.Marshal(map[string]string{
  		"url": "https://www.youtube.com/watch?v=dQw4w9WgXcQ",
  	})

  	req, _ := http.NewRequest("POST",
  		"https://api.transcriptmagic.com/api/youtube/transcript",
  		bytes.NewBuffer(body))
  	req.Header.Set("Authorization", "Bearer YOUR_API_KEY")
  	req.Header.Set("Content-Type", "application/json")

  	resp, _ := http.DefaultClient.Do(req)
  	defer resp.Body.Close()

  	var data struct {
  		Transcript []struct {
  			Text          string `json:"text"`
  			StartMs       string `json:"startMs"`
  			EndMs         string `json:"endMs"`
  			StartTimeText string `json:"startTimeText"`
  		} `json:"transcript"`
  		TranscriptOnlyText string `json:"transcript_only_text"`
  		Language           string `json:"language"`
  	}
  	json.NewDecoder(resp.Body).Decode(&data)
  	fmt.Println(data.TranscriptOnlyText)
  }
  ```

  ```php PHP theme={null}
  <?php
  $ch = curl_init('https://api.transcriptmagic.com/api/youtube/transcript');

  curl_setopt($ch, CURLOPT_POST, true);
  curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
  curl_setopt($ch, CURLOPT_HTTPHEADER, [
      'Authorization: Bearer YOUR_API_KEY',
      'Content-Type: application/json',
  ]);
  curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode([
      'url' => 'https://www.youtube.com/watch?v=dQw4w9WgXcQ',
  ]));

  $response = curl_exec($ch);
  curl_close($ch);

  $data = json_decode($response, true);
  // transcript is an array of timed segments
  foreach ($data['transcript'] as $seg) {
      echo $seg['startTimeText'] . ' ' . $seg['text'] . "\n";
  }
  ```
</CodeGroup>

## Response

```json theme={null}
{
  "success": true,
  "type": "video",
  "url": "https://www.youtube.com/watch?v=dQw4w9WgXcQ",
  "transcript": [
    {
      "text": "We're no strangers to love",
      "startMs": "18800",
      "endMs": "25960",
      "startTimeText": "0:18"
    },
    {
      "text": "You know the rules and so do I",
      "startMs": "21800",
      "endMs": "29119",
      "startTimeText": "0:21"
    }
  ],
  "transcript_only_text": "We're no strangers to love. You know the rules and so do I...",
  "language": "English",
  "videoId": "dQw4w9WgXcQ",
  "captionTracks": [
    {
      "baseUrl": "https://www.youtube.com/api/timedtext?...",
      "name": { "simpleText": "English" },
      "languageCode": "en",
      "isTranslatable": true
    }
  ],
  "credits": 997
}
```

The YouTube endpoint returns the per-line timed array directly as `transcript` — there is no separate `segments` field. If you just want the text without timings, read `transcript_only_text` instead.

## Supported URL formats

| Format                      | Example                                  |
| --------------------------- | ---------------------------------------- |
| Standard watch URL          | `https://www.youtube.com/watch?v=…`      |
| YouTube Shorts              | `https://www.youtube.com/shorts/…`       |
| `youtu.be` short link       | `https://youtu.be/…`                     |
| Mobile URL                  | `https://m.youtube.com/watch?v=…`        |
| Live replay (with captions) | Any of the above, completed live streams |

## FAQ

<AccordionGroup>
  <Accordion title="Does it work on YouTube Shorts?">
    Yes. Any public YouTube URL works — Shorts (`youtube.com/shorts/…`), long-form videos, live replays, mobile links, and `youtu.be` short links are all accepted. Just POST the full URL.
  </Accordion>

  <Accordion title="What about age-restricted or unlisted videos?">
    Unlisted videos work as long as you provide the full URL. Age-restricted videos that require sign-in are **not** supported — the API can only fetch publicly viewable captions.
  </Accordion>

  <Accordion title="Which languages does the API support?">
    Whichever caption track YouTube exposes — that covers 100+ languages for auto-captions and every language creators manually publish. The `language` field on the response tells you which track was returned, and `captionTracks` lists every available track for the video. Translation is a separate step you run after fetching.
  </Accordion>

  <Accordion title="Do I get timestamps I can use for subtitles?">
    Yes. Each item in the `transcript` array includes `startMs`, `endMs`, and `startTimeText` — build SRT/VTT, chaptered summaries, or jump-to-moment UI directly from the response. See the [response schema](/api-reference/response-schema) page for an SRT generator example.
  </Accordion>

  <Accordion title="How accurate is the transcript?">
    When the creator has uploaded manual captions, accuracy is essentially 100%. When only YouTube auto-captions exist, accuracy matches YouTube's own ASR — very good for clear speech, weaker on heavy music.
  </Accordion>
</AccordionGroup>
