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

# Image Groups and Image Sequences

> Learn how to create Image Groups and Image Sequences in Encord using the SDK.

Image groups can consist of images with different dimensions. In contrast, image sequences are images that all have the same dimensions. When images of varying dimensions are grouped together, multiple image sequences are created, each containing files that share the same dimensions.

## Create Image Groups

**From Existing Files**

<CodeGroup>
  ```python Create Image Groups - Basic expandable theme={"dark"}

  from pathlib import Path
  from uuid import UUID

  from encord import EncordUserClient

  # --- Configuration ---
  SSH_PATH = "/Users/chris-encord/ssh-private-key.txt"
  FOLDER_ID = "00000000-0000-0000-0000-000000000000"

  # --- Connect to Encord ---
  user_client: EncordUserClient = EncordUserClient.create_with_ssh_private_key(
      ssh_private_key_path=SSH_PATH,
      # For US platform users use "https://api.us.encord.com"
      domain="https://api.encord.com",
  )

  folder = user_client.get_storage_folder(FOLDER_ID)

  group_uuid: UUID = folder.create_image_group(
      file_paths=[
          Path("/path/to/front.jpg"),
          Path("/path/to/side.jpg"),
          Path("/path/to/rear.jpg"),
      ],
      title="vehicle-inspection-001",
  )

  print(f"Created image group with UUID: {group_uuid}")
  ```

  ```python Create Image Groups - Advanced expandable theme={"dark"}

  from pathlib import Path
  from uuid import UUID

  from encord import EncordUserClient

  # --- Configuration ---
  SSH_PATH = "/Users/chris-encord/ssh-private-key.txt"
  FOLDER_ID = "00000000-0000-0000-0000-000000000000"

  # --- Connect to Encord ---
  user_client: EncordUserClient = EncordUserClient.create_with_ssh_private_key(
      ssh_private_key_path=SSH_PATH,
      domain="https://api.encord.com",
  )

  folder = user_client.get_storage_folder(FOLDER_ID)

  image_groups = [
      {
          "title": "vehicle-inspection-001",
          "file_paths": [
              Path("./images/vehicle-001/front.jpg"),
              Path("./images/vehicle-001/side.jpg"),
              Path("./images/vehicle-001/rear.jpg"),
          ],
          "client_metadata": {
              "inspection_id": "001",
              "vehicle_type": "car",
          },
      },
      {
          "title": "vehicle-inspection-002",
          "file_paths": [
              Path("./images/vehicle-002/front.jpg"),
              Path("./images/vehicle-002/side.jpg"),
              Path("./images/vehicle-002/rear.jpg"),
          ],
          "client_metadata": {
              "inspection_id": "002",
              "vehicle_type": "truck",
          },
      },
  ]

  for image_group in image_groups:
      group_uuid: UUID = folder.create_image_group(
          file_paths=image_group["file_paths"],
          title=image_group["title"],
          client_metadata=image_group["client_metadata"],
      )

      print(
          f"Created image group '{image_group['title']}' "
          f"with UUID: {group_uuid}"
      )
  ```
</CodeGroup>

**From Local Files**

