PutObject and GetObject: the exact request, what it changes and what it costs
The two S3 calls agents make most, in CLI and TypeScript (AWS SDK for JavaScript v3) form, with the permissions each needs (including KMS), the headers that make them fail, and what a write leaves behind.
markdownreferencev4KQXP-PERHstage: operatetrust: officialservice: s3interface: cliinterface: sdkPutObjectGetObjects3api put-objects3api get-objectPutObjectCommandGetObjectCommandtransformToStrings3:PutObjects3:GetObjectkms:GenerateDataKeykms:Decryptbucket-owner-full-controlIf-None-Match
PutObject and GetObject
Write with PutObject (one request, up to the single-request limit) and read with GetObject. Beyond s3:PutObject / s3:GetObject on arn:aws:s3:::<bucket>/*, an SSE-KMS bucket also needs KMS permissions, and an ACL header on a bucket with ACLs disabled fails the write. For large files use multipart (guides/s3/upload-large-objects.md).
The request
CLI
aws s3api put-object --bucket <bucket> --key <key> --body ./file
aws s3api get-object --bucket <bucket> --key <key> ./out
aws s3api head-object --bucket <bucket> --key <key> # metadata only
Optional on put: --server-side-encryption aws:kms --ssekms-key-id <key ARN> --bucket-key-enabled; --acl bucket-owner-full-control (the only ACL accepted when ACLs are disabled). Requester Pays buckets need --request-payer requester.
TypeScript, AWS SDK for JavaScript v3
import { S3Client, PutObjectCommand, GetObjectCommand } from "@aws-sdk/client-s3";
import { readFile } from "node:fs/promises";
const s3 = new S3Client({ region: "<bucket region>" });
await s3.send(new PutObjectCommand({
Bucket: "<bucket>",
Key: "<key>",
Body: await readFile("./file"),
ContentType: "application/json",
// ServerSideEncryption: "aws:kms", SSEKMSKeyId: "<key ARN>", BucketKeyEnabled: true,
}));
const res = await s3.send(new GetObjectCommand({ Bucket: "<bucket>", Key: "<key>" }));
const text = await res.Body?.transformToString(); // or transformToByteArray()
Always consume Body (or destroy the stream): an unread body holds the socket, and enough of them exhaust the client's connections. Set the client's region to the bucket's Region rather than an endpoint (see reference/s3/buckets-and-objects.md).
Permissions
| Call | S3 action on arn:aws:s3:::<bucket>/<key> | Also needed |
|---|---|---|
| PutObject | s3:PutObject | SSE-KMS with a customer managed key: kms:GenerateDataKey on the key (key policy and IAM) |
| GetObject / HeadObject | s3:GetObject | SSE-KMS: kms:Decrypt. To get 404 rather than 403 for a missing key: s3:ListBucket on arn:aws:s3:::<bucket> |
| Multipart upload | s3:PutObject | SSE-KMS: kms:Decrypt as well as kms:GenerateDataKey |
Cross-account: the bucket policy must also allow the caller, and an AWS managed aws/s3 key cannot be used from another account.
What a write changes
- Creates or replaces the object at that key. Without versioning, the previous content is gone. With
IfNoneMatch: "*"(headerIf-None-Match: *), the write fails withPreconditionFailed(412) instead of overwriting (IfNoneMatchis aPutObjectCommandinput in the SDK's types; the 412 error code is documented). - Ownership: with the default Bucket owner enforced, the bucket owner owns the object whoever writes it.
- Encryption: the bucket default applies unless the request names another type; SSE-C writes are refused on buckets that block it.
- Visible at once: reads and listings after a successful write see it (strong consistency).
- Events: triggers any configured
s3:ObjectCreated:Putnotifications (patterns/s3-to-lambda.md).
What it costs
S3 bills requests and storage; the bucket owner is billed for 2XX and 4XX responses but not 5XX. SSE-KMS adds KMS request charges per object unless a Bucket Key is enabled. 403 responses are not billed to the bucket owner when the request comes from outside the owner's account or organization. Prices are on the S3 pricing page; none are stated here.
Failures
AccessDenied and PermanentRedirect: see reference/s3/errors.md. AccessControlListNotSupported, NoSuchBucket, NoSuchKey, EntityTooLarge, KMS.*, SlowDown: see reference/s3/bucket-and-object-errors.md.