Skip to main content

AWS S3 Cheatsheet — 58+ Commands for Buckets, Sync, Versioning, Encryption & More

AWS S3 cheat sheet — 58+ commands covering buckets, sync, presign, versioning, lifecycle, encryption, CORS, and multipart.

  • Runs locally
  • Category Developer & DevOps
  • Best for Formatting, validating, shrinking, or inspecting code-adjacent text.
58 commands
Core Operations (6)
aws s3 ls

Without arguments: list all buckets you own. With a path: list objects or prefixes under that key prefix. Add --recursive to flatten the tree and --human-readable --summarize for a du-style summary.

Common pitfall: Output silently paginates at 1000 entries. Any count divisible by 1000 likely means there are more results. Use `list-objects-v2` with `--starting-token` for reliable pagination and exact counts.

Examples
aws s3 ls
aws s3 ls s3://my-bucket/
aws s3 ls s3://my-bucket/logs/ --recursive --human-readable --summarize
aws s3 cp

Copy a file between local disk and S3, or between two S3 paths. Add --recursive to copy an entire directory tree. Supports --include/--exclude glob filters and --storage-class to set the storage tier on upload.

Common pitfall: Without `--recursive`, `aws s3 cp ./dir s3://bucket/prefix/` silently copies nothing — it tries to copy a file named "dir" which does not exist. Always add `--recursive` for directories.

Examples
aws s3 cp ./report.pdf s3://my-bucket/reports/report.pdf
aws s3 cp s3://my-bucket/reports/report.pdf ./report.pdf
aws s3 cp ./dist/ s3://my-bucket/ --recursive --exclude "*.map"
aws s3 cp s3://src-bucket/data/ s3://dst-bucket/data/ --recursive
aws s3 mv

Move an object by copying it to the destination and deleting the source. Supports --recursive for directories. For cross-account or cross-region moves, data transfer costs apply.

Common pitfall: There is no native server-side rename in S3. `mv` always copies first, then deletes — if the copy fails mid-way the source is NOT deleted. For large objects, the copy can time out; use `copy-object` for fine-grained control.

Examples
aws s3 mv s3://my-bucket/old-name.txt s3://my-bucket/new-name.txt
aws s3 mv s3://src-bucket/archive/ s3://dst-bucket/archive/ --recursive
aws s3 rm

Delete one object from S3. Add --recursive to delete everything under a prefix. Without versioning, this is permanent and unrecoverable. Use --dryrun to preview what would be deleted.

Common pitfall: `aws s3 rm s3://bucket/ --recursive` (trailing slash with no further prefix) deletes EVERY object in the bucket. Always run `--dryrun` first on unfamiliar paths.

Examples
aws s3 rm s3://my-bucket/logs/2024-01-01.log
aws s3 rm s3://my-bucket/tmp/ --recursive --dryrun
aws s3 rm s3://my-bucket/tmp/ --recursive
aws s3 mb

Create (make) a new S3 bucket. The `--region` flag is required outside us-east-1 — omitting it creates the bucket in us-east-1 regardless of your default region.

Common pitfall: Bucket names are globally unique across ALL AWS accounts. Must be lowercase, 3-63 characters, no underscores. If the name is taken by any account anywhere you get BucketAlreadyExists.

Examples
aws s3 mb s3://my-unique-bucket-2024
aws s3 mb s3://my-bucket --region ap-east-1
aws s3 rb

Remove an empty bucket. Add `--force` to delete all current-version objects first, then remove the bucket. Cannot remove a versioned bucket if non-current versions or delete markers still exist.

Common pitfall: On a versioned bucket, `--force` only deletes current-version objects and delete markers. Previous (non-current) versions remain and the bucket deletion fails. Delete all non-current versions first with `list-object-versions` + `delete-object --version-id`.

Examples
aws s3 rb s3://empty-bucket
aws s3 rb s3://my-bucket --force
Sync (5)
aws s3 sync

Rsync-style incremental sync: only transfers files whose size or last-modified date differs. Works local→S3, S3→local, and S3→S3. Much faster than `cp --recursive` for large directories.

Common pitfall: sync compares size and last-modified, NOT content hash. A file edited to the same size may not be re-transferred unless the timestamp changes. Use `--exact-timestamps` or `--checksum-mode on` for byte-perfect sync.

Examples
aws s3 sync ./dist s3://my-website-bucket/
aws s3 sync s3://my-bucket/data/ ./local-copy/
aws s3 sync s3://source-bucket/ s3://dest-bucket/ --source-region us-east-1 --region ap-east-1
aws s3 sync --delete

