> For the complete documentation index, see [llms.txt](https://docs.roboflow.com/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.roboflow.com/developer/command-line-interface/upload-a-dataset.md).

# Upload a Dataset

You can upload datasets with images and/or annotations using the Roboflow CLI.

We have prepared a video that walks through how to upload a dataset:

{% embed url="<https://www.loom.com/share/19637984033a466b831af56f9404fa89>" %}

## Upload a Directory

Use `roboflow image upload` with a directory path to bulk-upload a dataset with parallel per-image uploads:

```bash
roboflow image upload /path/to/dataset/folder -p PROJECT_ID
```

Or use the shorthand alias:

```bash
roboflow upload /path/to/dataset/folder -p PROJECT_ID
```

The CLI auto-detects whether the path is a file, directory, or `.zip` file. A directory triggers a bulk import with parallel per-image uploads unless you use `--zip-upload`.

### Options

| Flag                  | Description                               |
| --------------------- | ----------------------------------------- |
| `-p`, `--project`     | Project ID (required)                     |
| `-c`, `--concurrency` | Number of parallel uploads (default: 10)  |
| `-b`, `--batch`       | Batch name for grouping uploads           |
| `-r`, `--retries`     | Retry failed uploads N times (default: 0) |
| `-s`, `--split`       | Override split for all uploaded images    |

Example with options:

```bash
roboflow upload ./my-dataset -p my-project -c 20 -b "april-batch" -r 3
```

## Upload a Zip File

Use zip uploads for larger datasets or when your dataset is already packaged as a `.zip` file. Zip uploads use Roboflow's asynchronous zip upload flow. By default, the CLI uploads the zip file and waits for processing to finish.

To upload an existing zip file:

```bash
roboflow image upload /path/to/dataset.zip -p PROJECT_ID
```

To zip a local directory client-side and upload it with the async zip flow, use `--zip-upload` with the primary command:

```bash
roboflow image upload /path/to/dataset/folder -p PROJECT_ID --zip-upload
```

### Options for Zip Uploads

| Flag              | Description                                                                              |
| ----------------- | ---------------------------------------------------------------------------------------- |
| `-p`, `--project` | Project ID (required)                                                                    |
| `--zip-upload`    | Zip a directory client-side and upload it with the async zip upload flow                 |
| `--no-wait`       | Return immediately after the zip is uploaded instead of waiting for processing to finish |
| `-b`, `--batch`   | Batch name for grouping uploads                                                          |
| `-s`, `--split`   | Split set: train, valid, or test                                                         |
| `-t`, `--tag`     | Comma-separated tag names                                                                |

Example with zip upload options:

```bash
roboflow image upload ./my-dataset.zip -p my-project -s train -t "outdoor,daytime" -b "april-batch"
```

To start processing and return a task ID immediately:

```bash
roboflow image upload ./my-dataset.zip -p my-project --no-wait --json
```

The JSON response includes the asynchronous task ID:

```json
{
  "status": "pending",
  "task_id": "task-123",
  "path": "./my-dataset.zip",
  "project": "my-project",
  "result": {
    "task_id": "task-123",
    "status": "pending"
  }
}
```

Zip uploads do not support `--is-prediction`. Use the regular per-image upload flow for prediction uploads.

## Upload a Single Image

To upload a single image:

```bash
roboflow image upload photo.jpg -p PROJECT_ID
```

### Options for Single Image Upload

| Flag                 | Description                                       |
| -------------------- | ------------------------------------------------- |
| `-p`, `--project`    | Project ID (required)                             |
| `-a`, `--annotation` | Path to annotation file                           |
| `-m`, `--labelmap`   | Path to labelmap file                             |
| `-s`, `--split`      | Split set: train, valid, or test (default: train) |
| `-t`, `--tag`        | Comma-separated tag names                         |
| `-M`, `--metadata`   | JSON string of metadata                           |
| `--is-prediction`    | Mark upload as a prediction                       |
| `-b`, `--batch`      | Batch name                                        |

### Examples

Upload with an annotation:

```bash
roboflow upload photo.jpg -p my-project -a annotation.xml -s valid
```

Upload with tags and metadata:

```bash
roboflow upload photo.jpg -p my-project -t "outdoor,daytime" -M '{"camera_id":"cam001"}'
```

## Supported Project Types

You can upload data for the following project types:

* Object Detection
* Single-Label Classification
* Multi-Label Classification
* Instance Segmentation
* Semantic Segmentation
* Keypoint Detection

## Supported data.yaml Formats

The CLI supports both list-style and key-value pair formatted class name mappings in `data.yaml` files during dataset uploads:

```yaml
nc: 3
names: ['Paper', 'Rock', 'Scissors']
```

OR

```yaml
nc: 3
names:
  0: Paper
  1: Rock
  2: Scissors
```

## JSON Output

For automation, use `--json`:

```bash
roboflow upload photo.jpg -p my-project --json
```

```json
{"status": "uploaded", "path": "photo.jpg", "project": "my-project"}
```
