S3
Amazon Simple Storage Service for storing and retrieving any amount of data from anywhere.
Protocol: RestXmlSigning name: s3Persistent: Yes (metadata only — object data is not persisted across restarts)
Quick Start
Create a bucket, upload a file, and download it:
bash
# Create a bucket
curl -s -X PUT http://localhost:4566/my-bucket \
-H "Authorization: AWS4-HMAC-SHA256 Credential=test/20260421/us-east-1/s3/aws4_request, SignedHeaders=host, Signature=fake"
# Upload an object
curl -s -X PUT http://localhost:4566/my-bucket/hello.txt \
-H "Content-Type: text/plain" \
-H "Authorization: AWS4-HMAC-SHA256 Credential=test/20260421/us-east-1/s3/aws4_request, SignedHeaders=host, Signature=fake" \
-d "Hello, World!"
# Download the object
curl -s http://localhost:4566/my-bucket/hello.txt \
-H "Authorization: AWS4-HMAC-SHA256 Credential=test/20260421/us-east-1/s3/aws4_request, SignedHeaders=host, Signature=fake"
# List objects in bucket
curl -s "http://localhost:4566/my-bucket?list-type=2" \
-H "Authorization: AWS4-HMAC-SHA256 Credential=test/20260421/us-east-1/s3/aws4_request, SignedHeaders=host, Signature=fake"Configuration
S3 state is global per account — it does not vary by region. All buckets are visible regardless of the region in the request.
Use forcePathStyle: true in your SDK client to use path-style URLs (/bucket/key) instead of virtual-hosted style (bucket.localhost/key).
Operations
Bucket Operations
| Operation | Description |
|---|---|
ListBuckets | List all buckets. Returns Buckets list with Name and CreationDate. No input required |
CreateBucket | Create a new bucket. Input: bucket name in URL path, optional CreateBucketConfiguration XML (for non-us-east-1 regions). Returns empty CreateBucketResult |
DeleteBucket | Delete a bucket. Must be empty first (no objects). Input: bucket name in URL path |
HeadBucket | Check if a bucket exists. Returns 200 (exists) or 404 (not found). No body returned |
GetBucketLocation | Get the bucket's region. Returns LocationConstraint (empty string for us-east-1) |
PutBucketVersioning | Enable or suspend versioning. Input: VersioningConfiguration XML with Status: Enabled/Suspended |
GetBucketVersioning | Get versioning configuration |
PutBucketTagging | Set bucket tags. Input: Tagging XML with TagSet |
GetBucketTagging | Get bucket tags. Returns TagSet |
DeleteBucketTagging | Remove all bucket tags |
PutBucketPolicy | Set a bucket policy (JSON). Input: raw JSON policy body |
GetBucketPolicy | Get bucket policy (raw JSON) |
DeleteBucketPolicy | Remove bucket policy |
PutBucketCors | Set CORS configuration. Input: CORSConfiguration XML |
GetBucketCors | Get CORS configuration |
DeleteBucketCors | Remove CORS configuration |
PutBucketNotificationConfiguration | Configure S3 event notifications (SQS, SNS, Lambda) |
GetBucketNotificationConfiguration | Get event notification config |
ACL Operations
| Operation | Description |
|---|---|
GetBucketAcl | Get the access control list for a bucket. Returns Owner and Grants list |
PutBucketAcl | Set the access control list for a bucket. Input: AccessControlPolicy XML or a canned ACL header |
GetObjectAcl | Get the ACL for an object. Returns Owner and Grants list |
Lifecycle Operations
| Operation | Description |
|---|---|
GetBucketLifecycleConfiguration | Get lifecycle rules for a bucket. Returns Rules list |
PutBucketLifecycleConfiguration | Set lifecycle rules. Input: LifecycleConfiguration XML with Rule elements |
DeleteBucketLifecycleConfiguration | Remove all lifecycle rules from a bucket |
Encryption Operations
| Operation | Description |
|---|---|
GetBucketEncryption | Get the default server-side encryption configuration for a bucket |
PutBucketEncryption | Set the default encryption. Input: ServerSideEncryptionConfiguration XML |
DeleteBucketEncryption | Remove the default encryption configuration |
Logging Operations
| Operation | Description |
|---|---|
GetBucketLogging | Get the logging configuration for a bucket. Returns LoggingEnabled element if configured |
PutBucketLogging | Set the logging configuration. Input: BucketLoggingStatus XML |
Object Operations
| Operation | Description |
|---|---|
PutObject | Upload an object. Input: PUT /{bucket}/{key}, body is object data, Content-Type header sets MIME type. Returns: ETag header |
GetObject | Download an object. Input: GET /{bucket}/{key}, optional Range header for partial reads. Returns: object body with Content-Type, ETag, Content-Length headers |
HeadObject | Get object metadata without downloading the body. Returns headers only |
DeleteObject | Delete an object. Input: DELETE /{bucket}/{key}. Returns 204 No Content |
CopyObject | Copy an object within or between buckets. Input: PUT /{dest-bucket}/{dest-key} with x-amz-copy-source: /{src-bucket}/{src-key} header |
ListObjectsV2 | List objects with optional prefix and delimiter. Input: GET /{bucket}?list-type=2&prefix=...&delimiter=/&max-keys=1000. Returns: Contents list, CommonPrefixes (virtual folders) |
DeleteObjects | Batch delete objects. Input: POST /{bucket}?delete with Delete XML listing keys. Returns: Deleted and Error lists |
PutObjectTagging | Set object tags. Input: PUT /{bucket}/{key}?tagging with Tagging XML |
GetObjectTagging | Get object tags |
DeleteObjectTagging | Remove object tags |
Multipart Upload
| Operation | Description |
|---|---|
CreateMultipartUpload | Initiate a multipart upload. Returns UploadId |
UploadPart | Upload a part. Input: PUT /{bucket}/{key}?partNumber={N}&uploadId={id}, body is part data. Returns ETag |
CompleteMultipartUpload | Complete the upload. Input: POST /{bucket}/{key}?uploadId={id} with CompleteMultipartUpload XML listing all parts and their ETags |
AbortMultipartUpload | Cancel an in-progress upload. Input: DELETE /{bucket}/{key}?uploadId={id} |
ListMultipartUploads | List in-progress uploads for a bucket |
ListParts | List uploaded parts for a multipart upload |
SDK Example
typescript
import {
S3Client,
CreateBucketCommand,
PutObjectCommand,
GetObjectCommand,
ListObjectsV2Command,
DeleteObjectCommand,
CopyObjectCommand,
} from '@aws-sdk/client-s3';
import { Readable } from 'stream';
const s3 = new S3Client({
region: 'us-east-1',
endpoint: 'http://localhost:4566',
credentials: { accessKeyId: 'test', secretAccessKey: 'test' },
forcePathStyle: true, // Required for AWSim path-style URLs
});
// Create bucket
await s3.send(new CreateBucketCommand({ Bucket: 'my-bucket' }));
// Upload text
await s3.send(new PutObjectCommand({
Bucket: 'my-bucket',
Key: 'config/settings.json',
Body: JSON.stringify({ debug: true, version: '1.0.0' }),
ContentType: 'application/json',
}));
// Upload binary
import { readFileSync } from 'fs';
await s3.send(new PutObjectCommand({
Bucket: 'my-bucket',
Key: 'images/logo.png',
Body: readFileSync('logo.png'),
ContentType: 'image/png',
}));
// Download and read
const response = await s3.send(new GetObjectCommand({
Bucket: 'my-bucket',
Key: 'config/settings.json',
}));
const text = await response.Body?.transformToString();
console.log(JSON.parse(text!));
// List objects with prefix
const { Contents, CommonPrefixes } = await s3.send(new ListObjectsV2Command({
Bucket: 'my-bucket',
Prefix: 'config/',
Delimiter: '/',
}));
console.log('Objects:', Contents?.map(o => o.Key));
// Copy object
await s3.send(new CopyObjectCommand({
Bucket: 'my-bucket',
Key: 'config/settings-backup.json',
CopySource: '/my-bucket/config/settings.json',
}));
// Delete object
await s3.send(new DeleteObjectCommand({
Bucket: 'my-bucket',
Key: 'config/settings-backup.json',
}));CLI Example
bash
# Bucket operations
aws --endpoint-url http://localhost:4566 s3 mb s3://my-bucket
aws --endpoint-url http://localhost:4566 s3 ls
# Object operations
aws --endpoint-url http://localhost:4566 s3 cp file.txt s3://my-bucket/file.txt
aws --endpoint-url http://localhost:4566 s3 cp s3://my-bucket/file.txt ./downloaded.txt
aws --endpoint-url http://localhost:4566 s3 ls s3://my-bucket/
aws --endpoint-url http://localhost:4566 s3 rm s3://my-bucket/file.txt
# Sync a directory
aws --endpoint-url http://localhost:4566 s3 sync ./dist s3://my-bucket/dist/
# Low-level API access
aws --endpoint-url http://localhost:4566 s3api put-object \
--bucket my-bucket \
--key data/record.json \
--body record.json \
--content-type application/json
aws --endpoint-url http://localhost:4566 s3api list-objects-v2 \
--bucket my-bucket \
--prefix data/ \
--max-keys 100Event Notifications
S3 can notify SQS queues, SNS topics, or Lambda functions when objects are created or deleted. See Cross-Service Integrations.
ACL Example
bash
# Get bucket ACL
aws --endpoint-url http://localhost:4566 s3api get-bucket-acl --bucket my-bucket
# Get object ACL
aws --endpoint-url http://localhost:4566 s3api get-object-acl \
--bucket my-bucket \
--key my-object.txtLifecycle Example
bash
# Put lifecycle configuration
aws --endpoint-url http://localhost:4566 s3api put-bucket-lifecycle-configuration \
--bucket my-bucket \
--lifecycle-configuration '{"Rules":[{"ID":"expire-old","Status":"Enabled","Expiration":{"Days":30},"Filter":{"Prefix":"tmp/"}}]}'
# Get lifecycle configuration
aws --endpoint-url http://localhost:4566 s3api get-bucket-lifecycle-configuration \
--bucket my-bucketEncryption Example
bash
# Enable AES-256 default encryption
aws --endpoint-url http://localhost:4566 s3api put-bucket-encryption \
--bucket my-bucket \
--server-side-encryption-configuration \
'{"Rules":[{"ApplyServerSideEncryptionByDefault":{"SSEAlgorithm":"AES256"}}]}'
# Get encryption configuration
aws --endpoint-url http://localhost:4566 s3api get-bucket-encryption --bucket my-bucketBehavior Notes
- Object data is stored in memory; object metadata (
key,size,ETag,content-type) is persisted across restarts but object body data is lost on restart. - Presigned URLs are not supported.
- Bucket ACLs and object ACLs are accepted and stored but not enforced — all objects are accessible to any caller in AWSim.
- Lifecycle rules are accepted and stored but items are not automatically expired or transitioned.
- Encryption configuration is accepted and stored but objects are not actually encrypted at rest in AWSim.
- Logging configuration is accepted and stored but no log delivery occurs in AWSim.
- Object versioning is tracked (
VersionIdis returned) butGetObjectalways returns the latest version. ListObjectsV2supportsPrefixfiltering andDelimiterfor virtual folder grouping (CommonPrefixes).- The
forcePathStyle: trueSDK option is required — virtual-hosted style (bucket.localhost:4566) is not recommended for local development.