Sync and delete destination files that no longer exist at the source — the equivalent of `rsync --delete`. Essential for static site deploys so stale files are removed.

Common pitfall: `aws s3 sync . s3://bucket/ --delete` FROM THE WRONG DIRECTORY silently wipes the entire bucket. Always pin source to a specific subfolder like `./dist` and do a `--dryrun` on the first deployment to each environment.

Examples
aws s3 sync ./dist s3://my-website/ --delete --dryrun
aws s3 sync ./dist s3://my-website/ --delete
aws s3 sync ./dist s3://my-website/ --delete --cache-control "max-age=31536000" --exclude "*.html"
aws s3 sync --dryrun

Preview sync changes without transferring any data. Lists every upload, update, and delete that would occur. Run before any sync with `--delete` to verify the source path is correct.

Examples
aws s3 sync ./dist s3://my-bucket/ --delete --dryrun
aws s3 sync s3://prod-bucket/ s3://backup-bucket/ --dryrun
aws s3 sync --include / --exclude

Filter which files are synced using glob patterns. Filters apply in order; later rules override earlier ones. `--exclude "*" --include "*.js"` syncs only .js files.

Common pitfall: By default ALL files are included. `--include "*.css"` does NOT exclude everything else — you must `--exclude "*"` first. Order matters: `--exclude "*.log" --include "error.log"` includes error.log despite the exclusion.

Examples
aws s3 sync ./dist s3://bucket/ --exclude "*.map" --exclude "*.ts"
aws s3 sync ./dist s3://bucket/ --exclude "*" --include "*.html" --include "*.css" --include "*.js"
aws s3 sync --storage-class

Set the storage class for uploaded objects during sync. Options: STANDARD, INTELLIGENT_TIERING, STANDARD_IA, ONEZONE_IA, GLACIER_INSTANT_RETRIEVAL, GLACIER_FLEXIBLE_RETRIEVAL, DEEP_ARCHIVE.

Common pitfall: STANDARD_IA and ONEZONE_IA charge a 128 KB minimum object size and 30-day minimum storage duration. Small or short-lived objects cost MORE on IA than Standard. Use INTELLIGENT_TIERING for unknown access patterns.

Examples
aws s3 sync ./backups/ s3://my-bucket/backups/ --storage-class GLACIER_INSTANT_RETRIEVAL
aws s3 sync ./logs/ s3://my-bucket/logs/ --storage-class INTELLIGENT_TIERING
Pre-signed URLs (2)
aws s3 presign

Generate a time-limited, pre-signed GET URL for a private S3 object. Anyone with the URL can download the object without AWS credentials. Default expiry: 3600 seconds (1 hour).

Common pitfall: The URL inherits the signing identity — if the signer is an IAM role revoked before expiry, the presigned URL immediately stops working. Signatures are validated against current IAM state on every request.

Examples
aws s3 presign s3://my-bucket/invoice.pdf
aws s3 presign s3://my-bucket/invoice.pdf --expires-in 86400
aws s3 presign s3://my-bucket/report.csv --profile prod --expires-in 3600
aws s3api create-presigned-post

Generate a presigned HTTP POST form (URL + fields map) that lets a browser or third party upload directly to S3 without a server proxy. Supports content-type policies and size limits — more secure than presigned PUT for browser uploads.

Common pitfall: The returned `fields` map must be included as form fields BEFORE the file in multipart/form-data. If any required field is missing or Content-Type mismatches the policy, S3 returns 403 with a confusing XML error body.

Examples
aws s3api create-presigned-post --bucket my-bucket --key uploads/avatar.jpg --conditions '[{"Content-Type": "image/jpeg"}]' --expires-in 300
Static Website (3)
aws s3 website

Enable static website hosting on a bucket with index and error documents. The bucket gets an HTTP endpoint (not HTTPS — put CloudFront in front for TLS).

Common pitfall: Website hosting requires objects to be publicly readable. Block Public Access must be OFF and a bucket policy granting s3:GetObject to Principal "*" is needed. Forgetting this gives 403 on every page load.

Examples
aws s3 website s3://my-bucket --index-document index.html --error-document error.html
aws s3api put-bucket-website

Configure static website hosting with full control over routing rules — redirect prefixes, conditional redirects (by HTTP error code), and custom protocols.

Examples
aws s3api put-bucket-website --bucket my-bucket --website-configuration file://website.json
aws s3api get-bucket-website

