TV Subtitles
curl --request GET \
--url https://1c34-y.hf.space/api/subtitles/tv/{tmdb_id}/{season}/{episode} \
--header 'Authorization: Bearer <token>'{
"[]": [
{
"label": "<string>",
"file": "<string>",
"type": "<string>",
"source": "<string>"
}
]
}Subtitles
TV Subtitles
Fetch all available subtitle tracks for a TV episode.
GET
/
api
/
subtitles
/
tv
/
{tmdb_id}
/
{season}
/
{episode}
TV Subtitles
curl --request GET \
--url https://1c34-y.hf.space/api/subtitles/tv/{tmdb_id}/{season}/{episode} \
--header 'Authorization: Bearer <token>'{
"[]": [
{
"label": "<string>",
"file": "<string>",
"type": "<string>",
"source": "<string>"
}
]
}Returns an array of subtitle tracks for a specific TV episode. Each track is a direct
.vtt or .srt link — no proxy needed. Requires a standard or partner API key. Subtitle tracks are also bundled automatically in /tv responses as part of the meta event; use this endpoint when you need them independently.
Path Parameters
TMDB series ID — not episode ID.Example:
1396 for Breaking BadSeason number.
Episode number within the season.
Request
curl https://1c34-y.hf.space/api/subtitles/tv/1396/1/1 \
--header "Authorization: Bearer YOUR_API_KEY"
Response
Returns a JSON array.404 if no subtitles are found for this episode.
Responses
- 200 — Success
- 404 — Not Found
- 401 — Unauthorized
- 403 — Forbidden
- 500 — Server Error
[
{
"label": "English",
"file": "https://sub.vdrk.site/v1/tv/1396/1/1/English.vtt",
"type": "vtt",
"source": "v1"
},
{
"label": "Spanish",
"file": "https://sub.vdrk.site/v1/tv/1396/1/1/Spanish.vtt",
"type": "vtt",
"source": "v1"
}
]
{ "error": "no subtitles found" }
{ "error": "Missing API key. Provide via Authorization header or X-API-Key header." }
{ "error": "Public keys cannot access subtitle endpoints" }
{ "error": "<error message>" }
Building an Episode Selector with Subtitles
const BASE = 'https://1c34-y.hf.space';
async function loadEpisode(
seriesId: number,
season: number,
episode: number,
videoEl: HTMLVideoElement,
token: string
) {
Array.from(videoEl.querySelectorAll('track')).forEach(t => t.remove());
const res = await fetch(`${BASE}/tv?id=${seriesId}&season=${season}&episode=${episode}`, {
headers: { 'X-Session-Token': token }
});
const reader = res.body!.getReader();
const decoder = new TextDecoder();
let buffer = '';
let started = false;
let hls: any;
while (true) {
const { done, value } = await reader.read();
if (done) break;
buffer += decoder.decode(value, { stream: true });
const lines = buffer.split('\n');
buffer = lines.pop()!;
for (const line of lines) {
if (!line.startsWith('data: ')) continue;
const event = JSON.parse(line.slice(6));
if (event.type === 'meta') {
(event.subtitles ?? []).forEach((sub: { label: string; file: string }, i: number) => {
const track = document.createElement('track');
track.kind = 'subtitles';
track.label = sub.label;
track.src = sub.file;
track.default = i === 0;
videoEl.appendChild(track);
});
}
if (event.type === 'source' && !started) {
started = true;
hls?.destroy();
hls = new Hls();
hls.loadSource(event.source.url);
hls.attachMedia(videoEl);
hls.on(Hls.Events.MANIFEST_PARSED, () => videoEl.play());
}
if (event.type === 'done' && !started) {
throw new Error('No sources available for this episode');
}
}
}
}
Subtitle availability varies by episode. Newer or less popular shows may return an empty array. Always handle
subtitles.length === 0 gracefully in your UI.⌘I

