How to create a folder in S3 (there are no folders)

TL;DR

Amazon S3 has no folders. It is a flat key-value store, and a “folder” is just a shared key prefix that ends in a slash. The AWS console's Create folder button writes a zero-byte object whose key ends in /, and the CLI does the same with aws s3api put-object --key reports/2026/. You usually don't need either: upload an object to reports/2026/q3.pdf and the folder appears on its own in the console, the CLI and S3 Viewer, which lists every bucket with Delimiter=/ so each shared prefix shows as a folder. Cloudflare R2 and every other S3-compatible store behave the same way.

Steps

Step-by-step.

  1. 01

    In S3 Viewer: upload into the path you want

    Open the bucket, then Upload → Upload folder and pick a directory, or drag a folder onto the listing. Every file is written under the current prefix plus its relative path, so reports/2026/q3.pdf creates the 2026/ folder as a side effect. There is no “New folder” button because an empty folder is not something S3 can hold; the folder exists the moment a key needs it, and S3 Viewer shows it right away.
  2. 02

    AWS console: Create folder

    In the bucket's Objects tab choose Create folder, type a name and confirm. The console writes a zero-byte object whose key is the folder name plus a trailing slash, for example reports/2026/. That placeholder is what keeps an empty folder visible.
  3. 03

    AWS CLI: put a zero-byte placeholder, or just copy a file into the path

    aws s3api put-object with a key ending in / is the exact equivalent of the console button. If the folder is about to receive files anyway, skip the placeholder and copy the first file to its full key. Note that aws s3 cp --recursive and aws s3 sync skip empty local directories, because there is nothing to upload.
    # an "empty folder": a 0-byte object whose key ends in /
    aws s3api put-object --bucket my-bucket --key reports/2026/
    
    # or let the first upload create the prefix
    aws s3 cp ./q3.pdf s3://my-bucket/reports/2026/q3.pdf
  4. 04

    SDK: PutObject with an empty body

    Any SDK can write the placeholder. The trailing slash is the whole trick; nothing else marks the object as a folder. In Python: s3.put_object(Bucket='my-bucket', Key='reports/2026/').
    await s3.putObject({
      Bucket: 'my-bucket',
      Key: 'reports/2026/', // trailing slash = folder placeholder
      Body: '',
    });
  5. 05

    Verify with a delimited listing

    aws s3 ls lists with Delimiter=/ and prints each shared prefix as PRE. This is the same ListObjectsV2 call S3 Viewer makes, which is why both show the same folders.
    aws s3 ls s3://my-bucket/reports/
    #                            PRE 2025/
    #                            PRE 2026/
    # 2026-09-05 10:12:44      12034 index.csv
  6. 06

    Know when a folder disappears

    Without a placeholder, deleting the last object under a prefix removes the folder from every listing, because nothing shares that prefix any more. With a placeholder the folder stays, and SDK listings show the reports/2026/ key itself as a 0-byte object. S3 Viewer hides that key inside the folder it represents so the view stays clean.
  7. 07

    Renaming or moving a folder means copying every key

    A folder is a prefix, so there is nothing to rename. Moving reports/2026/ to archive/2026/ means copying and deleting every object under it: aws s3 mv s3://my-bucket/reports/2026/ s3://my-bucket/archive/2026/ --recursive. The same copy-then-delete pattern applies to a single object.
Under the hood

What's actually happening.

S3 stores objects in a flat namespace. A key is an opaque string of up to 1,024 bytes, and the slash in reports/2026/q3.pdf means nothing to storage. It only matters to ListObjectsV2: pass Prefix=reports/ and Delimiter=/ and S3 rolls every key that continues past the next slash into a CommonPrefixes entry. Those entries are the folders you see. Keys that end at the current level come back in Contents as files.


The console's Create folder button exists because a listing can only show a prefix that at least one key shares. A zero-byte object named reports/2026/ is that key: it shares the prefix with nothing else, so the folder shows up empty. S3 Viewer lists with the same Prefix and Delimiter parameters, pages through results 1,000 keys at a time, and drops the placeholder key from the view when you are inside the folder it stands for, so you see a folder rather than a folder plus a 0-byte file.


Two practical consequences. Prefixes are also the unit S3 uses to scale request rates (thousands of requests per second per prefix), so spreading hot objects across prefixes is a real performance technique. And because a folder is only a prefix, IAM conditions such as s3:prefix are how you grant access to “a folder” rather than a bucket.

FAQ

Common questions.

Does Amazon S3 have folders?

No. S3 is a flat key-value store; every object lives in the bucket under a single key such as reports/2026/q3.pdf. Folders are a display convention: any tool that lists with Delimiter=/ groups keys by their shared prefix and shows each prefix as a folder. The AWS console, the AWS CLI and S3 Viewer all do this.

How do I create an empty folder in S3?

Write a zero-byte object whose key ends in a slash, for example reports/2026/. The console's Create folder button does exactly this, as does aws s3api put-object --bucket my-bucket --key reports/2026/. The placeholder keeps the folder visible even when it contains no other objects.

Why did my S3 folder disappear?

The folder had no placeholder object, and you deleted or moved the last object under its prefix. With nothing left to share the prefix, listings stop showing it. Create a zero-byte reports/2026/ object if you need the folder to survive being emptied.

How do I create a folder in S3 with the AWS CLI?

Run aws s3api put-object --bucket my-bucket --key reports/2026/ to create a placeholder, or copy a file to the path you want (aws s3 cp ./file.pdf s3://my-bucket/reports/2026/file.pdf) and the folder appears on its own. aws s3 mb creates buckets, not folders.

How do I create a folder in S3 with Python (boto3)?

Call s3.put_object(Bucket='my-bucket', Key='reports/2026/') with no Body. The trailing slash is what makes S3 tools treat the object as a folder. To create the folder implicitly, upload any object with that prefix, for example Key='reports/2026/q3.pdf'.

Does creating a folder in S3 cost anything?

One PUT request, billed at the standard request rate (about $0.005 per 1,000 in most regions), and a zero-byte object with no meaningful storage cost. Creating the folder implicitly by uploading a file costs nothing beyond the upload itself.

How do I create a folder in Cloudflare R2?

R2 implements the S3 API, so the same two approaches work: write a zero-byte object whose key ends in /, or upload an object into the path and let the prefix appear. In S3 Viewer, Upload folder works identically against an R2 bucket.

How deep can S3 folders go?

As deep as the key allows. An S3 key can be up to 1,024 bytes of UTF-8, and every slash inside it is just another character, so a/b/c/d/e/file.txt is one key with five folder levels. Very deep prefixes only affect how many ListObjectsV2 calls a browser needs to walk down.

How do I move files into a folder in S3?

Copy each object to its new key under the folder prefix and delete the original; S3 has no move or rename operation. aws s3 mv does both steps for you, and S3 Viewer's Rename action does the same for a single object, preserving metadata and tags.
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.