How to bulk-delete S3 files

TL;DR

Select the files in S3 Viewer and confirm Delete — this works on AWS S3, R2, B2, MinIO, and other S3-compatible endpoints. Each file must still match the one you reviewed; changed files and uncertain results require fresh review. On versioned AWS buckets, ordinary deletion adds delete markers and keeps prior versions. Unversioned deletion can be permanent.

Steps

Step-by-step.

  1. 01

    In S3 Viewer: tick the checkboxes, then Delete

    Each row in the file list has a checkbox. The Delete button in the toolbar is disabled until you tick something, then shows the count — Delete (12). S3 Viewer sends batches of up to 1,000 keys, checking each file against the one you reviewed, on every connected provider. If some keys fail, the result tells you which. Confirmed failures remain available for retry; uncertain results require refresh and review and are never automatically replayed.
  2. 02

    AWS CLI: delete a whole prefix

    The CLI lists every key under the prefix and deletes them in batches of 1,000 under the hood.
    aws s3 rm s3://my-bucket/old-logs/ --recursive
  3. 03

    AWS CLI: delete from a key list

    For non-contiguous keys, build a JSON delete request and pass it to aws s3api delete-objects.
    aws s3api delete-objects \
      --bucket my-bucket \
      --delete '{"Objects":[{"Key":"a.log"},{"Key":"b.log"}]}'
  4. 04

    AWS SDK: DeleteObjectsCommand

    For programmatic bulk delete, use DeleteObjectsCommand in batches of up to 1,000. The response includes any per-key errors, so you can retry failures without re-running the whole batch.
    const result = await s3.send(
      new DeleteObjectsCommand({
        Bucket: 'my-bucket',
        Delete: {
          Objects: keys.map((Key) => ({ Key })),
          Quiet: false,
        },
      }),
    );
  5. 05

    If versioning is on: also delete the versions

    On a versioned bucket, a normal delete just adds a delete marker. To actually purge, list every version and delete each one explicitly with its VersionId. S3 Viewer does not purge specific versions. On unversioned buckets, deletion can be permanent.
    aws s3api list-object-versions \
      --bucket my-bucket --prefix old-logs/ \
      --query 'Versions[].{Key:Key,VersionId:VersionId}' \
      > versions.json
  6. 06

    Lifecycle rules for ongoing cleanup

    For predictable cleanup (e.g., delete logs older than 30 days), use S3 Lifecycle rules instead of running deletes yourself. Cheap, automatic, and survives you forgetting.

Under the hood

What's actually happening.

S3's DeleteObjects API takes up to 1,000 keys per request and returns a per-key result list — successes and failures together. For larger deletes you batch by 1,000 and reissue any failed keys. The AWS CLI's rm --recursive handles the listing and batching for you under the hood. S3 Viewer supports checkbox multi-select and folder deletion on AWS S3, checking each object against its reviewed identity. Missing identities, changes, and uncertain results require fresh review. Other providers stop before deleting objects. On versioned AWS buckets, every “delete” is really a soft delete (it writes a delete marker); to actually purge, you have to enumerate versions and delete each one with its VersionId, which S3 Viewer does not do. For predictable cleanup, lifecycle rules are the right long-term tool.

FAQ

Common questions.

How do I bulk-delete files from S3?

Select files in S3 Viewer and confirm Delete, on any connected provider. The app checks each reviewed file and reports changes or failures. From the AWS CLI, aws s3 rm s3://bucket/prefix --recursive deletes a prefix; programmatic bulk deletion uses DeleteObjects in batches of up to 1,000.

How many objects can I delete in one S3 API call?

Up to 1,000 per DeleteObjects request. For more, batch them — most SDKs and tools handle the batching for you. S3 Viewer batches automatically; the AWS CLI's rm --recursive does too.

How do I delete all files in an S3 bucket prefix?

From the CLI: aws s3 rm s3://bucket/prefix/ --recursive lists every key under the prefix and deletes them in 1,000-key batches. From S3 Viewer: open the ⋮ menu on the folder's row and choose Delete folder — it deletes everything under that prefix recursively, paging through the listing. Programmatically: list with ListObjectsV2 and call DeleteObjects.

Why didn't my bulk delete remove my files?

Almost always versioning. On a versioned bucket, DeleteObjects writes a delete marker per key — the prior versions are still there (and still billed). Use ListObjectVersions to enumerate every version and DeleteObject with --version-id to fully purge.

Can I undo a bulk delete in S3?

Only if versioning was enabled when you deleted. Remove the delete markers (or restore the prior versions) to bring objects back. Without versioning, bulk deletes are permanent — there is no recycle bin.

Does Cloudflare R2 support bulk delete?

Yes. S3 Viewer supports single, bulk, and folder deletion on R2. R2's plain DeleteObject has no delete-time condition, so S3 Viewer checks each object is still the one reviewed with a HEAD request immediately before deleting it, rather than relying on R2 to enforce the condition the way AWS S3 does.

Use S3 Viewer for this

Skip the CLI. Try it in the browser.

S3 Viewer turns the steps above into a single click. Open source, self-hostable, free.