Upload from the local file system

In this guide you'll learn how to upload a video file from the local file system to the API service. For a description of each field in the request and response, see the API Reference > Create a video indexing task page.


  • You’re familiar with the concepts that are described on the Platform overview page.
  • You’ve created an index, and the unique identifier of your index is stored in a variable named INDEX_ID. For details about creating an index, see the Create indexes page.
  • Your video must meet the following requirements:
    • Video resolution: must be greater or equal than 360p and less or equal than 4K.
    • Duration: must be between 4 seconds and 2 hours (7,200s).
    • File size: must not exceed 2 GB.
      If you require different options, send us an email at [email protected].
    • Audio track: If the conversation indexing option is selected, the video you're uploading must contain an audio track.



For consistent search results, Twelve Labs recommends you upload 360p videos.


  1. Declare the /tasks endpoint:

    TASKS_URL = f"{API_URL}/tasks"
    const TASKS_URL = `${API_URL}/tasks`
  2. Read your video file. Open a stream, making sure to replace the placeholders surrounded by <> with your values:

    file_name = "<YOUR_FILE_NAME>"
    file_path = "<YOUR_FILE_PATH>"
    file_stream = open(file_path,"rb")
    const file_path = '<YOUR_FILE_PATH>'
    const file_stream = fs.createReadStream(file_path)
  3. If you're using Python, store the unique identifier of your index and the language of your video in a dictionary named data and the file to upload in an array named file_param. If you're using Node.js, store the unique identifier of your index, the language of the video, and the file to upload in a variable named formData of type FormData:

    data = {
        "index_id": INDEX_ID, 
        "language": "en"
    file_param = [
        ("video_file", (file_name, file_stream, "application/octet-stream")),]
    let formData = new FormData()
    formData.append('INDEX_ID', INDEX_ID)
    formData.append('language', 'en')
    formData.append('video_file', file_stream)
  4. Upload your video. Call the POST method of the /tasks endpoint and store the result in a variable named response:

    response = requests.post(TASKS_URL, headers={"x-api-key": API_KEY}, data=data, files=file_param)
    const resp = await axios.post(
    		'headers': {
    			'Content-Type': 'multipart/form-data',
    			'x-api-key': process.env.API_KEY
    const response = await resp.data
  5. Store the unique identifier of your video indexing task in a variable named TASK_ID and print the status code and response:

    TASK_ID = response.json().get("_id")
    print (f"Status code: {response.status_code}")
    pprint (response.json())
    const TASK_ID = response._id
    console.log(`Status code: ${resp.status}`)

    The output should look similar to the following one:

    Status code: 200
      "_id": "6396bf71a62a34ad8ad3ed20"
  6. (Optional) The API service must have finished indexing your video before it becomes searchable. You can use the GET method of the /tasks/{_id} endpoint to monitor the indexing process. Construct the URL for retrieving the status of your video indexing task based on the TASK_ID variable you’ve declared in the previous step, and wait until the status shows as ready:

    TASK_STATUS_URL = f"{API_URL}/tasks/{TASK_ID}"
    while True:
        response = requests.get(TASK_STATUS_URL, headers={"x-api-key": API_KEY})
        STATUS = response.json().get("status")
        if STATUS == "ready":
    const TASK_STATUS_URL = `${API_URL}/tasks/${TASK_ID}`
    const uploadResp = await new Promise((res) => {
      const interval = setInterval(async () => {
          const { data: response } = await axios.get(
                    headers: {
                        'x-api-key': API_KEY
            if (response.status == 'ready') {
        }, 1000)



    • You can also use webhooks to monitor the status of the indexing process. For details, see the Webhooks section.
    • For details about the possible statuses, see the API Reference > Tasks page.
  7. (Optional) Store the unique identifier of your video in a variable named VIDEO_ID:

    VIDEO_ID = response.json().get('video_id')
    const VIDEO_ID = uploadResp.video_id
  8. (Optional) Print the unique identifier of your video, the status code, and the response:

    print (f"Status code: {STATUS}")
    print(f"VIDEO ID: {VIDEO_ID}")
    pprint (response.json())
    console.log(`Status code: ${uploadResp.status}`)
    console.log(`VIDEO_ID: ${VIDEO_ID}`)

    The output should look similar to the following one:

    Status code: 200
    VIDEO ID: 6391c8a669ff3402ec515aba
    {'_id': '6391c89afb14854546891276',
      'created_at': '2022-12-08T11:20:58.859Z',
      'estimated_time': '2022-12-08T11:34:54.585Z',
      'index_id': '6391c88bfb14854546891275',
      'metadata': {'duration': 810.84,
        'filename': 'best-racing-moments.mp4',
        'height': 480,
        'width': 854},
      'status': 'ready',
      'type': 'index_task_info',
      'updated_at': '2022-12-08T11:34:50.474Z',
      'video_id': '6391c8a669ff3402ec515aba'}