Retrieve the current static website configuration for a bucket, including index/error documents and any routing rules.

Examples
aws s3api get-bucket-website --bucket my-bucket
Policies & ACLs (6)
aws s3api get-bucket-policy

Retrieve the JSON bucket policy. Useful for auditing who can access the bucket from which account, VPC endpoint, or IP range.

Common pitfall: A bucket with NO policy uses only IAM identity policies. A bucket with an explicit `Deny *` policy locks out everyone including root. Test the policy JSON with the IAM Policy Simulator before applying.

Examples
aws s3api get-bucket-policy --bucket my-bucket
aws s3api get-bucket-policy --bucket my-bucket --output text | python3 -m json.tool
aws s3api put-bucket-policy

Apply a new JSON bucket policy, replacing any existing one. Commonly used to allow cross-account access, enforce TLS-only (deny HTTP), or restrict access to a specific VPC endpoint.

Common pitfall: Accidentally setting a `Deny *` policy locks YOU out of your own bucket — because S3 explicit denials override identity policies. Always test the policy before applying with `--expected-bucket-owner` to scope the call.

Examples
aws s3api put-bucket-policy --bucket my-bucket --policy file://bucket-policy.json
aws s3api delete-bucket-policy

Remove the entire bucket policy. Access then falls back to IAM identity policies only.

Examples
aws s3api delete-bucket-policy --bucket my-bucket
aws s3api put-public-access-block

Enable the four public-access-block settings at the bucket level: BlockPublicAcls, IgnorePublicAcls, BlockPublicPolicy, RestrictPublicBuckets. Set all four to true to make a bucket completely private.

Common pitfall: These settings also exist at the ACCOUNT level. Account-level Block Public Access overrides bucket-level. When troubleshooting public access, check both levels: bucket setting AND the account-level `aws s3control get-public-access-block`.

Examples
aws s3api put-public-access-block --bucket my-bucket --public-access-block-configuration BlockPublicAcls=true,IgnorePublicAcls=true,BlockPublicPolicy=true,RestrictPublicBuckets=true
aws s3api get-public-access-block --bucket my-bucket
aws s3api get-public-access-block

Check the current public access block configuration for a bucket.

Examples
aws s3api get-public-access-block --bucket my-bucket
aws s3api get-bucket-acl

Read the legacy ACL for a bucket. Modern S3 recommends disabling ACLs entirely (Object Ownership = Bucket owner enforced) and using bucket policies instead.

Common pitfall: Since April 2023, new buckets have ACLs disabled by default. Passing `--acl public-read` returns `AccessControlListNotSupported`. Migrate to bucket policies for public access control.

Examples
aws s3api get-bucket-acl --bucket my-bucket
aws s3api put-bucket-ownership-controls --bucket my-bucket --ownership-controls Rules=[{ObjectOwnership=BucketOwnerEnforced}]
Versioning (5)
aws s3api put-bucket-versioning

Enable object versioning on a bucket. Every upload creates a new version; deletes create a delete marker (object is recoverable). Versioning cannot be disabled — only suspended.

Common pitfall: Versioning increases storage costs: every version of every object is billed. Add a lifecycle rule to expire non-current versions after N days to avoid runaway storage costs on frequently updated files.

Examples
aws s3api put-bucket-versioning --bucket my-bucket --versioning-configuration Status=Enabled
aws s3api put-bucket-versioning --bucket my-bucket --versioning-configuration Status=Suspended
aws s3api get-bucket-versioning

Check whether versioning is Enabled, Suspended, or never-configured (empty response) on a bucket.

Examples
aws s3api get-bucket-versioning --bucket my-bucket
aws s3api list-object-versions

List all versions and delete markers of every object in a bucket. Output can be very large on heavily versioned buckets — always use --prefix to scope the query.

Examples
aws s3api list-object-versions --bucket my-bucket --prefix logs/
aws s3api list-object-versions --bucket my-bucket --query "Versions[?Key=='config.json']"
aws s3api delete-object --version-id

Permanently delete a specific version of an object. Without --version-id, delete on a versioned bucket only adds a delete marker (soft delete). Get the version ID from `list-object-versions`.

Common pitfall: Deleting a delete marker (the "tombstone") restores the previous version as the current object. Always verify in `list-object-versions` output whether you are deleting a regular version or a delete marker.

Examples
aws s3api delete-object --bucket my-bucket --key config.json --version-id "3HL4kqtJvjVBH40Nrjfkd"
aws s3api get-object --version-id