<CodeGroup>
  ```python Create Image Groups from Items - Basic expandable theme={"dark"}

  from encord import EncordUserClient
  from encord.orm.dataset import LongPollingStatus
  from encord.orm.storage import DataUploadImageGroupFromItems
  from encord.storage import DataUploadItems

  user_client = EncordUserClient.create_with_ssh_private_key(
      ssh_private_key_path="<private_key_path>"
  )

  storage_folder = user_client.get_storage_folder("<folder_hash>")

  image_group = DataUploadImageGroupFromItems(
      image_items=[
          "11111111-1111-1111-1111-111111111111",
          "22222222-2222-2222-2222-222222222222",
          "33333333-3333-3333-3333-333333333333",
      ],
      title="My Image Group",
  )

  upload_job_id = storage_folder.add_private_data_to_folder_start(
      integration_id="<integration_id>",
      private_files=DataUploadItems(
          image_groups_from_items=[image_group]
      ),
  )

  result = storage_folder.add_private_data_to_folder_get_result(upload_job_id)

  if result.status == LongPollingStatus.DONE:
      print("Image group created successfully!")
  ```

  ```python Create Image Groups from Items - Advanced expandable theme={"dark"}

  from encord import EncordUserClient
  from encord.orm.dataset import LongPollingStatus
  from encord.orm.storage import DataUploadImageGroupFromItems
  from encord.storage import DataUploadItems

  # --- Configuration ---
  SSH_PATH = "/Users/chris-encord/ssh-private-key.txt"  # Replace with your SSH private key path
  FOLDER_ID = "00000000-0000-0000-0000-000000000000"  # Replace with the Folder ID
  INTEGRATION_ID = "00000000-0000-0000-0000-000000000000"  # Replace with the Integration ID

  # --- Connect to Encord ---
  user_client = EncordUserClient.create_with_ssh_private_key(
      ssh_private_key_path=SSH_PATH,
      # For US platform users use "https://api.us.encord.com"
      domain="https://api.encord.com",
  )

  storage_folder = user_client.get_storage_folder(FOLDER_ID)

  image_groups = [
      DataUploadImageGroupFromItems(
          image_items=[
              "11111111-1111-1111-1111-111111111111",
              "22222222-2222-2222-2222-222222222222",
              "33333333-3333-3333-3333-333333333333",
          ],
          title="vehicle-inspection-001",
          client_metadata={
              "inspection_id": "001",
              "vehicle_type": "car",
          },
      ),
      DataUploadImageGroupFromItems(
          image_items=[
              "44444444-4444-4444-4444-444444444444",
              "55555555-5555-5555-5555-555555555555",
              "66666666-6666-6666-6666-666666666666",
          ],
          title="vehicle-inspection-002",
          client_metadata={
              "inspection_id": "002",
              "vehicle_type": "truck",
          },
      ),
  ]

  upload_job_id = storage_folder.add_private_data_to_folder_start(
      integration_id=INTEGRATION_ID,
      private_files=DataUploadItems(
          image_groups_from_items=image_groups,
      ),
  )

  result = storage_folder.add_private_data_to_folder_get_result(upload_job_id)

  if result.status == LongPollingStatus.DONE:
      print(f"Successfully created {len(image_groups)} image groups.")
  ```
</CodeGroup>

## Create Image Sequences

**From Existing Files**

<CodeGroup>
  ```python Create Image Sequences - Basic expandable theme={"dark"}

  from pathlib import Path
  from uuid import UUID

  from encord import EncordUserClient

  # --- Configuration ---
  SSH_PATH = "/Users/chris-encord/ssh-private-key.txt"
  FOLDER_ID = "00000000-0000-0000-0000-000000000000"

  # --- Connect to Encord ---
  user_client: EncordUserClient = EncordUserClient.create_with_ssh_private_key(
      ssh_private_key_path=SSH_PATH,
      # For US platform users use "https://api.us.encord.com"
      domain="https://api.encord.com",
  )

  folder = user_client.get_storage_folder(FOLDER_ID)

  sequence_uuid: UUID = folder.create_image_sequence(
      file_paths=[
          Path("/path/to/frame001.jpg"),
          Path("/path/to/frame002.jpg"),
          Path("/path/to/frame003.jpg"),
      ],
      title="drive-sequence-001",
  )

  print(f"Created image sequence with UUID: {sequence_uuid}")
  ```

  ```python Create Image Sequences - Advanced expandable theme={"dark"}

  from pathlib import Path
  from uuid import UUID

  from encord import EncordUserClient

  # --- Configuration ---
  SSH_PATH = "/Users/chris-encord/ssh-private-key.txt"  # Replace with the file path to your SSH private key
  FOLDER_ID = "00000000-0000-0000-0000-000000000000"  # Replace with the Folder ID

  # --- Connect to Encord ---
  user_client: EncordUserClient = EncordUserClient.create_with_ssh_private_key(
      ssh_private_key_path=SSH_PATH,
      # For US platform users use "https://api.us.encord.com"
      domain="https://api.encord.com",
  )

  folder = user_client.get_storage_folder(FOLDER_ID)

  image_sequences = [
      {
          "title": "drive-sequence-001",
          "file_paths": [
              Path("/path/to/frame001.jpg"),
              Path("/path/to/frame002.jpg"),
              Path("/path/to/frame003.jpg"),
          ],
          "client_metadata": {
              "sequence_id": "001",
              "scenario": "urban",
          },
      },
      {
          "title": "drive-sequence-002",
          "file_paths": [
              Path("/path/to/frame004.jpg"),
              Path("/path/to/frame005.jpg"),
              Path("/path/to/frame006.jpg"),
          ],
          "client_metadata": {
              "sequence_id": "002",
              "scenario": "highway",
          },
      },
  ]

  for image_sequence in image_sequences:
      sequence_uuid: UUID = folder.create_image_sequence(
          file_paths=image_sequence["file_paths"],
          title=image_sequence["title"],
          client_metadata=image_sequence["client_metadata"],
      )

      print(
          f"Created image sequence '{image_sequence['title']}' "
          f"with UUID: {sequence_uuid}"
      )
  ```
