Upload from a URL

In this guide you'll learn how to upload a video file from a publicly accessible URL. The API service will retrieve the file directly from the specified URL, so your application doesn't have to store the video locally and upload the bytes.

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, see the Create indexes page.
  • The URL of the video that you want to upload is stored in a variable named VIDEO_URL.
  • 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. If you're using Python, declare a dictionary named data and use it to store the unique identifier of your index, the language, and the URL of your video. If you're using Node.js, declare a variable named formData of type FormData and use it to store the unique identifier of your index, the language, and the URL of your video:

    data = {
      "index_id": INDEX_ID,
      "language": "en",
      "video_url": VIDEO_URL,
    let formData = new FormData()
    formData.append('index_id', INDEX_ID)
    formData.append('language', 'en')
    formData.append('video_url', VIDEO_URL)
  3. 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}, json=data)
    let config = {
        method: 'post',
        url: TASKS_URL,
        headers: headers,
        data : formData
    let resp = await axios(config)
    let response = await resp.data
  4. Store the ID of your 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"
  5. (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)



    • For details about the possible statuses, see the Tasks page.
    • You can also use webhooks to monitor the status of the indexing process. For details, see the Webhooks section.
  6. (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
  7. (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'}