Upload from the local file system

This guide shows how you can upload a video file from the local file system. 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. For consistent search results, Twelve Labs recommends you upload 360p videos.
    • Duration: For Marengo, it must be between 4 seconds and 2 hours (7,200s). For Pegasus, it must be between 5 seconds and 30 minutes (1800s).
    • File size: Must not exceed 2 GB.
      If you require different options, send us an email at [email protected].
    • Audio track: If the conversation engine option is selected, the video you're uploading must contain an audio track.


  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 platform 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"