Download a specific historical version of an object by version ID. Useful to recover an accidental overwrite or inspect what changed between versions.

Examples
aws s3api get-object --bucket my-bucket --key config.json --version-id "3HL4kqtJvjVBH40Nrjfkd" ./recovered-config.json
Lifecycle (3)
aws s3api put-bucket-lifecycle-configuration

Define lifecycle rules: transition objects to cheaper storage classes after N days, expire (delete) current versions, clean up non-current versions and delete markers, or abort incomplete multipart uploads.

Common pitfall: Lifecycle rules act on OBJECT CREATION DATE, not last-access date. A file uploaded once and never read will still be transitioned/expired on schedule. Lifecycle transitions are billed as data operations.

Examples
aws s3api put-bucket-lifecycle-configuration --bucket my-bucket --lifecycle-configuration file://lifecycle.json
aws s3api get-bucket-lifecycle-configuration

Retrieve all lifecycle rules currently configured for a bucket.

Examples
aws s3api get-bucket-lifecycle-configuration --bucket my-bucket
aws s3api delete-bucket-lifecycle

Remove all lifecycle rules from a bucket. Objects already being processed by an in-flight rule continue until the transition or expiration completes.

Examples
aws s3api delete-bucket-lifecycle --bucket my-bucket
Encryption (5)
aws s3api put-bucket-encryption

Enable default server-side encryption for all new objects uploaded to the bucket. SSE-S3 (AES-256) is free; SSE-KMS uses a customer-managed key and charges per API call.

Common pitfall: Default encryption does NOT retroactively encrypt existing objects. Run S3 Batch Operations or re-upload existing objects if you need them encrypted too.

Examples
aws s3api put-bucket-encryption --bucket my-bucket --server-side-encryption-configuration '{"Rules": [{"ApplyServerSideEncryptionByDefault": {"SSEAlgorithm": "AES256"}}]}'
aws s3api put-bucket-encryption --bucket my-bucket --server-side-encryption-configuration '{"Rules": [{"ApplyServerSideEncryptionByDefault": {"SSEAlgorithm": "aws:kms", "KMSMasterKeyID": "arn:aws:kms:us-east-1:123456789012:key/abc-123"}, "BucketKeyEnabled": true}]}'
aws s3api get-bucket-encryption

Check the current default encryption configuration for a bucket — which algorithm and KMS key are used.

Examples
aws s3api get-bucket-encryption --bucket my-bucket
aws s3 cp --sse aws:kms

Upload with SSE-KMS encryption using the default KMS key. Use `--sse-kms-key-id` to specify a customer-managed key ARN for more control.

Common pitfall: Cross-account downloads of KMS-encrypted objects require the downloader to have kms:Decrypt permission AND the KMS key policy must allow the other account. Without both, you get Access Denied that looks like an S3 policy issue.

Examples
aws s3 cp ./secrets.json s3://my-bucket/secrets.json --sse aws:kms
aws s3 cp ./secrets.json s3://my-bucket/secrets.json --sse aws:kms --sse-kms-key-id arn:aws:kms:us-east-1:123456789012:key/abc-123
aws s3 cp --sse AES256

Upload with SSE-S3 (AES-256) encryption — the simplest option. AWS manages the keys at no extra cost. Anyone with s3:GetObject permission can read without additional KMS permissions.

Examples
aws s3 cp ./data.csv s3://my-bucket/data.csv --sse AES256
aws s3api delete-bucket-encryption

Remove the default encryption policy from a bucket. New objects uploaded after this will not be encrypted by default; existing objects keep their encryption.

Examples
aws s3api delete-bucket-encryption --bucket my-bucket
CORS (3)
aws s3api get-bucket-cors

Retrieve the CORS configuration for a bucket — the list of allowed origins, methods, and headers for cross-origin browser requests.

Common pitfall: CORS is a browser-only security mechanism. SDK calls and server-to-server requests are never blocked by CORS. If your web app gets CORS errors but your server can access the file, the CORS configuration is missing or wrong.

Examples
aws s3api get-bucket-cors --bucket my-bucket
aws s3api put-bucket-cors

Set CORS rules from a JSON file. Typically allow GET/HEAD for the static website origin and PUT/POST for your presigned upload origin.

Examples
aws s3api put-bucket-cors --bucket my-bucket --cors-configuration file://cors.json
aws s3api delete-bucket-cors

