Search 4M+ subtitles matched to a TMDB-clean database, download season packs and single episodes, and translate any subtitle with AI in under 60 seconds.
Every title resolves to clean TMDB/IMDb ids — no fuzzy guessing.
Half a million titles indexed and ready to search.
One of the largest subtitle catalogs, across dozens of languages.
Cached, edge-fast search responses for snappy autocomplete.
The complete Subscene back-catalog, preserved and searchable.
Match titles by their localized and alternative names worldwide.
Pull a whole season in one call, or a single episode.
Look up titles and subtitles directly by IMDb id or URL.
Strong anime coverage with release-aware matching and tone presets.
Translate a full subtitle file into any language in under a minute.
Drop a messy release filename and get the right match.
Search and download work on a free key. AI translation, AI transcription, AI filename search, 30,000 requests/day and 2,000 downloads/day require SubDL Pro.
Upgrade to SubDL Pro
Authenticate every request with your API key in an
Authorization: Bearer
header (or X-API-Key).
The legacy ?api_key=
query is still accepted for download links. Base URL:
https://api.subdl.com
# Your first request
curl "https://api.subdl.com/api/v2/movies/search?q=dune" \
-H "Authorization: Bearer $SUBDL_API_KEY" /api/v2/movies/search Title search for autocomplete or a search page. Returns posters and matched ids (sd_id, imdb_id, tmdb_id).
q * Search query (min 2 chars). Accepts an IMDb id/url too. type Filter: movie or tv. limit Max results, 1–30 (default 10). Small values behave like autocomplete. curl "https://api.subdl.com/api/v2/movies/search?q=dune&type=movie&limit=5" \
-H "Authorization: Bearer $SUBDL_API_KEY" import requests
r = requests.get(
"https://api.subdl.com/api/v2/movies/search?q=dune&type=movie&limit=5",
headers={"Authorization": f"Bearer {SUBDL_API_KEY}"},
)
print(r.json()) const res = await fetch("https://api.subdl.com/api/v2/movies/search?q=dune&type=movie&limit=5", {
headers: { Authorization: `Bearer ${SUBDL_API_KEY}` },
});
const data = await res.json(); <?php
$ch = curl_init("https://api.subdl.com/api/v2/movies/search?q=dune&type=movie&limit=5");
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_HTTPHEADER, [
"Authorization: Bearer " . $SUBDL_API_KEY,
]);
$data = json_decode(curl_exec($ch), true); {
"results": [
{
"sd_id": "sd123456",
"type": "movie",
"name": "Dune: Part Two",
"original_name": "Dune: Part Two",
"year": 2024,
"imdb_id": "tt15239678",
"tmdb_id": 693134,
"poster_url": "https://.../poster.jpg",
"subtitles_count": 412,
"url": "https://subdl.com/subtitle/sd123456/dune-part-two"
}
]
} /api/v2/files/search Pass a release filename and get the matched title plus its subtitles. Ideal for media managers scanning a library.
filename * The release filename, e.g. Dune.Part.Two.2024.2160p.BluRay.x265-GROUP.mkv languages Comma-separated language codes, e.g. en,fa,ar. subs_per_page Subtitles per page (max 30). curl "https://api.subdl.com/api/v2/files/search?filename=Dune.Part.Two.2024.2160p.BluRay.x265-GROUP.mkv&languages=en,fa" \
-H "Authorization: Bearer $SUBDL_API_KEY" import requests
r = requests.get(
"https://api.subdl.com/api/v2/files/search?filename=Dune.Part.Two.2024.2160p.BluRay.x265-GROUP.mkv&languages=en,fa",
headers={"Authorization": f"Bearer {SUBDL_API_KEY}"},
)
print(r.json()) const res = await fetch("https://api.subdl.com/api/v2/files/search?filename=Dune.Part.Two.2024.2160p.BluRay.x265-GROUP.mkv&languages=en,fa", {
headers: { Authorization: `Bearer ${SUBDL_API_KEY}` },
});
const data = await res.json(); <?php
$ch = curl_init("https://api.subdl.com/api/v2/files/search?filename=Dune.Part.Two.2024.2160p.BluRay.x265-GROUP.mkv&languages=en,fa");
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_HTTPHEADER, [
"Authorization: Bearer " . $SUBDL_API_KEY,
]);
$data = json_decode(curl_exec($ch), true); /api/v2/subtitles/search Fast exact subtitle search by id or title. Provide one of sd_id, imdb_id, tmdb_id, film_name, or file_name. Add unpack=1 to receive per-file (non-zip) download urls.
sd_id | imdb_id | tmdb_id * One title key. (Or film_name / file_name.) type movie or tv. Required when using tmdb_id — a TMDB id is only unique together with the media type. languages Comma-separated language codes. season / episode For TV. Use full_season=1 for a season pack. unpack 1 to expand archives into exact single-file download urls. curl "https://api.subdl.com/api/v2/subtitles/search?imdb_id=tt15239678&languages=en,fa" \
-H "Authorization: Bearer $SUBDL_API_KEY" import requests
r = requests.get(
"https://api.subdl.com/api/v2/subtitles/search?imdb_id=tt15239678&languages=en,fa",
headers={"Authorization": f"Bearer {SUBDL_API_KEY}"},
)
print(r.json()) const res = await fetch("https://api.subdl.com/api/v2/subtitles/search?imdb_id=tt15239678&languages=en,fa", {
headers: { Authorization: `Bearer ${SUBDL_API_KEY}` },
});
const data = await res.json(); <?php
$ch = curl_init("https://api.subdl.com/api/v2/subtitles/search?imdb_id=tt15239678&languages=en,fa");
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_HTTPHEADER, [
"Authorization: Bearer " . $SUBDL_API_KEY,
]);
$data = json_decode(curl_exec($ch), true); /api/v2/subtitles/{nId}/download Address a subtitle by its nId. format=zip (default) returns the archive; format=file returns the exact single (non-zip) file when the archive has one obvious file.
nId * Subtitle nId (from a search result). format zip (default) or file (exact non-zip file). curl "https://api.subdl.com/api/v2/subtitles/abcdef/download?format=file" \
-H "Authorization: Bearer $SUBDL_API_KEY" import requests
r = requests.get(
"https://api.subdl.com/api/v2/subtitles/abcdef/download?format=file",
headers={"Authorization": f"Bearer {SUBDL_API_KEY}"},
)
print(r.json()) const res = await fetch("https://api.subdl.com/api/v2/subtitles/abcdef/download?format=file", {
headers: { Authorization: `Bearer ${SUBDL_API_KEY}` },
});
const data = await res.json(); <?php
$ch = curl_init("https://api.subdl.com/api/v2/subtitles/abcdef/download?format=file");
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_HTTPHEADER, [
"Authorization: Bearer " . $SUBDL_API_KEY,
]);
$data = json_decode(curl_exec($ch), true); Translate an existing subtitle into any language with AI, typically in under 60 seconds. Returns a request_id; poll the job until download_ready.
n_id * Subtitle nId to translate. target_language * Target language code, e.g. FA. tone Optional: faithful, formal, casual, cinematic_action, comedic_fun, anime. curl -X POST "https://api.subdl.com/api/v2/ai/translations" \
-H "Authorization: Bearer $SUBDL_API_KEY" \
-H "Content-Type: application/json" \
-d '{"n_id":"abcdef","target_language":"FA","tone":"faithful"}' import requests
r = requests.post(
"https://api.subdl.com/api/v2/ai/translations",
headers={"Authorization": f"Bearer {SUBDL_API_KEY}"},
json={
"n_id": "abcdef",
"target_language": "FA",
"tone": "faithful"
},
)
print(r.json()) const res = await fetch("https://api.subdl.com/api/v2/ai/translations", {
method: "POST",
headers: {
Authorization: `Bearer ${SUBDL_API_KEY}`,
"Content-Type": "application/json",
},
body: JSON.stringify({"n_id":"abcdef","target_language":"FA","tone":"faithful"}),
});
const data = await res.json(); <?php
$ch = curl_init("https://api.subdl.com/api/v2/ai/translations");
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_POSTFIELDS, '{"n_id":"abcdef","target_language":"FA","tone":"faithful"}');
curl_setopt($ch, CURLOPT_HTTPHEADER, [
"Authorization: Bearer " . $SUBDL_API_KEY,
"Content-Type: application/json",
]);
$data = json_decode(curl_exec($ch), true); List your translation jobs with their status and progress.
curl "https://api.subdl.com/api/v2/ai/translations?page=1" \
-H "Authorization: Bearer $SUBDL_API_KEY" import requests
r = requests.get(
"https://api.subdl.com/api/v2/ai/translations?page=1",
headers={"Authorization": f"Bearer {SUBDL_API_KEY}"},
)
print(r.json()) const res = await fetch("https://api.subdl.com/api/v2/ai/translations?page=1", {
headers: { Authorization: `Bearer ${SUBDL_API_KEY}` },
});
const data = await res.json(); <?php
$ch = curl_init("https://api.subdl.com/api/v2/ai/translations?page=1");
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_HTTPHEADER, [
"Authorization: Bearer " . $SUBDL_API_KEY,
]);
$data = json_decode(curl_exec($ch), true); Poll a single job for progress, ETA, and download_ready.
curl "https://api.subdl.com/api/v2/ai/translations/req_123" \
-H "Authorization: Bearer $SUBDL_API_KEY" import requests
r = requests.get(
"https://api.subdl.com/api/v2/ai/translations/req_123",
headers={"Authorization": f"Bearer {SUBDL_API_KEY}"},
)
print(r.json()) const res = await fetch("https://api.subdl.com/api/v2/ai/translations/req_123", {
headers: { Authorization: `Bearer ${SUBDL_API_KEY}` },
});
const data = await res.json(); <?php
$ch = curl_init("https://api.subdl.com/api/v2/ai/translations/req_123");
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_HTTPHEADER, [
"Authorization: Bearer " . $SUBDL_API_KEY,
]);
$data = json_decode(curl_exec($ch), true); Generate subtitles from a media file with speech-to-text. In beta — shape may change.
curl -X POST "https://api.subdl.com/api/v2/ai/transcriptions" \
-H "Authorization: Bearer $SUBDL_API_KEY" \
-H "Content-Type: application/json" \
-d '{"media_url":"https://.../episode.mp3","language":"en"}' import requests
r = requests.post(
"https://api.subdl.com/api/v2/ai/transcriptions",
headers={"Authorization": f"Bearer {SUBDL_API_KEY}"},
json={
"media_url": "https://.../episode.mp3",
"language": "en"
},
)
print(r.json()) const res = await fetch("https://api.subdl.com/api/v2/ai/transcriptions", {
method: "POST",
headers: {
Authorization: `Bearer ${SUBDL_API_KEY}`,
"Content-Type": "application/json",
},
body: JSON.stringify({"media_url":"https://.../episode.mp3","language":"en"}),
});
const data = await res.json(); <?php
$ch = curl_init("https://api.subdl.com/api/v2/ai/transcriptions");
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_POSTFIELDS, '{"media_url":"https://.../episode.mp3","language":"en"}');
curl_setopt($ch, CURLOPT_HTTPHEADER, [
"Authorization: Bearer " . $SUBDL_API_KEY,
"Content-Type: application/json",
]);
$data = json_decode(curl_exec($ch), true); Use AI to resolve a messy or ambiguous release filename to the best TMDB match. In beta.
curl "https://api.subdl.com/api/v2/ai/filename-search?filename=that.movie.2021.WEBRip.mkv" \
-H "Authorization: Bearer $SUBDL_API_KEY" import requests
r = requests.get(
"https://api.subdl.com/api/v2/ai/filename-search?filename=that.movie.2021.WEBRip.mkv",
headers={"Authorization": f"Bearer {SUBDL_API_KEY}"},
)
print(r.json()) const res = await fetch("https://api.subdl.com/api/v2/ai/filename-search?filename=that.movie.2021.WEBRip.mkv", {
headers: { Authorization: `Bearer ${SUBDL_API_KEY}` },
});
const data = await res.json(); <?php
$ch = curl_init("https://api.subdl.com/api/v2/ai/filename-search?filename=that.movie.2021.WEBRip.mkv");
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_HTTPHEADER, [
"Authorization: Bearer " . $SUBDL_API_KEY,
]);
$data = json_decode(curl_exec($ch), true); /api/v2/me Your plan plus separated counters (search/day, downloads/day, AI/month) with reset times. Does not count against your search quota.
curl "https://api.subdl.com/api/v2/me" \
-H "Authorization: Bearer $SUBDL_API_KEY" import requests
r = requests.get(
"https://api.subdl.com/api/v2/me",
headers={"Authorization": f"Bearer {SUBDL_API_KEY}"},
)
print(r.json()) const res = await fetch("https://api.subdl.com/api/v2/me", {
headers: { Authorization: `Bearer ${SUBDL_API_KEY}` },
});
const data = await res.json(); <?php
$ch = curl_init("https://api.subdl.com/api/v2/me");
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_HTTPHEADER, [
"Authorization: Bearer " . $SUBDL_API_KEY,
]);
$data = json_decode(curl_exec($ch), true); {
"plan": { "is_pro": false, "name": "Free" },
"usage": {
"search": { "used": 12, "limit": 2000, "remaining": 1988, "period": "day" },
"downloads": { "used": 3, "limit": 50, "remaining": 47, "period": "day" },
"ai": {
"translations": { "eligible": false, "free_trial_per_month": 1, "period": "month" }
}
},
"upgrade_url": "https://subdl.com/pro"
}
Every response includes X-RateLimit-Limit,
X-RateLimit-Remaining, and
X-RateLimit-Reset. Errors share one shape:
{
"error": {
"code": "quota_exceeded",
"message": "Daily request quota exceeded.",
"docs_url": "https://subdl.com/developers#errors"
}
} | Tier | Search / day | Downloads / day | AI |
|---|---|---|---|
| Free | 2,000 | 50 | 1 free trial / feature / month |
| SubDL Pro | 30,000 | 2,000 | 60 translations / month |
Create a free SubDL account, open your panel, and generate an API key from the API section. The free tier includes 2,000 searches and 50 downloads per day.
Yes. The free tier allows 2,000 searches and 50 downloads per day. SubDL Pro raises this to 30,000 searches and 2,000 downloads per day, plus AI subtitle translation.
Search 4M+ subtitles across 500K+ TMDB-matched movies and TV shows, download SRT files, and use AI subtitle translation — ideal for media players, Bazarr-style tools, and apps.