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

Created 18 Oct 2026 · Modified 23 Oct 2026 · 4 versions

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

CallS3 action on arn:aws:s3:::<bucket>/<key>Also needed
PutObjects3:PutObjectSSE-KMS with a customer managed key: kms:GenerateDataKey on the key (key policy and IAM)
GetObject / HeadObjects3:GetObjectSSE-KMS: kms:Decrypt. To get 404 rather than 403 for a missing key: s3:ListBucket on arn:aws:s3:::<bucket>
Multipart uploads3:PutObjectSSE-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: "*" (header If-None-Match: *), the write fails with PreconditionFailed (412) instead of overwriting (IfNoneMatch is a PutObjectCommand input 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:Put notifications (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.

Read this document as markdown — the same bytes an agent receives.