Remove all CORS rules from a bucket. After removal, all cross-origin browser requests to the bucket will fail with a CORS error.

Examples
aws s3api delete-bucket-cors --bucket my-bucket
Low-level S3 API (10)
aws s3api head-object

Fetch object metadata (Content-Type, Content-Length, ETag, Last-Modified, custom metadata) without downloading the body. The cheapest way to check if an object exists and what size it is.

Common pitfall: 403 means the object exists but you lack read access; 404 means the object does not exist. The CLI error message is the same "Not Found" for both — you cannot tell them apart without checking the HTTP status code.

Examples
aws s3api head-object --bucket my-bucket --key reports/annual.pdf
aws s3api head-object --bucket my-bucket --key image.png --expected-bucket-owner 123456789012
aws s3api head-bucket

Check if a bucket exists and you have access to it. Returns 200 (exists + access), 403 (exists, no access), or 404 (does not exist). Useful for health checks and pre-flight validation.

Examples
aws s3api head-bucket --bucket my-bucket
aws s3api head-bucket --bucket my-bucket --expected-bucket-owner 123456789012
aws s3api get-object

Download an object with fine-grained control: byte-range requests, conditional GETs (If-Match, If-Modified-Since), server-side checksum validation, and response header overrides.

Examples
aws s3api get-object --bucket my-bucket --key large.bin --range "bytes=0-99" /tmp/chunk.bin
aws s3api get-object --bucket my-bucket --key config.json --if-modified-since "2024-01-01" ./config.json
aws s3api put-object

Upload an object with custom metadata, content-type, tags, storage class, and server-side encryption in one atomic call. Use when `aws s3 cp` does not offer enough control.

Common pitfall: Single PUT is limited to 5 GB. For larger objects use multipart upload. The high-level `aws s3 cp` and `aws s3 sync` auto-switch to multipart above 8 MB by default; `s3api put-object` does not.

Examples
aws s3api put-object --bucket my-bucket --key data.csv --body ./data.csv --content-type "text/csv" --metadata Author=alice,Project=analytics
aws s3api put-object --bucket my-bucket --key archive.tar.gz --body ./archive.tar.gz --storage-class GLACIER_INSTANT_RETRIEVAL
aws s3api copy-object

Server-side copy of an object up to 5 GB — no data transfer cost within the same region. Use for renaming, changing storage class, re-encrypting with a new KMS key, or updating metadata without re-uploading the body.

Common pitfall: For objects > 5 GB, `copy-object` fails. Use `aws s3 cp s3:// s3://` which automatically uses multipart copy. For re-encrypting large objects at scale, use S3 Batch Operations.

Examples
aws s3api copy-object --copy-source my-bucket/old-name.txt --bucket my-bucket --key new-name.txt
aws s3api copy-object --copy-source src-bucket/data.json --bucket dst-bucket --key data.json --storage-class STANDARD_IA
aws s3api copy-object --copy-source my-bucket/file.txt --bucket my-bucket --key file.txt --server-side-encryption aws:kms --ssekms-key-id new-key-arn --metadata-directive COPY
aws s3api list-objects-v2

Paginated list of objects with full metadata, filtering by prefix and delimiter. Use v2 over v1 (list-objects) — v2 uses continuation tokens instead of markers and is more efficient.

Common pitfall: Default max-keys is 1000. If the response has `NextContinuationToken`, there are more results. Loop using `--starting-token` with that value until no continuation token is returned.

Examples
aws s3api list-objects-v2 --bucket my-bucket --prefix logs/ --max-keys 100
aws s3api list-objects-v2 --bucket my-bucket --delimiter "/" --query "CommonPrefixes[].Prefix"
aws s3api list-objects-v2 --bucket my-bucket --prefix reports/ --query "Contents[].{Key: Key, Size: Size}"
aws s3api get-bucket-location

Get the AWS region where a bucket resides. Essential when you get "301 redirect" or "PermanentRedirect" errors — the bucket exists but you are hitting the wrong regional endpoint.

Common pitfall: Buckets in us-east-1 return an EMPTY LocationConstraint (null), not the string "us-east-1". Treat a null result as "us-east-1" in your automation scripts.

Examples
aws s3api get-bucket-location --bucket my-bucket
REGION=$(aws s3api get-bucket-location --bucket my-bucket --query "LocationConstraint" --output text); REGION=${REGION:-us-east-1}
aws s3api put-bucket-tagging

