Forum rules
Under no circumstances is spamming or advertising of any kind allowed. Do not post any abusive, obscene, vulgar, slanderous, hateful, threatening, sexually-orientated or any other material that may violate others security. Profanity or any kind of insolent behavior to other members (regardless of rank) will not be tolerated. Remember, what you don’t find offensive can be offensive to other members. Please treat each other with the kind of reverence you’d expect from other members.
Failure to comply with any of the above will result in users being banned without notice. If any further details are needed, contact: “The team” using the link at the bottom of the forum page. Thank you.
Masutin
Posts: 10
Joined: Sat Apr 21, 2012 11:32 am

Texts from opensubtitles.stoplight.io/docs/opensubtitles-api in one file?

Sat May 24, 2025 12:43 pm

Having these as one manual would be useful.

User avatar
oss
Site Admin
Posts: 6192
Joined: Sat Feb 25, 2006 11:26 pm
Contact: Website

Re: Texts from opensubtitles.stoplight.io/docs/opensubtitles-api in one file?

Sat May 24, 2025 3:25 pm

I dont think we have this, but I believe also some AI could do that.

haroldpoi
Posts: 20
Joined: Tue May 03, 2022 4:30 pm

Re: Texts from opensubtitles.stoplight.io/docs/opensubtitles-api in one file?

Sat May 24, 2025 7:19 pm

I did that some weeks ago (output in markdown). It is missing ai related endpolints.
This document describes the endpoints available in the OpenSubtitles API v1.

**Base URL:** `https://api.opensubtitles.com/api/v1`

*(Note: The `/login` endpoint may return a different `base_url`, potentially `https://vip-api.opensubtitles.com`, which should be used for subsequent requests for that authenticated session).*

**Authentication:**

* **API Key:** Most endpoints require an API Key provided via the `Api-Key` header. Obtain this key from your user profile on opensubtitles.com.
* Example Header: `Api-Key: YOUR_API_KEY`
* **Bearer Token:** Endpoints requiring user authentication (`/download`, `/infos/user`, `/logout`) additionally need a Bearer token obtained via the `/login` endpoint, provided in the `Authorization` header.
* Example Header: `Authorization: Bearer YOUR_BEARER_TOKEN`

**Required Headers:**

* **`Api-Key`**: Your application's API key (see Authentication).
* **`User-Agent`**: Identify your application. Use the format `<<APP_NAME}} v{{APP_VERSION}}>>`.
* Example: `User-Agent: MySubtitleApp v1.2.0`
* **`Content-Type`**: Required for POST requests with a body. Should be `application/json`.
* **`Accept`**: Recommended for GET requests expecting JSON. Should be `application/json`.

**General Best Practices & Notes:**

* **Parameter Logic:** Follow the specific logic guidelines provided for each endpoint (e.g., prefer IDs over text queries, use parent IDs for TV shows).
* **Parameter Filtering:** Treat parameters primarily as filters. Conflicting information (e.g., correct ID with wrong year) might reduce results.
* **Case Sensitivity & Sorting:** Send query parameters sorted alphabetically and in lowercase to potentially improve caching and avoid redirection issues.
* **ID Formatting:** Remove leading zeroes from ID parameters (IMDB ID, TMDB ID, etc.).
* **Redirects:** Follow HTTP redirects (e.g., use `curl --location`). Sorting parameters and avoiding defaults can help minimize redirects.
* **Rate Limiting:** Be mindful of rate limits (e.g., 40 requests per 10 seconds mentioned for `/features`, 1 request per second for `/login`). Adhere to limits returned in response headers or documentation.
* **Errors:** Errors can occur due to the collaborative nature of the data. Use user feedback for reporting issues.
* **`ai_translated` vs `machine_translated`**: AI-translated subtitles are generally higher quality and included by default. Machine-translated are lower quality and excluded by default.

---

### 1. Search for Subtitles

Finds subtitles based on various criteria like external IDs, file hash, or text query.

* **Method:** `GET`
* **Path:** `/api/v1/subtitles`
* **Authentication:** `Api-Key` required.

**Headers:**

* `Api-Key: YOUR_API_KEY` (Required)
* `User-Agent: <<APP_NAME}} v{{APP_VERSION}}>>` (Required)
* `Accept: application/json` (Recommended)

**Query Parameters:**

| Parameter | Type | Description | Default | Constraints / Allowed Values |
| :------------------- | :------ | :------------------------------------------------------------------------------------------------------------ | :-------- | :------------------------------------------------------- |
| `id` | integer | OpenSubtitles ID of the specific movie or episode feature. | | |
| `imdb_id` | integer | IMDB ID of the movie or episode (e.g., `539911` not `tt0539911`). Use `parent_imdb_id` for the TV Show itself. | | Remove leading zeroes. |
| `tmdb_id` | integer | TMDB ID of the movie or episode. Use `parent_tmdb_id` for the TV Show itself. | | Remove leading zeroes. |
| `parent_imdb_id` | integer | For TV Shows: IMDB ID of the parent TV Show. Recommended with `season_number` and `episode_number`. | | Remove leading zeroes. |
| `parent_tmdb_id` | integer | For TV Shows: TMDB ID of the parent TV Show. Recommended with `season_number` and `episode_number`. | | Remove leading zeroes. |
| `parent_feature_id` | integer | For TV Shows: OpenSubtitles Feature ID of the parent TV Show. | | |
| `query` | string | Text search query (e.g., movie title, file name). Less precise than IDs. Include filename here if using `moviehash`. | | Send lowercase. |
| `season_number` | integer | For TV Shows: The season number. Use with `parent_imdb_id` or `parent_tmdb_id`. | | Do not use if sending a specific episode `imdb_id`. |
| `episode_number` | integer | For TV Shows: The episode number. Use with `parent_imdb_id` or `parent_tmdb_id`. | | Do not use if sending a specific episode `imdb_id`. |
| `moviehash` | string | The hash calculated from the video file. Send along with `query` (filename) for better results. | | Exactly 16 hex chars (`^[a-f0-9]{16}$`). |
| `languages` | string | Comma-separated list of language codes (ISO 639-1 or 639-2/B). | | e.g., `en,fr`. Sort alphabetically (`en,fr` not `fr,en`). |
| `type` | string | Filter by feature type. | `all` | `movie`, `episode`, `all` |
| `year` | integer | Filter by the movie or episode's release year. | | |
| `ai_translated` | string | Filter based on AI translation. | `include` | `include`, `exclude` |
| `machine_translated` | string | Filter based on machine translation. | `exclude` | `include`, `exclude` |
| `hearing_impaired` | string | Filter for subtitles for the hearing impaired (HI/SDH). | `include` | `include`, `exclude`, `only` |
| `foreign_parts_only` | string | Filter for subtitles that only cover foreign language parts. | `include` | `include`, `exclude`, `only` |
| `trusted_sources` | string | Filter subtitles from trusted uploaders/sources. | `include` | `include`, `only` |
| `moviehash_match` | string | How to handle moviehash matching. `only` returns *only* subtitles matching the hash. | `include` | `include`, `only` |
| `uploader_id` | integer | List subtitles uploaded by a specific user ID. Best used alone. | | |
| `order_by` | string | Field to sort results by. Sorting is computationally expensive; avoid if possible. | | See list below. |
| `order_direction` | string | Direction for sorting. | `desc` | `asc`, `desc` |
| `page` | integer | Results page number to retrieve. | `1` | |

