# How do I get a YouTube transcript with timestamps as JSON or SRT?

> Get a YouTube video's timed transcript as JSON segments, turn it into an SRT file or links that jump to the second something was said. Price per video and code.

Canonical page: https://okdata.online/answers/youtube-transcript-timestamps-srt/

**Short answer: **The YouTube transcript endpoint returns every caption line as a segment with start and end in seconds, plus the full text, for $0.004 per video. Keep the JSON as it is, or write the segments out as SRT with a dozen lines of Python; timestamps cost nothing extra.

A podcast clip editor wants every place a guest mentions a product, with a link that opens the video at that second. A plain transcript is not enough; you need when each line was said. [YouTube video transcript](/apis/youtube/videos/transcript/get/) returns that in the same call as the text.

## What the JSON looks like

The transcript sits in `data.item` of the response:

```json
{
  "video_id": "dQw4w9WgXcQ",
  "lang": "en",
  "text": "We're no strangers to love ...",
  "segments": [
    { "start": 18.64, "end": 21.88, "text": "We're no strangers to love" },
    { "start": 22.64, "end": 26.92, "text": "You know the rules and so do I" }
  ]
}
```

Times are seconds from the start of the video. Libraries that report `duration` instead: it is `end - start`.

## From segments to SRT

```python
import os, requests

body = requests.get(
    "https://api.okdata.online/v1/youtube/videos/transcript/get",
    headers={"Authorization": f"Bearer {os.environ['OKDATA_API_KEY']}"},
    params={"id": "dQw4w9WgXcQ", "lang": "en"}, timeout=60,
).json()
segments = body["data"]["item"]["segments"]

def srt_time(sec):
    ms = int(round(sec * 1000))
    return f"{ms // 3_600_000:02}:{ms // 60_000 % 60:02}:{ms // 1000 % 60:02},{ms % 1000:03}"

with open("dQw4w9WgXcQ.srt", "w", encoding="utf-8") as f:
    for n, s in enumerate(segments, 1):
        f.write(f"{n}\n{srt_time(s['start'])} --> {srt_time(s['end'])}\n{s['text']}\n\n")
```

For WebVTT, start the file with `WEBVTT` and use a dot instead of the comma before the milliseconds.

## Links that jump to the moment

`https://www.youtube.com/watch?v=dQw4w9WgXcQ&t=18s` opens the video at second 18. Round `start` down and you can put a clickable source next to every quote an AI pulls from the transcript, which makes summaries easy to check.

## Price

| Job | Cost |
|---|---|
| One video, text plus timings | $0.004 |
| A 100-episode back catalogue | $0.40 |
| 1,000 videos | $4.00 |

Timings come with every transcript. Videos without captions return `not_found` and are not charged.

## Things to know before you ship the file

- Automatic captions often overlap: a line can end after the next one starts. If a player complains, clip each `end` to the next `start`.
- Lines follow how YouTube split the captions, so they are short and not sentence-aligned. Join segments before quoting a full sentence.
- The endpoint takes the 11-character ID, not a URL.
- No styling, positions or speaker labels come back; only text and time.

## Other ways to get timed captions

- yt-dlp with `--write-subs --convert-subs srt` writes the file directly when it is not blocked on your network.
- On your own channel, the official Data API downloads captions in SRT through `tfmt`.
- Without captions, Whisper produces timestamps from audio you are allowed to use.

Batch work and costs for whole channels are on the [video transcript solution page](/solutions/transcripts/).

## Endpoints used

- [YouTube video transcript](https://okdata.online/apis/youtube/videos/transcript/get/) `youtube.videos.transcript.get`: $0.004 per call

Updated 2026-11-12
