> ## Documentation Index
> Fetch the complete documentation index at: https://docs.supadata.ai/llms.txt
> Use this file to discover all available pages before exploring further.

# Batch

> Get multiple transcripts or video metadata from YouTube videos in a playlist, channel or list of URLs.

The batch endpoints allow you to process multiple YouTube videos in a single request. This is useful for analyzing entire playlists or channels, or for processing a list of videos. Batch operations are asynchronous and return a job ID that can be used to check the results.

Batch transcripts and metadata are part of Supadata's [YouTube Transcript API](https://supadata.ai/youtube-transcript-api) and [YouTube API](https://supadata.ai/youtube-api).

<Info>This feature is available on Pro and above.</Info>

## Supported Source Types

All batch endpoints support the following source types:

* List of video URLs or IDs
* Playlist URL or ID
* Channel URL, handle, or ID

<Note>
  Playlist and channel batches include regular videos only. Shorts and live
  videos are not part of the batch.
</Note>

## Batch Endpoints

### Transcript Batch

#### Request

<CodeGroup>
  ```js Node theme={null}
  import {
    Supadata,
  } from '@supadata/js';
  // Initialize the client
  const supadata = new Supadata({
    apiKey: 'YOUR_API_KEY',
  });

  // Start a YouTube transcript batch job
  const transcriptBatch = await supadata.youtube.transcript.batch({
    videoIds: ['dQw4w9WgXcQ', 'xvFZjo5PgG0'],
    // playlistId: 'PLlaN88a7y2_plecYoJxvRFTLHVbIVAOoc' // alternatively
    // channelId: 'UC_9-kyTW8ZkZNDHQJ6FgpwQ' // alternatively
    lang: 'en',
  });
  console.log(`Started transcript batch job: ${transcriptBatch.jobId}`);
  ```

  ```python Python theme={null}
  from supadata import Supadata, SupadataError

  # Initialize the client
  supadata = Supadata(api_key="YOUR_API_KEY")

  transcript_batch_job = supadata.youtube.transcript.batch(
      video_ids=["dQw4w9WgXcQ", "xvFZjo5PgG0"],
      # playlist_id="PLlaN88a7y2_plecYoJxvRFTLHVbIVAOoc", # alternatively
      # channel_id="UC_9-kyTW8ZkZNDHQJ6FgpwQ", # alternatively
      lang="en",  # Optional: specify preferred transcript language
      limit=100   # Optional: limit for playlist/channel
  )
  print(f"Started transcript batch job: {transcript_batch_job.job_id}")
  ```

  ```bash cURL theme={null}
  curl -X POST 'https://api.supadata.ai/v1/youtube/transcript/batch' \
  -H 'x-api-key: YOUR_API_KEY' \
  -H 'Content-Type: application/json' \
  -d '{
    "videoIds": [
      "dQw4w9WgXcQ",
      "https://www.youtube.com/watch?v=xvFZjo5PgG0"
    ],
    "lang": "en",
    "text": true
  }'
  ```
</CodeGroup>

#### Parameters

| Parameter | Type | Required | Description |
| - | - | - | - |
| videoIds | array | One of these is required | Array of YouTube video IDs or URLs |
| playlistId | string | One of these is required | YouTube playlist URL or ID |
| channelId | string | One of these is required | YouTube channel URL, handle or ID |
| limit | number | No | Maximum number of videos to process (when using playlistId or channelId). Default: 10, Max: 5000 |
| lang | string | No | Preferred language code for transcripts (ISO 639-1) |
| text | boolean | No | When true, returns plain text transcript. Default: false |

#### Response

```json theme={null}
{
  "jobId": "123e4567-e89b-12d3-a456-426614174000"
}
```

### Video Metadata Batch

#### Request

<CodeGroup>
  ```js Node theme={null}
  import {
    Supadata,
  } from '@supadata/js';
  // Initialize the client
  const supadata = new Supadata({
    apiKey: 'YOUR_API_KEY',
  });

  // Start a YouTube video metadata batch job
  const videoBatch = await supadata.youtube.video.batch({
    playlistId: 'PLlaN88a7y2_plecYoJxvRFTLHVbIVAOoc',
    limit: 20,
    // videoIds: ['dQw4w9WgXcQ', 'xvFZjo5PgG0'] // alternatively
    // channelId: 'UC_9-kyTW8ZkZNDHQJ6FgpwQ' // alternatively
  });
  console.log(`Started video metadata batch job: ${videoBatch.jobId}`);
  ```

  ```python Python theme={null}
  from supadata import Supadata

  # Initialize the client
  supadata = Supadata(api_key="YOUR_API_KEY")

  video_batch_job = supadata.youtube.video.batch(
      playlist_id="PLlaN88a7y2_plecYoJxvRFTLHVbIVAOoc",
      limit=20
      # video_ids=["dQw4w9WgXcQ", "xvFZjo5PgG0"], # alternatively
      # channel_id="UC_9-kyTW8ZkZNDHQJ6FgpwQ", # alternatively
  )
  print(f"Started video metadata batch job: {video_batch_job.job_id}")
  ```

  ```bash cURL theme={null}
  curl -X POST 'https://api.supadata.ai/v1/youtube/video/batch' \
  -H 'x-api-key: YOUR_API_KEY' \
  -H 'Content-Type: application/json' \
  -d '{
    "playlistId": "PLlaN88a7y2_plecYoJxvRFTLHVbIVAOoc",
    "limit": 20
  }'
  ```