**Orderable Fields (`order_by`):**
`language`, `download_count`, `new_download_count`, `hearing_impaired`, `hd`, `fps`, `votes`, `points`, `ratings`, `from_trusted`, `foreign_parts_only`, `ai_translated`, `machine_translated`, `upload_date`, `release`, `comments`

**Search Logic Guidelines:**

1. **Moviehash:** If available, send it. Include the `filename` in the `query` parameter alongside `moviehash` for better matching (unless filenames are irrelevant, e.g., streaming service temp names). If `moviehash` is sent, the response includes a `moviehash_match` boolean, and matching subtitles appear first.
2. **IDs vs. Query:** If you have an IMDB or TMDB ID, use it instead of a `query` for higher precision.
3. **TV Show Episodes:**
* *Best:* Use the parent show's ID (`parent_imdb_id` or `parent_tmdb_id`) along with `season_number` and `episode_number`.
* *Alternative:* If you have the specific `imdb_id` or `tmdb_id` for the *episode*, send *only* that ID (do not include season/episode numbers or parent IDs).
4. **`/features` Endpoint:** Consider querying `/features` first to get exact episode lists and IDs.

**Responses:**

* **`200 OK`**: Successfully retrieved subtitles.
* **Body:** `application/json`
```json
{
"total_pages": 1, // Total number of pages available
"total_count": 35, // Total number of subtitles matching the query
"per_page": 50, // Number of results per page (fixed)
"page": 1, // Current page number
"data": [
{
"id": "10139516", // OpenSubtitles internal subtitle file group ID
"type": "subtitle",
"attributes": {
"subtitle_id": "10139516", // Same as outer id
"language": "el", // Language code
"download_count": 1, // Historical download count
"new_download_count": 0, // Recent download count (e.g., last 30 days)
"hearing_impaired": false, // Is it for hearing impaired?
"hd": true, // Suitable for HD release?
"fps": 0, // Frames per second (0 if unknown/not applicable)
"votes": 0, // User votes
"ratings": 0, // User ratings score
"from_trusted": true, // Uploaded by a trusted source?
"foreign_parts_only": false, // Only covers foreign speech?
"upload_date": "2025-05-02T19:54:42Z", // Upload timestamp (UTC)
"ai_translated": false, // Was this AI translated?
"machine_translated": false, // Was this machine translated?
"moviehash_match": true, // (Only present if moviehash was sent in request) Did this subtitle match the hash?
"nb_cd": 1, // Number of CDs/parts (usually 1)
"slug": "cheers-s01e03-720p-web-x264-galaxytv-gre", // URL-friendly identifier
"release": "Cheers.S01E03.720p.WEB.x264-GalaxyTV.gre", // Associated release name
"comments": "Ανοιχτό κάλεσμα...", // Uploader comments
"legacy_subtitle_id": 13082870, // ID from the old OpenSubtitles system
"legacy_uploader_id": 7938990, // Uploader ID from the old system
"uploader": {
"uploader_id": 361640, // Current uploader ID
"name": "haroldpoi", // Uploader username
"rank": "Subtitle Translator" // Uploader rank/status
},
"feature_details": { // Information about the associated movie/episode
"feature_id": 1480735, // OpenSubtitles Feature ID
"feature_type": "Episode", // "Movie" or "Episode"
"year": 1982, // Release year
"title": "The Tortelli Tort", // Feature title
"movie_name": "Cheers - S01E03 The Tortelli Tort", // Formatted name
"imdb_id": 539911, // IMDB ID (without 'tt')
"tmdb_id": 7645, // TMDB ID
"season_number": 1, // (Episode only) Season number
"episode_number": 3, // (Episode only) Episode number
"parent_imdb_id": 83399, // (Episode only) Parent show IMDB ID
"parent_title": "Cheers", // (Episode only) Parent show title
"parent_tmdb_id": 141, // (Episode only) Parent show TMDB ID
"parent_feature_id": 644054 // (Episode only) Parent show Feature ID
},
"url": "https://www.opensubtitles.com/el/subtit ... y/13082870", // URL to the subtitle page on the website
"related_links": [ // Links to related pages on the website
{
"label": "All subtitles for Tv Show Cheers",
"url": "https://www.opensubtitles.com/el/featur ... ect/644054",
"img_url": "https://s9.opensubtitles.com/features/5/3/7/1480735.jpg"
},
// ... other related links
],
"files": [ // Array of actual subtitle files associated with this entry
{
"file_id": 11047023, // **The ID needed for the /download endpoint**
"cd_number": 1, // Typically 1
"file_name": "Cheers.S01E03.720p.WEB.x264-GalaxyTV.gre" // Original filename
}
// ... potentially more files if nb_cd > 1
]
}
},
// ... more subtitle objects up to per_page limit
]
}
```
* **Other Responses:** Standard HTTP error codes (400 Bad Request, 401 Unauthorized, 403 Forbidden, 429 Too Many Requests, etc.).