Apply cost-allocation tags to a bucket. These are bucket-level tags, separate from object-level tags. Use them to track S3 costs per project, team, or environment in Cost Explorer.

Common pitfall: Bucket tags are completely separate from object tags. Setting a bucket tag does NOT tag the objects inside it. Tag objects individually at upload time or use S3 Batch Operations for existing objects.

Examples
aws s3api put-bucket-tagging --bucket my-bucket --tagging '{"TagSet": [{"Key": "env", "Value": "prod"}, {"Key": "team", "Value": "backend"}]}'
aws s3api get-bucket-tagging --bucket my-bucket
aws s3api create-multipart-upload

Initiate a multipart upload and return an UploadId. You then upload parts (each ≥ 5 MB except the last), then call complete-multipart-upload to assemble them. Required for objects > 5 GB.

Common pitfall: Incomplete multipart uploads (started but never completed or aborted) accumulate in your bucket and cost money. Always set a lifecycle rule to abort incomplete multipart uploads after N days.

Examples
aws s3api create-multipart-upload --bucket my-bucket --key large-file.tar.gz
aws s3api list-multipart-uploads --bucket my-bucket
aws s3api abort-multipart-upload --bucket my-bucket --key large-file.tar.gz --upload-id <UploadId>
aws s3api restore-object

Initiate a temporary restoration of an object archived in GLACIER_FLEXIBLE_RETRIEVAL or DEEP_ARCHIVE. After the restore completes (hours to days depending on tier), the object becomes readable for a specified number of days.

Common pitfall: Restoring does not change the storage class — you are paying for both Glacier storage AND the standard tier copy during the restoration window. The EXPEDITED tier costs ~10× more than STANDARD but restores in 1-5 minutes instead of 3-5 hours.

Examples
aws s3api restore-object --bucket my-bucket --key archive/2023.tar.gz --restore-request Days=7,GlacierJobParameters={Tier=Standard}
aws s3api restore-object --bucket my-bucket --key archive/urgent.tar.gz --restore-request Days=1,GlacierJobParameters={Tier=Expedited}
Common Pitfalls (10)
sync . --delete from the wrong directory

`aws s3 sync . s3://bucket/ --delete` is the most destructive S3 mistake: run from the wrong directory and you sync whatever is there while deleting everything else in the bucket.

Common pitfall: Mitigation: always pin the source to a named build folder (./dist, ./build, ./out), run --dryrun before every first deployment, and restrict bucket write access via a bucket policy scoped to your CI IAM principal.

Examples
aws s3 sync ./dist s3://my-site/ --delete --dryrun
aws s3 sync ./dist s3://my-site/ --delete
single PUT is limited to 5 GB

A single `put-object` call for a file larger than 5 GB fails with EntityTooLarge. The high-level `aws s3 cp` auto-switches to multipart above 8 MB by default; `s3api put-object` does not.

Common pitfall: Maximum single-part size: 5 GB. Maximum object size: 5 TB (requires multipart). Each multipart part must be ≥ 5 MB (except the last). Incomplete uploads accumulate charges — set a lifecycle rule to abort them after N days.

Examples
aws s3 cp ./huge-backup.tar.gz s3://my-bucket/ --multipart-chunksize 100MB
list paginates silently at 1000 keys

`aws s3 ls` returns at most 1000 entries without pagination warnings. `list-objects-v2` also defaults to 1000 keys. If the result has `NextContinuationToken`, there are more objects.

Examples
aws s3 ls s3://my-bucket/ --recursive | wc -l
aws s3api list-objects-v2 --bucket my-bucket --query "length(Contents)"
--acl is ignored when Object Ownership is enforced

Since April 2023, new buckets default to "Bucket owner enforced" Object Ownership, which DISABLES ACLs. Passing `--acl public-read` returns `AccessControlListNotSupported`. Use a bucket policy for public access instead.

Examples
aws s3api get-bucket-ownership-controls --bucket my-bucket
aws s3api put-bucket-ownership-controls --bucket my-bucket --ownership-controls Rules=[{ObjectOwnership=BucketOwnerPreferred}]
cross-account access requires two grants

A cross-account read needs BOTH: (1) the source bucket policy grants s3:GetObject to the target role/account, AND (2) the target account IAM policy grants s3:GetObject on that bucket ARN. One grant alone gives AccessDenied.

Common pitfall: KMS-encrypted objects add a third layer: the KMS key policy must also allow the target account to use the key for decryption. Check all three: bucket policy, identity policy, KMS key policy.

