Search, download, and upload subtitles programmatically.
The Subtitles Search API lets you search for movie and TV show subtitles by film name, file name, IDs (IMDb, TMDB, SubDL), season and episode numbers, type (movie or TV), release year, and language.
Endpoint: https://api.subdl.com/api/v1/subtitles
Method: GET
You can get a free API key from your SubDL account panel.
Pass parameters in the URL query string. api_key is required, plus at least one search parameter (film_name, file_name, sd_id, imdb_id, or tmdb_id).
| Parameter | Required | Description |
|---|---|---|
api_key | Yes | Your API key from your SubDL account. |
film_name | No | Text search by film name. |
file_name | No | Search by file name. |
sd_id | No | Search by SubDL ID. |
imdb_id | No | Search by IMDb ID. |
tmdb_id | No | Search by TMDB ID. |
type | No | Content type: movie or tv. |
season_number | No | Season number, for TV shows. |
episode_number | No | Episode number, for TV shows. |
year | No | Release year of the movie or TV show. |
languages | No | Comma-separated language codes, e.g. EN,FR. See the list of supported languages. |
subs_per_page | No | Number of subtitles returned per page. Default 10, maximum 30. |
comment | No | Set comment=1 to include the author comment for each subtitle. |
releases | No | Set releases=1 to include the release list for each subtitle. |
hi | No | Set hi=1 to include the hearing-impaired flag for each subtitle. |
full_season | No | Set full_season=1 to return full-season subtitle packs. |
unpack | No | Set unpack=1 to include the individual episode files saved inside packed/full-season subtitles. |
client | No | Identify your integration: bazarr, stremio, kodi, subdl_player, custom_integration, or other. |
A successful response returns a JSON object with these fields:
true on success.results.0 means default/unknown). See the framerate table in the Upload API docs.23.976, or null when unknown/default.unpack=1. Each item is one saved subtitle file from the pack and includes file_n_id, name, release_name, season, episode, language, hi, format, size, md5, and url.An error response returns a JSON object with these fields:
false on failure.Append the subtitle url from the response to the dl.subdl.com endpoint:
https://dl.subdl.com/subtitle/3197651-3213944.zip
When unpack=1 is used, individual raw subtitle files can be downloaded from the returned file URL:
https://dl.subdl.com/subtitle/{n_id}/{file_n_id}
Paid API users can authenticate download links with either an api_key query parameter or the x-api-key header. Authenticated downloads use your paid account-wide download quota instead of the anonymous limit of 300 downloads per day per IP.
curl "https://dl.subdl.com/subtitle/3197651-3213944.zip?api_key=example-api-key"
curl -H "x-api-key: example-api-key" "https://dl.subdl.com/subtitle/{n_id}/{file_n_id}"
curl "https://api.subdl.com/api/v1/subtitles?api_key=example-api-key&film_name=Inception&type=movie&languages=EN,FR&unpack=1"
{
"status": true,
"results": [
{
"imdb_id": "tt1375666",
"tmdb_id": 27205,
"type": "movie",
"name": "Inception",
"sd_id": 123456,
"first_air_date": null,
"year": 2010
}
],
"subtitles": [
{
"release_name": "Season Pack",
"name": "Season.Pack.zip",
"url": "/subtitle/3197651-3213944.zip",
"season": 1,
"episode": 1,
"framerate": 2,
"fps": "23.976",
"episode_from": 1,
"episode_end": 10,
"full_season": true,
"unpack_files": [
{
"file_n_id": "file123",
"name": "Episode.One.srt",
"release_name": "Episode One",
"season": 1,
"episode": 1,
"language": "EN",
"hi": false,
"format": "srt",
"size": 12345,
"md5": "example-md5",
"url": "/subtitle/parent_n_id/file123"
}
]
}
]
}
fetch(
"https://api.subdl.com/api/v1/subtitles?api_key=example-api-key&film_name=Inception&type=movie&languages=EN&unpack=1",
{
method: "GET",
headers: {
Accept: "application/json",
},
}
)
.then((response) => response.json())
.then((data) => console.log(data))
.catch((error) => console.error("Error:", error))
Use your API key to check your account, paid plan, per-key usage, and account-wide request/download quotas:
curl "https://api.subdl.com/api/v1/me?api_key=example-api-key"
Free API keys get 2,000 requests per day. The SubDL Pro plan includes 30,000 requests per day, 2,000 key-authenticated downloads per day, and up to 10 managed API keys.
Paid API users can use higher-limit autocomplete and search endpoints:
curl "https://api.subdl.com/api/v1/auto?api_key=example-api-key&query=matrix&type=movie"
curl "https://api.subdl.com/api/v1/search?api_key=example-api-key&query=lost&type=tv"
These endpoints require an active paid API subscription, count toward the account-wide request quota, and allow up to 600 requests per minute per key.
Paid users with translation quota can request a subtitle in a language that doesn’t exist yet:
curl -X POST "https://api.subdl.com/api/v1/pro/translate/subtitles?api_key=example-api-key" \
-H "Content-Type: application/json" \
-d '{"n_id":"subtitle-n-id","file_n_id":"optional-file-id","target_language":"FA"}'
The response returns a request_id immediately. Poll the job until download_ready is true, then download:
curl "https://api.subdl.com/api/v1/pro/translate/jobs/{request_id}?api_key=example-api-key"
curl "https://api.subdl.com/api/v1/pro/translate/jobs/{request_id}/download?api_key=example-api-key"
Status values are queued, running, publishing, translated, published, reused, and failed.
Translation error responses include a stable error code plus a human-readable message:
Repeating a request for the same source subtitle, target language, and tone returns the finished job immediately with reused: true and does not consume quota.
The Subtitle Upload API lets you upload subtitle files for movies and TV shows to the SubDL platform. The upload follows a structured three-step process to ensure proper file handling, validation, and metadata association.
.srt, .sub, .ass, etc.)All endpoints require a valid authentication token in the request headers. Tokens can be obtained through the SubDL authentication system.
n_id) that links all upload steps together.All uploaded subtitles go through a review process before being made publicly available.
Before uploading a subtitle file, obtain a unique identifier (n_id).
Endpoint: https://api3.subdl.com/user/getNId
Method: GET
Headers:
| Header | Description |
|---|---|
token | Your authentication token |
{
"ok": true,
"n_id": "iwpVZm9Sva",
"error": null
}
{
"ok": false,
"n_id": null,
"error": "Error message"
}
After obtaining an n_id, upload the subtitle file.
Endpoint: https://api3.subdl.com/user/uploadSingleSubtitle
Method: POST
Headers:
| Header | Description |
|---|---|
token | Your authentication token |
Form Parameters (multipart/form-data):
| Parameter | Required | Description |
|---|---|---|
subtitle | Yes | The subtitle file to upload. |
n_id | No | The unique identifier obtained in Step 1. |
file_n_id | No | A specific file identifier when replacing an existing subtitle. |
{
"ok": true,
"n_id": "8aRlnG50ZS",
"file": {
"fileName": "Captain.America.Brave.New.World.2025.1080p.WEB-DL.x264.6CH-Pahe.in.srt",
"info": {
"index": 0,
"e": 1,
"s": 1,
"q": "web",
"hi": false
},
"md5": "",
"file_n_id": "s42RJ00Gae",
"fileSize": 274694
}
}
{
"ok": false,
"error": "Error message"
}
After uploading the file, submit metadata to complete the upload.
Endpoint: https://api3.subdl.com/user/uploadSubtitle
Method: POST
Headers:
| Header | Description |
|---|---|
token | Bearer token for authentication |
Form Parameters:
| Parameter | Required | Description |
|---|---|---|
file_n_ids | Yes | Array of file_n_id values from Step 2, e.g. ["r5mEd88x1P"]. |
n_id | Yes | The n_id value from Step 1. |
type | Yes | Content type: movie or tv. |
tmdb_id | Yes | TMDB ID of the movie or TV show (recommended identifier). |
name | Yes | Title or name of the subtitle. For packed multi-file uploads, this is also used as the downloaded ZIP filename. |
lang | Yes | Language code, e.g. EN, RU. See the list of supported languages. |
quality | Yes | Source quality of the subtitle — see the quality values below. |
production_type | Yes | Production type identifier (integer, default 0) — see the production type values below. |
releases | Yes | Array of release names this subtitle is compatible with, e.g. ["Movie.2025.1080p.WEB-DL.x264"]. |
framerate | Yes | Framerate code (integer, default 0) — see the framerate values below. |
comment | Yes | Comment about the subtitle (can be empty). |
season | Yes | Season number for TV shows (use 0 for movies). |
hi | Yes | true if the subtitle is for hearing-impaired viewers. |
is_full_season | Yes | true if the subtitle covers an entire season. |
imdb_id | No | IMDb ID of the movie or TV show. |
tags | No | Array of tags to improve searchability. |
ef | No | Episode from — start of the episode range, for TV series. |
ee | No | Episode end — end of the episode range, for TV series. |
sd_id | No | Existing subtitle ID, when updating a subtitle you already uploaded. |
| Value | Source |
|---|---|
web | Web release (streaming, WEB-DL) |
bluray | Blu-ray source |
dvd | DVD source |
hdtv | HDTV broadcast source |
cam | Camera recording |
| Value | Meaning |
|---|---|
0 | Default / Standard |
1 | Translation |
2 | Original |
3 | Machine translated |
| Value | Framerate |
|---|---|
0 | default |
2 | 23.976 |
6 | 23.980 |
5 | 24.000 |
3 | 25.000 |
4 | 29.970 |
7 | 30.000 |
When identifying content for your subtitle upload, provide:
movie or tv.tmdb_id: The Movie Database ID (recommended)imdb_id: Internet Movie Database IDsubdl_id: Internal SubDL database ID for the movie/TV show (not to be confused with sd_id, which identifies a subtitle)Using the correct identifier with the proper type ensures your subtitle is associated with the right content.
{
"status": true,
"message": "subtitle sent for review"
}
{
"status": false,
"message": "Error message"
}
curl --location 'https://api3.subdl.com/user/getNId' \
--header 'token: YOUR_TOKEN'
curl --location 'https://api3.subdl.com/user/uploadSingleSubtitle' \
--header 'token: YOUR_TOKEN' \
--form 'subtitle=@"/path/to/your/subtitle.srt"' \
--form 'n_id="iwpVZm9Sva"'
curl --location 'https://api3.subdl.com/user/uploadSubtitle' \
--header 'token: YOUR_TOKEN' \
--form 'file_n_ids=["r5mEd88x1P"]' \
--form 'tmdb_id=822119' \
--form 'type=movie' \
--form 'quality=web' \
--form 'production_type=0' \
--form 'name=Captain America Subtitle' \
--form 'releases=["Captain.America.Brave.New.World.2025.1080p.WEB-DL.x264.6CH-Pahe.in"]' \
--form 'framerate=0' \
--form 'comment=' \
--form 'lang=SR' \
--form 'season=0' \
--form 'hi=false' \
--form 'is_full_season=false' \
--form 'n_id=12g74yIzR9N' \
--form 'tags=[]'
// Step 1: Get Unique ID
async function getNId(token) {
const response = await fetch("https://api3.subdl.com/user/getNId", {
method: "GET",
headers: {
token: token,
},
})
return await response.json()
}
// Step 2: Upload Subtitle File
async function uploadSubtitleFile(
token,
subtitleFile,
n_id = null,
file_n_id = null
) {
const formData = new FormData()
formData.append("subtitle", subtitleFile)
if (n_id) formData.append("n_id", n_id)
if (file_n_id) formData.append("file_n_id", file_n_id)
const response = await fetch(
"https://api3.subdl.com/user/uploadSingleSubtitle",
{
method: "POST",
headers: {
token: token,
},
body: formData,
}
)
return await response.json()
}
// Step 3: Complete Subtitle Upload
async function completeSubtitleUpload(bearerToken, uploadData) {
const formData = new FormData()
formData.append("file_n_ids", JSON.stringify(uploadData.file_n_ids))
formData.append("tmdb_id", uploadData.tmdb_id)
formData.append("type", uploadData.type)
formData.append("quality", uploadData.quality)
formData.append("production_type", uploadData.production_type)
formData.append("name", uploadData.name)
formData.append("releases", JSON.stringify(uploadData.releases))
formData.append("framerate", uploadData.framerate)
formData.append("comment", uploadData.comment)
formData.append("lang", uploadData.lang)
formData.append("season", uploadData.season)
formData.append("hi", uploadData.hi)
formData.append("is_full_season", uploadData.is_full_season)
formData.append("n_id", uploadData.n_id)
// Optional parameters
if (uploadData.tags) formData.append("tags", JSON.stringify(uploadData.tags))
if (uploadData.imdb_id) formData.append("imdb_id", uploadData.imdb_id)
if (uploadData.ef) formData.append("ef", uploadData.ef)
if (uploadData.ee) formData.append("ee", uploadData.ee)
if (uploadData.sd_id) formData.append("sd_id", uploadData.sd_id)
const response = await fetch("https://api3.subdl.com/user/uploadSubtitle", {
method: "POST",
headers: {
token: `Bearer ${bearerToken}`,
},
body: formData,
})
return await response.json()
}
n_id) must be completed before Step 2 (upload file), and Step 2 before Step 3 (complete upload).file_n_id value returned in Step 2 is required for the file_n_ids array in Step 3.file_n_ids) and camelCase (fileNIds) parameter names are supported.