SubDL API
Search, download, and upload subtitles programmatically.
Subtitles Search API
Overview
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.
Request Parameters
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. |
Successful Response
A successful response returns a JSON object with these fields:
- status:
trueon success. - results: An array of movies or TV shows matching the search criteria.
- subtitles: An array of subtitles for the first movie/TV show in
results. - subtitles[].framerate: Framerate code of the upload (
0means default/unknown). See the framerate table in the Upload API docs. - subtitles[].fps: Human-readable FPS value such as
23.976, ornullwhen unknown/default. - subtitles[].unpack_files: Returned only when
unpack=1. Each item is one saved subtitle file from the pack and includesfile_n_id,name,release_name,season,episode,language,hi,format,size,md5, andurl.
Error Response
An error response returns a JSON object with these fields:
- status:
falseon failure. - error: A message describing the reason for the failure.
Downloading Subtitles
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}"
Usage Example
Request
curl "https://api.subdl.com/api/v1/subtitles?api_key=example-api-key&film_name=Inception&type=movie&languages=EN,FR&unpack=1"
Response Body
{
"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"
}
]
}
]
}
JavaScript Example
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))
Account Status
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.
Pro Autocomplete and Search API
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.
Pro API Translation
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:
- translation_not_entitled (HTTP 402): No active paid plan with translation quota. Both SubDL Plus and SubDL Pro include a monthly translation quota.
- translation_quota_exhausted (HTTP 429): The monthly translation quota is used up; it resets on the 1st of each month (UTC).
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.
Notes
- API rate limiting is applied account-wide, with per-key counters shown in the dashboard.
- The search first looks for exact matches in the database, then falls back to broader criteria if necessary.
- Language codes must follow the supported language list to ensure accurate filtering.
Subtitle Upload API
Overview
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.
API Capabilities
- Upload subtitle files in common formats (
.srt,.sub,.ass, etc.) - Associate subtitles with specific movies or TV shows using TMDB or IMDb identifiers
- Support multiple languages and quality indicators
- Specify release compatibility and technical parameters
- Add metadata such as hearing-impaired markers and production type
Authentication
All endpoints require a valid authentication token in the request headers. Tokens can be obtained through the SubDL authentication system.
Three-Step Upload Process
- Get Unique ID: Obtain a session identifier (
n_id) that links all upload steps together. - Upload File: Send the subtitle file to the server and receive a file identifier.
- Submit Metadata: Provide details about the subtitle and complete the upload.
All uploaded subtitles go through a review process before being made publicly available.
Step 1: Get Unique ID
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 |
Successful Response
{
"ok": true,
"n_id": "iwpVZm9Sva",
"error": null
}
Error Response
{
"ok": false,
"n_id": null,
"error": "Error message"
}
Step 2: Upload Subtitle File
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. |
Successful Response
{
"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
}
}
Error Response
{
"ok": false,
"error": "Error message"
}
Step 3: Complete Subtitle Upload
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. |
Quality Values
| Value | Source |
|---|---|
web | Web release (streaming, WEB-DL) |
bluray | Blu-ray source |
dvd | DVD source |
hdtv | HDTV broadcast source |
cam | Camera recording |
Production Type Values
| Value | Meaning |
|---|---|
0 | Default / Standard |
1 | Translation |
2 | Original |
3 | Machine translated |
Framerate Values
| Value | Framerate |
|---|---|
0 | default |
2 | 23.976 |
6 | 23.980 |
5 | 24.000 |
3 | 25.000 |
4 | 29.970 |
7 | 30.000 |
Identifying the Movie or TV Show
When identifying content for your subtitle upload, provide:
- type: Either
movieortv. - One of the following identifiers:
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 withsd_id, which identifies a subtitle)
Using the correct identifier with the proper type ensures your subtitle is associated with the right content.
Successful Response
{
"status": true,
"message": "subtitle sent for review"
}
Error Response
{
"status": false,
"message": "Error message"
}
cURL Examples
Step 1: Get Unique ID
curl --location 'https://api3.subdl.com/user/getNId' \
--header 'token: YOUR_TOKEN'
Step 2: Upload Subtitle File
curl --location 'https://api3.subdl.com/user/uploadSingleSubtitle' \
--header 'token: YOUR_TOKEN' \
--form 'subtitle=@"/path/to/your/subtitle.srt"' \
--form 'n_id="iwpVZm9Sva"'
Step 3: Complete Subtitle Upload
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=[]'
JavaScript Example
// 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()
}
Notes
- All requests require authentication.
- Step 1 (get
n_id) must be completed before Step 2 (upload file), and Step 2 before Step 3 (complete upload). - The
file_n_idvalue returned in Step 2 is required for thefile_n_idsarray in Step 3. - Both snake_case (
file_n_ids) and camelCase (fileNIds) parameter names are supported. - Uploaded subtitles are sent for review before being made available on the platform.
- Supported languages and file formats may change; refer to the platform’s documentation for the most up-to-date information.