Examples
aws s3api get-bucket-policy --bucket src-bucket
aws s3api get-bucket-encryption --bucket src-bucket
cross-region data transfer is billed

Copying objects between S3 buckets in different regions incurs data transfer costs (~$0.02/GB). Within the same region, S3-to-S3 transfer is free. Same-region EC2→S3 is also free; cross-region costs money.

Examples
aws s3 cp s3://us-bucket/data s3://eu-bucket/data --recursive --source-region us-east-1 --region eu-west-1
get-bucket-location returns null for us-east-1

`get-bucket-location` returns an EMPTY `LocationConstraint` for buckets in us-east-1 — not the string "us-east-1". Always normalize null to "us-east-1" in scripts.

Examples
aws s3api get-bucket-location --bucket my-bucket
REGION=$(aws s3api get-bucket-location --bucket my-bucket --query "LocationConstraint" --output text); REGION=${REGION:-us-east-1}
bucket names are globally unique and lowercase

S3 bucket names must be globally unique across ALL AWS accounts, not just yours. Lowercase only, 3-63 characters, no underscores, no uppercase. If any account has claimed the name, you get BucketAlreadyExists.

Examples
aws s3 mb s3://mycompany-prod-data-2024
versioning cannot be fully disabled once enabled

Once you enable versioning you can only SUSPEND it — not turn it off. Suspended versioning preserves all existing versions; new uploads go to a null version ID. All historical versions continue accumulating storage costs until explicitly deleted.

Examples
aws s3api put-bucket-versioning --bucket my-bucket --versioning-configuration Status=Suspended
aws s3api list-object-versions --bucket my-bucket --query "Versions[].{Key:Key,VersionId:VersionId}"
incomplete multipart uploads accumulate charges

Every `create-multipart-upload` that is never completed or aborted leaves orphaned parts billed at standard storage rates. They do NOT appear in `aws s3 ls`. Use `list-multipart-uploads` to find them.

Common pitfall: Best practice: always add an AbortIncompleteMultipartUpload lifecycle rule after 7 days to any bucket that uses the multipart API. This is a free protection against silent storage cost accumulation.

Examples
aws s3api list-multipart-uploads --bucket my-bucket
aws s3api abort-multipart-upload --bucket my-bucket --key file.gz --upload-id <UploadId>

What this tool does

Searchable AWS S3 cheat sheet with 58+ real-world commands spanning eleven topic areas — the exact commands cloud engineers, SREs, and backend developers actually run daily, not the exhaustive AWS API reference. Eleven sections cover everything you need: Core Operations (aws s3 ls / cp / mv / rm / mb / rb), Sync (sync, --delete, --dryrun, --include/--exclude, --storage-class), Pre-signed URLs (aws s3 presign with custom expiry, s3api create-presigned-post for browser uploads), Static Website Hosting (aws s3 website, routing rules), Policies & ACLs (bucket policy, public-access-block, ACL migration to bucket owner enforced), Versioning (enable/suspend, list-object-versions, recover a specific version, delete a delete marker), Lifecycle Rules (transition to cheaper storage, expire non-current versions, abort incomplete multipart), Encryption (SSE-S3, SSE-KMS with S3 Bucket Key, per-object upload flags), CORS (get/put/ delete rules with browser-vs-SDK explanation), Low-level S3 API (head-object, head-bucket, get-object ranges, put-object with metadata, server-side copy-object, list-objects-v2 pagination, restore-object from Glacier, multipart lifecycle), and a Pitfalls section covering the ten mistakes that actually waste your afternoon: the deadly sync without a subfolder, 5 GB single-PUT limit, silent list pagination at 1000 keys, Object Ownership breaking --acl, cross-account needing two grants, cross-region egress costs, null LocationConstraint for us-east-1, globally-unique bucket naming rules, versioning-cannot-be- disabled surprise, and orphaned multipart parts accumulating charges. Every command has full syntax, bilingual EN/ZH explanation, real-world pitfall, and 1-3 copy-ready examples with realistic bucket names, version IDs, and ARNs. Search across command, description, pitfall, and example in real time. Filter by section with one click. 100% client-side — no AWS credentials, no API calls.

Tool details

Input
Files + Text
The page exposes text boxes, numeric controls, file pickers, or structured inputs depending on the tool.
Output
Live result + Copy + Preview
The result area focuses on usable output, with copy, download, or preview actions when supported.
Privacy
Browser-side processing
The main tool logic does not call an external API, so inputs normally stay in the current tab.
Save / share
Shareable URL state
Key settings are encoded in the URL so another person can reopen the same setup.
Performance budget
Initial JS <= 28 KB
No WASM budget is declared, keeping the tool quick to open on mobile.
Best fit
Developer & DevOps · Developer
Category and role tags drive related tools, internal links, and quick fit checks.