</CodeGroup>

**From Local Files**

<CodeGroup>
  ```python Create Image Sequences from Items - Basic expandable theme={"dark"}

  from encord import EncordUserClient
  from encord.orm.dataset import LongPollingStatus
  from encord.orm.storage import DataUploadImageGroupFromItems
  from encord.storage import DataUploadItems

  # --- Configuration ---
  SSH_PATH = "/Users/chris-encord/ssh-private-key.txt"  # Replace with your SSH private key path
  FOLDER_ID = "00000000-0000-0000-0000-000000000000"  # Replace with the Folder ID
  INTEGRATION_ID = "00000000-0000-0000-0000-000000000000"  # Replace with the Integration ID

  # --- Connect to Encord ---
  user_client = EncordUserClient.create_with_ssh_private_key(
      ssh_private_key_path=SSH_PATH,
      domain="https://api.encord.com",
  )

  storage_folder = user_client.get_storage_folder(FOLDER_ID)

  image_sequence = DataUploadImageGroupFromItems(
      image_items=[
          "11111111-1111-1111-1111-111111111111",
          "22222222-2222-2222-2222-222222222222",
          "33333333-3333-3333-3333-333333333333",
      ],
      title="drive-sequence-001",
      create_video=True,
  )

  upload_job_id = storage_folder.add_private_data_to_folder_start(
      integration_id=INTEGRATION_ID,
      private_files=DataUploadItems(
          image_groups_from_items=[image_sequence],
      ),
  )

  result = storage_folder.add_private_data_to_folder_get_result(upload_job_id)

  if result.status == LongPollingStatus.DONE:
      print("Image sequence created successfully.")
  ```

  ```python Create Image Sequences from Items - Advanced expandable theme={"dark"}

  from encord import EncordUserClient
  from encord.orm.dataset import LongPollingStatus
  from encord.orm.storage import DataUploadImageGroupFromItems
  from encord.storage import DataUploadItems

  # --- Configuration ---
  SSH_PATH = "/Users/chris-encord/ssh-private-key.txt"  # Replace with your SSH private key path
  FOLDER_ID = "00000000-0000-0000-0000-000000000000"  # Replace with the Folder ID
  INTEGRATION_ID = "00000000-0000-0000-0000-000000000000"  # Replace with the Integration ID

  # --- Connect to Encord ---
  user_client = EncordUserClient.create_with_ssh_private_key(
      ssh_private_key_path=SSH_PATH,
      domain="https://api.encord.com",
  )

  storage_folder = user_client.get_storage_folder(FOLDER_ID)

  image_sequences = [
      DataUploadImageGroupFromItems(
          image_items=[
              "11111111-1111-1111-1111-111111111111",
              "22222222-2222-2222-2222-222222222222",
              "33333333-3333-3333-3333-333333333333",
          ],
          title="drive-sequence-001",
          create_video=True,
          client_metadata={
              "sequence_id": "001",
              "scenario": "urban",
          },
      ),
      DataUploadImageGroupFromItems(
          image_items=[
              "44444444-4444-4444-4444-444444444444",
              "55555555-5555-5555-5555-555555555555",
              "66666666-6666-6666-6666-666666666666",
          ],
          title="drive-sequence-002",
          create_video=True,
          client_metadata={
              "sequence_id": "002",
              "scenario": "highway",
          },
      ),
  ]

  upload_job_id = storage_folder.add_private_data_to_folder_start(
      integration_id=INTEGRATION_ID,
      private_files=DataUploadItems(
          image_groups_from_items=image_sequences,
      ),
  )

  result = storage_folder.add_private_data_to_folder_get_result(upload_job_id)

  if result.status == LongPollingStatus.DONE:
      print(f"Successfully created {len(image_sequences)} image sequences.")
  ```
</CodeGroup>

## Create at Scale

For large-scale imports, create image groups and image sequences from a JSON manifest. This is the recommended approach when importing hundreds or thousands of grouped images because it avoids making one SDK request per group.

### Image Groups