</CodeGroup>

#### Parameters

| Parameter | Type | Required | Description |
| - | - | - | - |
| videoIds | array | One of these is required | Array of YouTube video IDs or URLs |
| playlistId | string | One of these is required | YouTube playlist URL or ID |
| channelId | string | One of these is required | YouTube channel URL, handle or ID |
| limit | number | No | Maximum number of videos to process (when using playlistId or channelId). Default: 10, Max: 5000 |

#### Response

```json theme={null}
{
  "jobId": "123e4567-e89b-12d3-a456-426614174000"
}
```

## Getting Batch Results

Once you've created a batch job, you can check its status and retrieve results using the job ID.

### Check Batch Job Status

`GET /v1/youtube/batch/{jobId}` - Get the status and results of a batch job.

#### Parameters

| Parameter | Type | Required | Description |
| - | - | - | - |
| jobId | string | Yes | The ID of the batch job (path parameter) |
| limit | number | No | Query parameter. Return at most this many results (1-500). Together with `offset`, pages through a completed batch. Omit both to receive all results in one response. |
| offset | number | No | Query parameter. Skip this many results (in submission order) before returning a page. Default: 0 |

#### Request

<CodeGroup>
  ```js Node theme={null}
  import { Supadata } from "@supadata/js";

  const supadata = new Supadata({ apiKey: "YOUR_API_KEY" });

  // Check the status of a batch job
  const batchResult = await supadata.youtube.batch.getBatchResults(jobId);

  if (batchResult.status === "completed") {
    console.log("Batch job completed successfully!");
    console.log(`Total videos: ${batchResult.stats.total}`);
    console.log(`Succeeded: ${batchResult.stats.succeeded}`);
    console.log(`Failed: ${batchResult.stats.failed}`);

    // Process each result
    batchResult.results.forEach((result, index) => {
      if (result.transcript) {
        console.log(`Video ${index + 1}: ${result.videoId}`);
        console.log(`Transcript: ${result.transcript.content}`);
        console.log(`Language: ${result.transcript.lang}`);
      } else if (result.errorCode) {
        console.log(`Video ${index + 1} failed: ${result.errorCode}`);
      }
    });
  } else if (batchResult.status === "failed") {
    console.error("Batch job failed");
  } else {
    console.log("Job status:", batchResult.status);
  }
  ```

  ```python Python theme={null}
  from supadata import Supadata

  supadata = Supadata(api_key="YOUR_API_KEY")

  # Check the status of a batch job
  batch_result = supadata.youtube.batch.get_batch_results(job_id)

  if batch_result.status == "completed":
      print("Batch job completed successfully!")
      print(f"Total videos: {batch_result.stats.total}")
      print(f"Succeeded: {batch_result.stats.succeeded}")
      print(f"Failed: {batch_result.stats.failed}")

      # Process each result
      for i, result in enumerate(batch_result.results):
          if hasattr(result, 'transcript') and result.transcript:
              print(f"Video {i + 1}: {result.video_id}")
              print(f"Transcript: {result.transcript.content}")
              print(f"Language: {result.transcript.lang}")
          elif hasattr(result, 'error_code'):
              print(f"Video {i + 1} failed: {result.error_code}")
  elif batch_result.status == "failed":
      print("Batch job failed")
  else:
      print(f"Job status: {batch_result.status}")
  ```

  ```bash cURL theme={null}
  curl -X GET 'https://api.supadata.ai/v1/youtube/batch/123e4567-e89b-12d3-a456-426614174000' \
    -H 'x-api-key: YOUR_API_KEY'
  ```
</CodeGroup>

#### Response

```json theme={null}
{
  "status": "completed",
  "results": [
    {
      "videoId": "dQw4w9WgXcQ",
      "transcript": {
        "content": "Never gonna give you up, never gonna let you down...",
        "lang": "en",
        "availableLangs": ["en", "es", "fr"]
      }
    },
    {
      "videoId": "xvFZjo5PgG0",
      "errorCode": "transcript-unavailable"
    }
  ],
  "stats": {
    "total": 2,
    "succeeded": 1,
    "failed": 1
  },
  "completedAt": "2025-04-03T06:59:53.428Z"
}
```

## Batch Job Status

The batch job can be in one of the following states:

| Status | Description |
| - | - |
| queued | The job is in the queue waiting to be processed |
| active | The job is currently being processed |
| completed | The job has finished processing all videos |
| failed | The job failed due to an error |

If a job was abandoned before finishing and has aged out, the response also carries a top-level `"errorCode": "job-expired"`.

### Per-video error codes

Each entry in `results` has either a `transcript` / `video` object or an `errorCode`. Besides the standard [error codes](/errors) such as `transcript-unavailable` and `not-found`, two batch-specific codes can appear:

| errorCode | Description |
| - | - |
| processing | The video has not finished processing yet (only while the job is still `active`) |
| result-unavailable | The job completed but no result was stored for this video |

<Info>
  Batch jobs are processed asynchronously and may take some time to complete,
  especially for large playlists or channels. You should poll the job status
  endpoint until the status is either "completed" or "failed".
</Info>

## Pricing

* 1 video in a batch = 1 credit

Credits are charged when the job is submitted (one per requested video) and settled to the actual count when the job finishes. Videos whose transcript is unavailable are billed; videos that failed for other reasons are not. Polling the job status endpoint is free.


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.