**Example Request:**

```bash
curl --request GET \
--url 'https://api.opensubtitles.com/api/v1/su ... nguages=en' \
--header 'Api-Key: YOUR_API_KEY' \
--header 'User-Agent: MySubtitleApp v1.2.0' \
--header 'Accept: application/json'
```

---

### 2. Search for Features

Searches for features (Movies, TV Shows, Episodes) by text query or specific IDs. Useful for finding the correct ID before searching for subtitles or for implementing autocomplete functionality.

* **Method:** `GET`
* **Path:** `/api/v1/features`
* **Authentication:** `Api-Key` required.

**Headers:**

* `Api-Key: YOUR_API_KEY` (Required)
* `User-Agent: <<APP_NAME}} v{{APP_VERSION}}>>` (Required)
* `Accept: application/json` (Required)

**Query Parameters:**

| Parameter | Type | Description | Default | Constraints / Allowed Values |
| :------------ | :------ | :------------------------------------------------------------------------------- | :-------- | :----------------------------------- |
| `feature_id` | integer | Get details for a specific OpenSubtitles feature ID. | | |
| `imdb_id` | string | Get details for a specific IMDB ID. | | Remove leading 'tt' and zeroes. |
| `tmdb_id` | string | Get details for a specific TMDB ID. Combine with `type` to resolve ambiguity. | | Remove leading zeroes. |
| `query` | string | Text search query (e.g., movie title, release name). | | >= 3 characters. Send lowercase. |
| `query_match` | string | Type of matching for the `query`. `start` for autocomplete. | `start` | `start`, `word`, `exact` |
| `full_search` | boolean | If `true`, searches translated titles (`title_aka`) as well as the original title. | `false` | `true`, `false` |
| `type` | string | Filter results by type. Use with `tmdb_id` or `query`. | | `movie`, `tvshow`, `episode`, `all` or empty |
| `year` | integer | Filter by year. Can only be used in combination with `query`. | | |

**Notes:**