<CodeGroup>
  ```python Image Groups at Scale theme={"dark"}

  from pathlib import Path

  from encord import EncordUserClient
  from encord.orm.dataset import LongPollingStatus
  from encord.storage import DataUploadItems

  SSH_PATH = "/path/to/ssh-private-key.txt"
  FOLDER_ID = "00000000-0000-0000-0000-000000000000"
  JSON_FILE = Path("./image-groups.json")

  user_client = EncordUserClient.create_with_ssh_private_key(
      ssh_private_key_path=SSH_PATH,
      # For US platform users use "https://api.us.encord.com"
      domain="https://api.encord.com",
  )

  folder = user_client.get_storage_folder(FOLDER_ID)

  upload_job_id = folder.add_private_data_to_folder_start(
      DataUploadItems(file_path=JSON_FILE)
  )

  result = folder.add_private_data_to_folder_get_result(
      upload_job_id,
      timeout_seconds=600,
  )

  if result.status == LongPollingStatus.DONE:
      print("Upload complete.")
      print(result)
  else:
      print("Upload did not complete within the timeout.")
      print(result)
  ```

  ```json image-groups.json theme={"dark"}
  {
    "image_groups": [
      {
        "title": "vehicle-inspection-001",
        "createVideo": false,
        "objectUrl_0": "s3://my-bucket/vehicle-001/front.jpg",
        "objectUrl_1": "s3://my-bucket/vehicle-001/side.jpg",
        "objectUrl_2": "s3://my-bucket/vehicle-001/rear.jpg",
        "clientMetadata": {
          "inspection_id": "001",
          "vehicle_type": "car"
        }
      },
      {
        "title": "vehicle-inspection-002",
        "createVideo": false,
        "objectUrl_0": "s3://my-bucket/vehicle-002/front.jpg",
        "objectUrl_1": "s3://my-bucket/vehicle-002/side.jpg",
        "objectUrl_2": "s3://my-bucket/vehicle-002/rear.jpg",
        "clientMetadata": {
          "inspection_id": "002",
          "vehicle_type": "truck"
        }
      },
      {
        "title": "vehicle-inspection-003",
        "createVideo": false,
        "objectUrl_0": "s3://my-bucket/vehicle-003/front.jpg",
        "objectUrl_1": "s3://my-bucket/vehicle-003/side.jpg",
        "objectUrl_2": "s3://my-bucket/vehicle-003/rear.jpg",
        "clientMetadata": {
          "inspection_id": "003",
          "vehicle_type": "van"
        }
      }
    ],
    "skip_duplicate_urls": true
  }
  ```
</CodeGroup>

### Image Sequences

<CodeGroup>
  ```python Image Sequences at Scale theme={"dark"}
  from pathlib import Path

  from encord import EncordUserClient
  from encord.orm.dataset import LongPollingStatus
  from encord.storage import DataUploadItems

  SSH_PATH = "/path/to/ssh-private-key.txt"
  FOLDER_ID = "00000000-0000-0000-0000-000000000000"
  JSON_FILE = Path("./image-sequences.json")

  user_client = EncordUserClient.create_with_ssh_private_key(
      ssh_private_key_path=SSH_PATH,
      # For US platform users use "https://api.us.encord.com"
      domain="https://api.encord.com",
  )

  folder = user_client.get_storage_folder(FOLDER_ID)

  upload_job_id = folder.add_private_data_to_folder_start(
      DataUploadItems(file_path=JSON_FILE)
  )

  result = folder.add_private_data_to_folder_get_result(
      upload_job_id,
      timeout_seconds=600,
  )

  if result.status == LongPollingStatus.DONE:
      print("Upload complete.")
      print(result)
  else:
      print("Upload did not complete within the timeout.")
      print(result)

  ```

  ```json image-sequences.json theme={"dark"}
  {
    "image_groups": [
      {
        "title": "drive-sequence-001",
        "createVideo": true,
        "objectUrl_0": "s3://my-bucket/drive-001/frame_0001.jpg",
        "objectUrl_1": "s3://my-bucket/drive-001/frame_0002.jpg",
        "objectUrl_2": "s3://my-bucket/drive-001/frame_0003.jpg",
        "clientMetadata": {
          "sequence_id": "001",
          "scenario": "urban"
        }
      },
      {
        "title": "drive-sequence-002",
        "createVideo": true,
        "objectUrl_0": "s3://my-bucket/drive-001/frame_0001.jpg",
        "objectUrl_1": "s3://my-bucket/drive-001/frame_0002.jpg",
        "objectUrl_2": "s3://my-bucket/drive-001/frame_0003.jpg",
        "clientMetadata": {
          "sequence_id": "002",
          "scenario": "urban"
        }
      },
      {
        "title": "drive-sequence-003",
        "createVideo": true,
        "objectUrl_0": "s3://my-bucket/drive-001/frame_0001.jpg",
        "objectUrl_1": "s3://my-bucket/drive-001/frame_0002.jpg",
        "objectUrl_2": "s3://my-bucket/drive-001/frame_0003.jpg",
        "clientMetadata": {
          "sequence_id": "003",
          "scenario": "urban"
        }
      }
    ],
    "skip_duplicate_urls": true
  }
  ```
</CodeGroup>
