> For AI agents: the complete Sanity documentation index is available at [https://www.sanity.io/docs/llms.txt](https://www.sanity.io/docs/llms.txt).

# Export a dataset

How to export a dataset with the Sanity CLI, what the export archive contains, and how asset binaries are handled.

Exporting a dataset downloads its documents and asset binaries to a local gzipped tarball. It's the usual starting point for migrating content between datasets or projects, taking a point-in-time copy before a risky change, or working with content outside a studio.

This guide explains how to export a dataset with the Sanity CLI, what lands in the archive, how assets are handled, and how to read the warnings an export prints. To load an export back into a dataset, see [Importing data](https://www.sanity.io/docs/content-lake/importing-data).

Prerequisites:

- Read access to the dataset you want to export.
- A signed-in CLI session, from `npx sanity@latest login`. Exporting programmatically needs a token instead.

## Export a dataset with the CLI

Run the export from your project directory:

**npm**

```shell
npx sanity@latest datasets export production production.tar.gz
```

**pnpm**

```shell
pnpm dlx sanity@latest datasets export production production.tar.gz
```

**yarn**

```shell
yarn dlx sanity@latest datasets export production production.tar.gz
```

**bun**

```shell
bunx sanity@latest datasets export production production.tar.gz
```

The first argument is the dataset name and the second is the output path. Leave them out and the CLI prompts for both. To export from a project other than the one configured locally, pass `--project-id`.

The flags that change what the export contains:

- `--no-assets`: Export only non-asset documents, and remove asset references from them.
- `--raw`: Export documents as stored, without rewriting asset references.
- `--no-drafts`: Export only published versions of documents.
- `--types`: Limit the export to a comma-separated list of document types.
- `--mode`: How documents are read, either `stream` (the default) or `cursor`.

For every flag, run `npx sanity@latest datasets export --help` or see the [Datasets CLI command reference](https://www.sanity.io/docs/cli-reference/cli-datasets).

## What the export archive contains

The export is a gzipped tarball. Everything sits under a single directory named for the dataset and the time of the export:

- `data.ndjson`: Every exported document, one JSON object per line.
- `assets.json`: A map of asset document IDs to the URLs they were downloaded from.
- `images/`: The downloaded image binaries.
- `files/`: The downloaded file binaries.

The `images/` and `files/` directories are always present, and are empty when the export skipped asset binaries. You can import the tarball as it is, or extract it and import `data.ndjson` on its own. See [Importing data](https://www.sanity.io/docs/content-lake/importing-data).

## How assets are exported

By default, the export downloads the binary for every asset document in the dataset. An asset document is any document of type `sanity.imageAsset` or `sanity.fileAsset`, and each one is queued for download whether or not another document references it. Assets linked from Media Library are included the same way, because linking creates an asset document in the dataset.

If a download returns HTTP 401, 403, or 404, the export prints `⚠ Asset failed with HTTP 404 (ignoring)` with the asset document ID, skips that asset, and continues. The export still completes.

No flag limits the download to referenced assets. The two flags that change asset handling skip binaries rather than filtering them:

- `--no-assets` skips the binaries, drops the asset documents, and strips asset references from the exported documents. The result isn't a complete copy of the dataset.
- `--raw` exports documents as stored, without rewriting asset references. Combine it with `--no-assets` to leave the binaries out but keep the references in place.

> [!NOTE]
> Linked library assets count toward export size
> Linked assets are bundled at full size, the same as assets uploaded directly to the dataset, so a dataset that gets most of its media from a library can still produce a multi-gigabyte export. See [Media Library limits and usage details](https://www.sanity.io/docs/media-library/limits-and-usage).

## Diagnose a 404 during export

A 404 during export is a warning, not a failure. It means an asset document in the dataset has no binary behind it.

The most common cause is a Media Library asset that was unlinked and later deleted. Deleting an asset from the library doesn't remove the asset document that linking created in your dataset. The library blocks deletion while a document still references the asset, so this affects assets that were linked and then went unused. The dataset keeps the asset document, its binary is gone, and the next export reports a 404 for it.

To confirm whether a library asset still exists, take the asset ID from the last segment of the document's `media._ref` and query the library for it:

**check-asset-exists.ts**

```typescript
const mediaLibraryId = 'MEDIA_LIBRARY_ID'
const assetId = 'ASSET_ID' // The last segment of media._ref
const token = process.env.SANITY_API_TOKEN

const query = encodeURIComponent(`*[_type == 'sanity.asset' && _id == '${assetId}']{_id}`)

await fetch(`https://api.sanity.io/v2025-02-19/media-libraries/${mediaLibraryId}/query?query=${query}`, {
  method: 'GET',
  headers: {
    'Authorization': `Bearer ${token}`
  }
})
```

An empty `result` array means the asset is no longer in the library, which is what produces the 404.

## Export a large dataset

Dataset exports are billed against your API quota. Documents are streamed to keep that cost down, and the `--mode` flag chooses how they're read:

- `stream` (the default) reads the whole dataset in one request. The result is consistent, but it can be slow on large datasets.
- `cursor` pages through the dataset. It's faster on large datasets and uses more requests, and it can miss changes if someone makes an edit while the export runs.

## Export programmatically

The CLI command wraps the [@sanity/export](https://github.com/sanity-io/export) package. Use the package directly when you need to filter or transform documents as they're exported, or to run exports from your own tooling.

**npm**

```shell
npm install @sanity/export @sanity/client
```

**pnpm**

```shell
pnpm add @sanity/export @sanity/client
```

**yarn**

```shell
yarn add @sanity/export @sanity/client
```

**bun**

```shell
bun add @sanity/export @sanity/client
```

**export-dataset.ts**

```typescript
import {createClient} from '@sanity/client'
import {exportDataset} from '@sanity/export'

const client = createClient({
  projectId: 'YOUR_PROJECT_ID',
  dataset: 'production',
  apiVersion: '2026-09-09',
  token: process.env.SANITY_API_TOKEN,
  useCdn: false,
})

const result = await exportDataset({
  client,
  dataset: 'production',
  outputPath: './production.tar.gz',
  onProgress: (progress) => console.log(progress.step),
})

console.log(`Exported ${result.documentCount} documents and ${result.assetCount} assets`)
```

The client must be created with a token, and `outputPath` is required. Pass `'-'` to write to stdout, or a writable stream to send the archive somewhere else. The same options the CLI exposes as flags are available here, including `assets`, `raw`, `drafts`, `types`, and `mode`.

To export a Media Library rather than a dataset, call `exportMediaLibrary` with a `mediaLibraryId` in place of `dataset`. Passing both throws.

> [!WARNING]
> Use the named export
> The package's default export is deprecated and will be removed in a future release. Import the named `exportDataset` function instead.

## Other ways to export

The Export API streams a dataset's documents as newline-delimited JSON over HTTP. It doesn't download asset binaries, so use it when you want document data alone. See the [Export API reference](https://www.sanity.io/docs/http-reference/export).

Backups are retained copies of a dataset that Sanity takes on a schedule, rather than a file you download on demand. Use them for recovery instead of migration. See [Backups](https://www.sanity.io/docs/content-lake/backups).