How to use

  1. 1. Input

    Paste or drop your content into the tool panel.

  2. 2. Process

    Click the button. All processing is local in your browser.

  3. 3. Copy / Download

    Copy the result or download to disk in one click.

How AWS S3 Cheatsheet fits into your work

Use it in the small gaps between coding, reviewing, debugging, and shipping.

Developer jobs

  • Formatting, validating, shrinking, or inspecting code-adjacent text.
  • Preparing snippets for documentation, tickets, commits, or handoff.
  • Checking a small payload quickly without switching tools.

Developer checks

  • Run irreversible transforms like minify or obfuscate on a copy.
  • Keep secrets out of pasted snippets unless the tool explicitly stays local.
  • Use your normal tests or linter before shipping transformed code.

Good next steps

These links move the current task into a more complete workflow.

  1. 1 AWS CLI Cheatsheet AWS CLI cheat sheet — 80+ commands for EC2 / S3 / IAM / Lambda / RDS / EKS / CloudFormation with real examples. Open
  2. 2 AWS IAM Cheatsheet Search AWS IAM policy fields, ARNs, conditions, managed policies, trust rules, and inspect policy JSON locally. Open
  3. 3 kubectl Cheatsheet kubectl cheat sheet — 100+ Kubernetes commands with real examples, common pitfalls, and YAML snippets. Open

Real-world use cases

  • Deploy a static Next.js site to S3 without nuking the bucket

    You export a Next.js app to ./out and need to push it to S3 on every main branch push. The sheet hands you `aws s3 sync ./out s3://acme-www/ --delete --cache-control "max-age=31536000" --exclude "*.html"` plus the --dryrun tip so the first run confirms the source folder is ./out, not the repo root. The sync --delete pitfall card stops you from the forgotten-subfolder disaster that wipes the whole bucket.

  • Recover a config file overwritten by an accidental CI push

    A misconfigured CI job re-uploaded config.json with wrong environment variables. Because versioning was enabled on the bucket, you run `aws s3api list-object-versions --bucket acme-prod --key config.json` to find the last good VersionId, then `aws s3api copy-object --copy-source acme-prod/config.json?versionId=<id> --bucket acme-prod --key config.json` to restore it. No backup needed — versioning provides a built-in point-in-time record.

  • Share a private S3 report with a client for 24 hours

    A PDF invoice in a private bucket needs to be accessible to a client without creating an IAM user. You copy `aws s3 presign s3://acme-invoices/2024-Q4.pdf --expires-in 86400 --profile prod`, paste the URL in an email. After 86400 seconds the URL stops working and no AWS credentials were shared. The presign pitfall card warns you about what happens if the signing IAM role gets revoked mid-TTL.

  • Audit and fix an S3 bucket left publicly readable from a legacy deploy

    Security scan flags an S3 bucket with public read enabled via ACL. You check `aws s3api get-bucket-acl --bucket legacy-bucket`, confirm the ACL grants public-read, then check `aws s3api get-bucket-ownership-controls` to see Object Ownership. You update the bucket to BucketOwnerEnforced (disabling ACLs), then use a bucket policy with condition `aws:SecureTransport: true` to enforce HTTPS and restrict access to your VPC endpoint only.

Common pitfalls

  • Running `aws s3 sync . s3://bucket/ --delete` without specifying a subfolder like `./dist`. This syncs whatever files happen to be in your current directory and deletes everything else in the bucket. Always pin the source.

  • Using `--acl public-read` on buckets created after April 2023. New buckets have ACLs disabled by default (BucketOwnerEnforced). Use a bucket policy with Principal=* and s3:GetObject instead.

  • Not enabling versioning before storing production data. S3 has no "recycle bin" — an overwrite is permanent unless you have versioning or cross-region replication as a safety net.

Privacy

This cheat sheet is a single static page. Search runs entirely in your browser against an in-memory array of S3 commands. No AWS SDK is loaded, no credentials are prompted, and no API calls are made. Open DevTools → Network while you type — zero requests. Your input never leaves the browser.

FAQ

Tool combos

Folks in your role tend to reach for these alongside this tool.

Made by Toolora · 100% client-side · Updated 2026-06-13