* **Autocomplete:** If using `query` for autocomplete, be mindful of the rate limit (e.g., don't query on every keystroke if too fast).
* **ID vs Query:** Using `feature_id`, `imdb_id`, or `tmdb_id` directly retrieves a specific feature. `query` performs a search.

**Responses:**

* **`200 OK`**: Successfully retrieved features.
* **Body:** `application/json`
```json
{
"data": [
{
"id": "1480735", // OpenSubtitles Feature ID
"type": "feature",
"attributes": {
"feature_id": "1480735", // Same as outer id
"feature_type": "Episode", // "Movie", "Tvshow", "Episode"
"year": "1982", // Release year (string)
"title": "the tortelli tort", // Primary title (often lowercase)
"original_title": null, // Original language title (if different)
"movie_name": "Cheers - S01E03 The Tortelli Tort", // (Present on Episodes/Movies?) Formatted name
"imdb_id": 539911, // IMDB ID
"tmdb_id": 7645, // TMDB ID
"season_number": 1, // (Tvshow/Episode) Season number
"episode_number": 3, // (Episode) Episode number
"parent_imdb_id": 83399, // (Episode) Parent show IMDB ID
"parent_title": "Cheers", // (Episode) Parent show title
"parent_tmdb_id": 141, // (Episode) Parent show TMDB ID
"parent_feature_id": 644054, // (Episode) Parent show Feature ID
"title_aka": [ // Array of alternative titles/translations
"Trapička Torteliová",
"Wer ist hier das Ekel?",
// ... other aka titles
],
"url": "https://www.opensubtitles.com/en/tvshow ... telli-tort", // Link to feature page on website
"img_url": "/assets/no-poster-....png", // URL path to poster image (may be relative)
"subtitles_count": 40, // Total number of subtitles for this feature
"subtitles_counts": { // Breakdown of subtitles per language
"en": 11,
"sr": 5,
// ... counts for other languages
},
"seasons_count": 0, // (Tvshow) Number of seasons
"seasons": [] // (Tvshow) Array containing season details (might be empty in this specific response type)
}
}
// ... more feature objects if query returns multiple matches
]
}
```
* **Other Responses:** Standard HTTP error codes.

**Example Request:**

```bash
curl --request GET \
--url 'https://api.opensubtitles.com/api/v1/fe ... _id=539911' \
--header 'Api-Key: YOUR_API_KEY' \
--header 'User-Agent: MySubtitleApp v1.2.0' \
--header 'Accept: application/json'
```

### 3. Popular Features

Discovers features (Movies, TV Shows) that are popular on opensubtitles.com based on subtitle download counts over the last 30 days.

* **Method:** `GET`
* **Path:** `/api/v1/discover/popular`
* **Authentication:** `Api-Key` required.

**Headers:**

* `Api-Key: YOUR_API_KEY` (Required)
* `User-Agent: <<APP_NAME}} v{{APP_VERSION}}>>` (Required)
* `Accept: application/json` (Required)

**Query Parameters:**

| Parameter | Type | Description | Default | Constraints / Allowed Values |
| :-------- | :----- | :------------------------------------------------------------------------- | :------ | :--------------------------- |
| `language`| string | Filter popular features based on subtitle downloads for a specific language. | `all` | A single language code (e.g., `en`, `es`), or `all`. |
| `type` | string | Filter by feature type. | `all`? (Not specified, but likely) | `movie`, `tvshow` (or potentially `all`/empty) |

**Responses:**

* **`200 OK`**: Successfully retrieved popular features.
* **Body:** `application/json` (The response structure shows *feature* data, specifically Movies and TV Shows, based on popular *subtitle* downloads).
```json
{
"data": [
{
"id": "514811", // OpenSubtitles Feature ID
"type": "movie", // Feature type ("movie" or "tvshow")
"attributes": {
"feature_id": "514811", // Same as outer id
"title": "the lord of the rings: the fellowship of the ring", // Primary title
"original_title": "The Fellowship of the Ring", // Original language title
"year": "2001", // Release year (string)
"imdb_id": 120737, // IMDB ID
"tmdb_id": 120, // TMDB ID
"title_aka": [ // Array of alternative titles/translations
"Властелинът на пръстените: Задругата на пръстена",
// ... other aka titles
],
"url": "https://www.opensubtitles.com/en/movies ... f-the-ring", // Link to feature page
"img_url": "https://s9.opensubtitles.com/features/1/1/8/514811.jpg", // Link to poster image
"subtitles_count": 2917, // Total number of subtitles for this feature (Example value, might differ)
"subtitles_counts": { // Breakdown of subtitles per language
"en": 359,
"pl": 270,
// ... counts for other languages
}
// Note: TVShow specific fields like seasons_count, seasons might appear if type is "tvshow"
}
},
// ... more popular feature objects
]
}
```
* **Other Responses:** Standard HTTP error codes.

**Example Request:**

```bash
curl --request GET \
--url 'https://api.opensubtitles.com/api/v1/di ... anguage=en' \
--header 'Api-Key: YOUR_API_KEY' \
--header 'User-Agent: MySubtitleApp v1.2.0' \
--header 'Accept: application/json'
```

---

### 4. Latest Subtitles

Retrieves the 60 most recently uploaded subtitles.

* **Method:** `GET`
* **Path:** `/api/v1/discover/latest`
* **Authentication:** `Api-Key` required.

**Headers:**

* `Api-Key: YOUR_API_KEY` (Required)
* `User-Agent: <<APP_NAME}} v{{APP_VERSION}}>>` (Required)
* `Accept: application/json` (Required)

**Query Parameters:**

| Parameter | Type | Description | Default | Constraints / Allowed Values |
| :-------- | :----- | :------------------------------------------------------- | :------ | :--------------------------- |
| `language`| string | Filter latest subtitles by a specific language. | `all` | A single language code (e.g., `en`, `es`), or `all`. |
| `type` | string | Filter latest subtitles by associated feature type. | `all`? (Not specified, but likely) | `movie`, `tvshow` (Note: text mentions movie/tvshow, but example shows movie subtitle. Likely filters based on the feature the subtitle belongs to). |

**Responses:**

* **`200 OK`**: Successfully retrieved the latest subtitles.
* **Body:** `application/json` (The response structure is similar to the `/subtitles` search results, containing detailed subtitle information).
```json
{
"total_pages": 1, // Always 1 for this endpoint as it returns a fixed number
"total_count": 60, // Always 60 for this endpoint
"page": 1, // Always 1
"data": [
{
"id": "10139724", // Subtitle file group ID
"type": "subtitle",
"attributes": {
// Structure is identical to the "attributes" object described
// in the /subtitles endpoint response (See Part 1, Section 1).
// Includes fields like: subtitle_id, language, download_count,
// hearing_impaired, hd, fps, upload_date, release, comments,
// uploader details, feature_details, url, related_links, files.
"subtitle_id": "10139724",
"language": "bg",
"download_count": 0,
"new_download_count": 0,
"hearing_impaired": false,
"hd": true,
"fps": 23.976,
"upload_date": "2025-05-02T22:18:18Z",
"release": "A.Working.Man.2025.1080p.WEB-DL.DDP5.1.x265-davidco",
// ... other attributes ...
"feature_details": {
"feature_id": 2407235,
"feature_type": "Movie",
"year": 2025,
"title": "A Working Man",
"imdb_id": 9150192,
"tmdb_id": 1197306
// ... potentially parent details if it's an episode
},
"files": [
{
"file_id": 11047220, // ID needed for /download
"cd_number": 1,
"file_name": "A.Working.Man.2025.1080p.WEB-DL.DDP5.1.x265-davidco-bul"
}
]
// ... other attributes ...
}
},
// ... 59 more subtitle objects
]
}
```
* **Other Responses:** Standard HTTP error codes.

**Example Request:**

```bash
curl --request GET \
--url 'https://api.opensubtitles.com/api/v1/di ... anguage=fr' \
--header 'Api-Key: YOUR_API_KEY' \
--header 'User-Agent: MySubtitleApp v1.2.0' \
--header 'Accept: application/json'
```

---

### 5. Most Downloaded Subtitles

Discovers subtitles that are popular based on download counts over the last 30 days.

* **Method:** `GET`
* **Path:** `/api/v1/discover/most_downloaded`
* **Authentication:** `Api-Key` required.

**Headers:**

* `Api-Key: YOUR_API_KEY` (Required)
* `User-Agent: <<APP_NAME}} v{{APP_VERSION}}>>` (Required)
* `Accept: application/json` (Required)

**Query Parameters:**

| Parameter | Type | Description | Default | Constraints / Allowed Values |
| :-------- | :----- | :----------------------------------------------------------------- | :------ | :--------------------------- |
| `language`| string | Filter most downloaded subtitles by language. | `all` | A single language code (e.g., `en`, `es`), or `all`. |
| `type` | string | Filter by the type of the feature the subtitle belongs to. | `all`? (Not specified, but likely) | `movie`, `tvshow` (Note: text mentions movie/tvshow, implies filtering by the feature type). |

**Responses:**

* **`200 OK`**: Successfully retrieved the most downloaded subtitles.
* **Body:** `application/json` (The response structure is paginated and contains detailed subtitle information, similar to `/subtitles` search results).
```json
{
"total_pages": 1, // Total number of pages (might be > 1 depending on total results)
"total_count": 60, // Total results matching criteria (fixed at 60 in example, but could be more)
"page": 1, // Current page number
"data": [
{
"id": "848343", // Subtitle file group ID
"type": "subtitle",
"attributes": {
// Structure is identical to the "attributes" object described
// in the /subtitles endpoint response (See Part 1, Section 1).
// Includes fields like: subtitle_id, language, download_count,
// new_download_count (this is the primary sort key here),
// hearing_impaired, hd, fps, upload_date, release, comments,
// uploader details, feature_details, url, related_links, files.
"subtitle_id": "848343",
"language": "en",
"download_count": 238760, // Historical count
"new_download_count": 15649, // Recent count (used for ranking)
"hearing_impaired": false,
"hd": true,
// ... other attributes ...
"feature_details": {
"feature_id": 579213,
"feature_type": "Movie",
"year": 2012,
"title": "Cloud Atlas",
"imdb_id": 1371111,
"tmdb_id": 83542
// ... potentially parent details if it's an episode
},
"files": [
{
"file_id": 928281, // ID needed for /download
"cd_number": 1,
"file_name": "Cloud.Atlas.2012.RC.BDRip.STUDIO.AUDIO.XVID.AC3-5.1.HQ.Hive-CM8"
}
]
// ... other attributes ...
}
},
// ... more subtitle objects up to the limit per page
]
}
```
* **Other Responses:** Standard HTTP error codes.

**Example Request:**

```bash
curl --request GET \
--url 'https://api.opensubtitles.com/api/v1/di ... type=movie' \
--header 'Api-Key: YOUR_API_KEY' \
--header 'User-Agent: MySubtitleApp v1.2.0' \
--header 'Accept: application/json'
```



### 6. Download Subtitle

Requests a temporary download URL for a specific subtitle file. This endpoint increments the user's download count.

* **Method:** `POST`
* **Path:** `/api/v1/download`
* **Authentication:** `Api-Key` AND `Authorization` (Bearer Token) required.
* **VERY IMPORTANT:** Both `Api-Key` and `Authorization: Bearer <token>` headers **must** be present in the request.

**Headers:**

* `Api-Key: YOUR_API_KEY` (Required)
* `Authorization: Bearer YOUR_BEARER_TOKEN` (Required)
* `User-Agent: <<APP_NAME}} v{{APP_VERSION}}>>` (Required)
* `Content-Type: application/json` (Required)
* `Accept: application/json` (Recommended)

**Request Body:**

* **Content-Type:** `application/json`
```json
{
"file_id": 11047023, // integer (Required) - The file_id obtained from a /subtitles search result's "files" array.
"sub_format": "srt", // string (Optional) - Desired subtitle format (e.g., "srt", "sub"). Check /infos/formats (not documented here) for available formats. Defaults to original format if omitted.
"file_name": "MyDownloadedSubtitle.srt", // string (Optional) - Desired filename for the download. Server may override.
"in_fps": 23.976, // number (Optional) - Original FPS of the subtitle. Required **if** out_fps is specified for conversion.
"out_fps": 25.000, // number (Optional) - Target FPS for conversion. Required **if** in_fps is specified for conversion.
"timeshift": -1.5, // number (Optional) - Time adjustment in seconds (positive to delay, negative to hasten). E.g., 2.5 or -1.0.
"force_download": false // boolean (Optional) - If true (or 1), sets response headers to force browser download dialog. Defaults to false (or 0).
}
```

**Notes:**

* **Download Count:** Calling this endpoint consumes one download credit from the user's quota. The count is *not* triggered by actually downloading the file from the returned URL.
* **Temporary URL:** The `link` provided in the response is temporary and valid for approximately 3 hours. Do not cache the URL itself; request a new one if needed. The file *can* be downloaded multiple times from the same temporary URL within its validity period.
* **Encoding:** The subtitle file served from the temporary URL will always be UTF-8 encoded.
* **Conversion:** To convert FPS, **both** `in_fps` and `out_fps` must be provided. You typically get `in_fps` from the `/subtitles` search results.
* **File ID:** Use the `file_id` from the `files` array within a subtitle entry from the `/subtitles` endpoint, *not* the top-level `id` or `subtitle_id`.

**Responses:**

* **`200 OK`**: Download request successful.
* **Body:** `application/json`
```json
{
"link": "https://dl.opensubtitles.com/download/...", // Temporary URL to download the subtitle file
"file_name": "castle.rock.s01e03.webrip.x264-tbs.ettv.-eng.ro.srt", // The actual filename for the download
"requests": 3, // Total downloads made by the user in the current quota period
"remaining": 97, // Remaining downloads in the user's current quota
"message": "Your quota will be renewed in 07 hours and 30 minutes (2022-04-08 13:03:16 UTC)", // User-friendly message about quota reset
"reset_time": "07 hours and 30 minutes", // Time until quota reset (relative)
"reset_time_utc": "2022-04-08T13:03:16.000Z" // Timestamp of quota reset (UTC ISO 8601)
}
```
* **`403 Forbidden`**: Often indicates issues like invalid `file_id`, user out of download quota, missing/invalid Bearer token, or attempting conversion without proper FPS parameters. Check the response body for details.
* **`401 Unauthorized`**: Missing or invalid API Key or Bearer token.
* **Other Responses:** Standard HTTP error codes.

**Example Request:**

```bash
curl --request POST \
--url https://api.opensubtitles.com/api/v1/download \
--header 'Api-Key: YOUR_API_KEY' \
--header 'Authorization: Bearer YOUR_BEARER_TOKEN' \
--header 'User-Agent: MySubtitleApp v1.2.0' \
--header 'Content-Type: application/json' \
--header 'Accept: application/json' \
--data '{
"file_id": 11047023,
"file_name": "Cheers_S01E03.srt"
}'
```

---

### 7. User Information

Retrieves information about the currently authenticated user, including download quota status.

* **Method:** `GET`
* **Path:** `/api/v1/infos/user`
* **Authentication:** `Api-Key` AND `Authorization` (Bearer Token) required.

**Headers:**

* `Api-Key: YOUR_API_KEY` (Required)
* `Authorization: Bearer YOUR_BEARER_TOKEN` (Required)
* `User-Agent: <<APP_NAME}} v{{APP_VERSION}}>>` (Required)
* `Accept: application/json` (Required)

**Query Parameters:** None.

**Notes:**

* This endpoint provides a dedicated way to check user status and remaining downloads.
* Some of this information (like remaining downloads) is also returned in the `/download` response. User details are also returned in the `/login` response.

**Responses:**

* **`200 OK`**: Successfully retrieved user information.
* **Body:** `application/json`
```json
{
"data": {
"allowed_downloads": 100, // Total downloads allowed per quota period
"level": "Sub leecher", // User account level/rank
"user_id": 66, // OpenSubtitles User ID
"ext_installed": false, // Whether the user has the official browser extension installed
"vip": false, // Is the user a VIP member?
"downloads_count": 1, // Total downloads made in the current quota period
"remaining_downloads": 99 // Downloads remaining in the current quota period
}
}
```
* **`401 Unauthorized`**: Missing or invalid API Key or Bearer token.
* **Other Responses:** Standard HTTP error codes.

**Example Request:**

```bash
curl --request GET \
--url https://api.opensubtitles.com/api/v1/infos/user \
--header 'Api-Key: YOUR_API_KEY' \
--header 'Authorization: Bearer YOUR_BEARER_TOKEN' \
--header 'User-Agent: MySubtitleApp v1.2.0' \
--header 'Accept: application/json'
```

---

### 8. Guess Filename Properties (Guessit)

Parses a video filename to extract metadata like title, year, season, episode, quality, source, etc., using the `guessit` library logic.

* **Method:** `GET`
* **Path:** `/api/v1/utilities/guessit`
* **Authentication:** `Api-Key` required.

**Headers:**

* `Api-Key: YOUR_API_KEY` (Required)
* `User-Agent: <<APP_NAME}} v{{APP_VERSION}}>>` (Required)
* `Accept: application/json` (Required)

**Query Parameters:**

| Parameter | Type | Description | Required | Constraints / Allowed Values |
| :-------- | :----- | :---------------------------- | :------- | :--------------------------- |
| `filename`| string | The video filename to parse. | Yes | |

**Notes:**

* Based on the Python `guessit` library: [https://guessit-io.github.io/guessit/](https://guessit-io.github.io/guessit/)
* See `guessit` documentation for examples of detectable properties: [https://guessit-io.github.io/guessit/properties/](https://guessit-io.github.io/guessit/properties/)

**Responses:**

* **`200 OK`**: Successfully parsed the filename.
* **Body:** `application/json` (Returns detected properties. Note: Not all properties will be present for every filename).
```json
// Example for filename: "Stranger.Things.S04E01.Chapter.One.The.Hellfire.Club.1080p.NF.WEBRip.DDP5.1.Atmos.x264-GalaxyTV.mkv"
{
"title": "Stranger Things", // Guessed title
"year": null, // Guessed year (null if not found)
"season": 4, // Guessed season number
"episode": 1, // Guessed episode number
"episode_title": "Chapter One The Hellfire Club", // Guessed episode title
"language": null, // Guessed audio language (null if not specified)
"subtitle_language": null, // Guessed subtitle language (null if not specified)
"screen_size": "1080p", // Guessed resolution/screen size
"streaming_service": "Netflix", // Guessed streaming service (NF -> Netflix)
"source": "WEBRip", // Guessed source (WEBRip, BluRay, DVD, etc.)
"other": null, // Other tags found
"audio_codec": "Dolby Digital Plus", // Guessed audio codec (DDP -> Dolby Digital Plus)
"audio_channels": "5.1", // Guessed audio channels
"audio_profile": "Atmos", // Guessed audio profile
"video_codec": "H.264", // Guessed video codec (x264 -> H.264)
"release_group": "GalaxyTV", // Guessed release group
"type": "episode" // Guessed type (episode, movie)
}
// Example for filename: "The.Matrix.1999.BluRay.1080p.TrueHD.7.1.x264-GRP.mkv"
{
"title": "The Matrix",
"year": 1999,
"season": null,
"episode": null,
"episode_title": null,
"language": null,
"subtitle_language": null,
"screen_size": "1080p",
"streaming_service": null,
"source": "BluRay",
"other": null,
"audio_codec": "TrueHD",
"audio_channels": "7.1",
"audio_profile": null,
"video_codec": "H.264",
"release_group": "GRP",
"type": "movie"
}
```
* **`400 Bad Request`**: Likely missing the required `filename` parameter.
* **`401 Unauthorized`**: Missing or invalid API Key.
* **Other Responses:** Standard HTTP error codes.

**Example Request:**

```bash
curl --request GET \
--url 'https://api.opensubtitles.com/api/v1/ut ... laxyTV.mkv' \
--header 'Api-Key: YOUR_API_KEY' \
--header 'User-Agent: MySubtitleApp v1.2.0' \
--header 'Accept: application/json'
```



### 9. Login

Authenticates a registered OpenSubtitles user and generates a session token (Bearer token) for accessing protected endpoints.

* **Method:** `POST`
* **Path:** `/api/v1/login`
* **Authentication:** `Api-Key` required. User credentials provided in the body.
* **Rate Limit:** 1 request per second. Exceeding this or providing invalid credentials repeatedly may lead to temporary blocking.

**Headers:**

* `Api-Key: YOUR_API_KEY` (Required)
* `User-Agent: <<APP_NAME}} v{{APP_VERSION}}>>` (Required)
* `Content-Type: application/json` (Required)
* `Accept: application/json` (Recommended)

**Request Body:**

* **Content-Type:** `application/json`
```json
{
"username": "YOUR_USERNAME", // string (Required) - OpenSubtitles username.
"password": "YOUR_PASSWORD" // string (Required) - OpenSubtitles password.
}
```

**Notes:**

* **Base URL:** The response includes a `base_url`. **Crucially, all subsequent API requests for this authenticated session *must* use this returned `base_url`**. This might be `api.opensubtitles.com` or `vip-api.opensubtitles.com`. VIP users might get the latter, offering potentially different caching and rate limits.
* **Token Usage:** The returned `token` must be included in the `Authorization: Bearer <token>` header for all endpoints requiring user authentication (e.g., `/download`, `/infos/user`, `/logout`).
* **Expensive Operation:** Login is considered computationally expensive on the server. Avoid logging in unnecessarily. If a `401 Unauthorized` response is received, do not immediately retry with the same credentials without verifying them.

**Responses:**

* **`200 OK`**: Login successful, token generated.
* **Body:** `application/json`
```json
{
"user": { // Information about the authenticated user
"allowed_downloads": 100, // Max downloads per quota period
"allowed_translations": 5, // Max allowed translations (if applicable)
"level": "Sub leecher", // User rank/level
"user_id": 66, // User's OpenSubtitles ID
"ext_installed": false, // Official browser extension installed?
"vip": false // Is user a VIP?
},
"base_url": "api.opensubtitles.com", // **Use this hostname for subsequent requests in this session** (Can be api.opensubtitles.com or vip-api.opensubtitles.com)
"token": "eyJ0eXAiOiJKV1QiLCJ...", // The JWT Bearer token for authentication
"status": 200 // HTTP status code mirrored in the body
}
```
* **`401 Unauthorized`**: Invalid username or password. Do not retry excessively.
* **`403 Forbidden`**: Might indicate account issues (e.g., banned) or incorrect API Key usage.
* **`429 Too Many Requests`**: Login rate limit exceeded.
* **Other Responses:** Standard HTTP error codes.

**Example Request:**

```bash
curl --request POST \
--url https://api.opensubtitles.com/api/v1/login \
--header 'Api-Key: YOUR_API_KEY' \
--header 'User-Agent: MySubtitleApp v1.2.0' \
--header 'Content-Type: application/json' \
--header 'Accept: application/json' \
--data '{
"username": "testuser",
"password": "testpassword"
}'
```

---

### 10. Logout

Invalidates the user's current session token, effectively logging them out.

* **Method:** `DELETE`
* **Path:** `/api/v1/logout`
* **Authentication:** `Api-Key` AND `Authorization` (Bearer Token) required.

**Headers:**

* `Api-Key: YOUR_API_KEY` (Required)
* `Authorization: Bearer YOUR_BEARER_TOKEN` (Required) - The token to be invalidated.
* `User-Agent: <<APP_NAME}} v{{APP_VERSION}}>>` (Required)
* `Accept: application/json` (Recommended)

**Request Body:** None.

**Responses:**

* **`200 OK`**: Logout successful, token invalidated.
* **Body:** `application/json`
```json
{
"message": "token successfully destroyed",
"status": 200
}
```
* **`401 Unauthorized`**: Invalid or missing Bearer token, or token already expired/invalidated.
* **Other Responses:** Standard HTTP error codes.

**Example Request:**

```bash
curl --request DELETE \
--url https://api.opensubtitles.com/api/v1/logout \
--header 'Api-Key: YOUR_API_KEY' \
--header 'Authorization: Bearer YOUR_BEARER_TOKEN' \
--header 'User-Agent: MySubtitleApp v1.2.0' \
--header 'Accept: application/json'
```

---

### 11. Data Schemas / Models

These schemas represent the structure of data objects returned by various endpoints.

#### 11.1 Subtitle Schema

Represents a single subtitle entry, typically found within the `data` array of `/subtitles`, `/discover/latest`, and `/discover/most_downloaded` responses.

```json
{
"id": "string", // Subtitle file group ID (Primary identifier for the group)
"type": "subtitle", // Object type identifier
"attributes": {
"subtitle_id": "string", // Specific subtitle ID (often same as outer 'id')
"language": "string", // Language code (e.g., "en", "es")
"download_count": 0, // Historical download count
"new_download_count": 0, // Recent download count (e.g., last 30 days)
"hearing_impaired": true, // boolean: Is it for hearing impaired?
"hd": true, // boolean: Suitable for HD release?
"fps": 0, // number: Frames per second (0 if unknown/not applicable)
"votes": 0, // number: User votes count
"points": 0, // number: User points score (legacy?)
"ratings": 0, // number: User ratings score
"from_trusted": true, // boolean: Uploaded by a trusted source?
"foreign_parts_only": true, // boolean: Only covers foreign speech?
"ai_translated": true, // boolean: Was this AI translated?
"machine_translated": true, // boolean: Was this machine translated?
"upload_date": "string", // ISO 8601 timestamp (UTC): Upload time
"release": "string", // Associated release name (e.g., "Movie.Title.2023.1080p.BluRay.x264-GROUP")
"comments": "string", // Uploader's comments
"legacy_subtitle_id": 0, // number: ID from the old OpenSubtitles system
"uploader": { // Information about the uploader
"uploader_id": 0, // number: Current system uploader ID (can be null for anonymous)
"name": "string", // Uploader username (can be "Anonymous" or "n/a")
"rank": "string" // Uploader rank/status (e.g., "Trusted member", "Platinum Member")
},
"feature_details": { // Details about the associated Movie/Episode
"feature_id": 0, // number: OpenSubtitles Feature ID
"feature_type": "string", // "Movie" or "Episode"
"year": 0, // number: Release year
"title": "string", // Feature title
"movie_name": "string", // Formatted feature name (e.g., "Show - S01E01 Title")
"imdb_id": 0, // number: IMDB ID (numeric part only)
"tmdb_id": 0, // number: TMDB ID
// --- Episode Specific ---
"season_number": 0, // number: (Present if Episode)
"episode_number": 0, // number: (Present if Episode)
"parent_imdb_id": 0, // number: (Present if Episode) Parent show IMDB ID
"parent_tmdb_id": 0, // number: (Present if Episode) Parent show TMDB ID
"parent_title": "string", // string: (Present if Episode) Parent show title
"parent_feature_id": 0 // number: (Present if Episode) Parent show Feature ID
},
"url": "string", // URL to the subtitle page on opensubtitles.com
"related_links": [ // Array of related website links
{
"label": "string", // Link text
"url": "string", // Link URL
"img_url": "string" // Associated image URL (optional)
}
],
"files": [ // Array of actual subtitle files in this group (usually 1)
{
"file_id": 0, // number: **ID required for the /download endpoint**
"cd_number": 0, // number: Disc number (usually 1)
"file_name": "string" // Original filename of the subtitle file
}
]
}
}
```

#### 11.2 Feature-Tvshow Schema

Represents a TV Show feature, typically found within the `data` array of `/features` or `/discover/popular` responses when `type=tvshow`.

```json
{
"id": "string", // OpenSubtitles Feature ID
"type": "feature", // Object type identifier (could also be "tvshow" depending on context)
"attributes": {
"feature_id": "string", // Same as outer 'id'
"feature_type": "Tvshow", // Explicit type
"title": "string", // Show title
"original_title": "string", // Original language title (if different)
"year": "string", // Start year of the show (string)
"imdb_id": 0, // number: IMDB ID (numeric part)
"tmdb_id": 0, // number: TMDB ID
"title_aka": [ // Array of alternative titles/translations
"string"
],
"url": "string", // URL to the show page on opensubtitles.com
"img_url": "string", // URL/path to the poster image
"subtitles_count": 0, // number: Total subtitles across all seasons/episodes
"subtitles_counts": { // Object: Breakdown of subtitle counts per language
"en": 0,
"fr": 0
// ...other languages
},
"seasons_count": 0, // number: Total number of seasons
"seasons": [ // Array containing season/episode details (content may vary depending on endpoint)
{
"season_number": 1, // number
"episodes": [ // Array of episodes within the season
{
"episode_number": 1, // number
"title": "string", // Episode title
"feature_id": "string" // Episode's Feature ID
// ... other potential episode details
}
]
}
]
}
}
```

#### 11.3 Feature-Episode Schema

Represents a TV Show Episode feature, typically found within the `data` array of `/features` responses when `type=episode` or when querying by an episode ID.

```json
{
"id": "string", // OpenSubtitles Feature ID for the Episode
"type": "feature", // Object type identifier (could also be "episode")
"attributes": {
"feature_id": "string", // Same as outer 'id'
"feature_type": "Episode", // Explicit type
"title": "string", // Episode title
"original_title": "string", // Original language title (can be null/empty object?)
"year": "string", // Air year of the episode (string)
"imdb_id": 0, // number: Episode's IMDB ID (numeric part)
"tmdb_id": 0, // number: Episode's TMDB ID
"parent_imdb_id": 0, // number: Parent TV Show's IMDB ID (numeric part, can be null/empty object?)
"parent_title": "string", // Parent TV Show's title
"parent_tmdb_id": 0, // number: Parent TV Show's TMDB ID
"parent_feature_id": "string", // Parent TV Show's Feature ID
"season_number": 0, // number: Season number
"episode_number": 0, // number: Episode number within the season
"title_aka": [ // Array of alternative titles/translations
"string"
],
"url": "string", // URL to the episode page on opensubtitles.com
"img_url": "string", // URL/path to an image (often placeholder/show poster)
"subtitles_count": 0, // number: Total subtitles for this specific episode
"subtitles_counts": { // Object: Breakdown of subtitle counts per language for this episode
"en": 0,
"fr": 0
// ...other languages
}
}
}
```

#### 11.4 Feature-Movie Schema

Represents a Movie feature, typically found within the `data` array of `/features` or `/discover/popular` responses when `type=movie`.

```json
{
"id": "string", // OpenSubtitles Feature ID for the Movie
"type": "feature", // Object type identifier (could also be "movie")
"attributes": {
"feature_id": "string", // Same as outer 'id'
"feature_type": "Movie", // Explicit type
"title": "string", // Movie title
"original_title": "string", // Original language title (if different)
"year": "string", // Release year (string)
"imdb_id": 0, // number: IMDB ID (numeric part)
"tmdb_id": 0, // number: TMDB ID
"title_aka": [ // Array of alternative titles/translations
"string"
],
"url": "string", // URL to the movie page on opensubtitles.com
"img_url": "string", // URL/path to the poster image
"subtitles_count": 0, // number: Total subtitles for this movie
"subtitles_counts": { // Object: Breakdown of subtitle counts per language
"en": 0,
"fr": 0
// ...other languages
},
// These fields seem less relevant for movies but were included in the example schema.
// They likely default to 0 or null/empty for actual movie features.
"seasons_count": 0, // number: Should be 0 for movies
"parent_title": null, // Should be null/empty for movies
"season_number": 0, // Should be 0/null for movies
"episode_number": null, // Should be null/empty for movies
"parent_imdb_id": null // Should be null/empty for movies
}
}
```

User avatar
oss
Site Admin
Posts: 6192
Joined: Sat Feb 25, 2006 11:26 pm
Contact: Website

Re: Texts from opensubtitles.stoplight.io/docs/opensubtitles-api in one file?

Sat May 24, 2025 7:33 pm

thanks. if you have something to add to docs or change something...let me know, I know documentation is very important

Return to “Developing”

Who is online

Users browsing this forum: No registered users and 2 guests