How to change an S3 object's content type or metadata
S3 has no UpdateObject call, so changing a stored header — content type, cache-control, content-disposition, content-language, content-encoding, Expires — or the custom metadata means copying the object onto itself with MetadataDirective set to REPLACE. S3 Viewer's Edit settings does exactly that on every provider, R2 included, guarded by the same reviewed-ETag condition as every other write. Storage class, server-side encryption and, on AWS, ACL grants and tags all carry over; only the headers you changed are new.
Step-by-step.
- 01
In S3 Viewer: open the object and choose Edit settings
Open the object and click Edit settings. Change the content type, cache-control, content-disposition, content-language, content-encoding or expires header, add or remove custom metadata keys, and save. S3 Viewer sends a self-copy withMetadataDirective: REPLACE, checks the object hasn't changed since you opened it, and refreshes the details panel once the write lands. Leave a field blank to remove that header entirely. - 02
AWS CLI: copy-object onto itself
aws s3api copy-objectwith the same bucket and key as both source and destination, plus--metadata-directive REPLACE, rewrites the object's headers without touching its bytes.aws s3api copy-object \ --bucket my-bucket \ --copy-source my-bucket/reports/q3.pdf \ --key reports/q3.pdf \ --metadata-directive REPLACE \ --content-type application/pdf \ --cache-control "max-age=3600" \ --metadata reviewed=true - 03
AWS SDK: copyObject with MetadataDirective REPLACE
WithoutMetadataDirective: "REPLACE",copyObjectdefaults toCOPYand keeps the source's headers and metadata untouched — REPLACE is what makes this a settings edit rather than a plain duplicate.await s3.copyObject({ Bucket: 'my-bucket', CopySource: 'my-bucket/reports/q3.pdf', Key: 'reports/q3.pdf', MetadataDirective: 'REPLACE', ContentType: 'application/pdf', CacheControl: 'max-age=3600', Metadata: { reviewed: 'true' }, }); - 04
Only the source needs to be unchanged, not the destination
Because the destination key is the source key, there is nothing to check for “already exists” — S3 Viewer's only condition is that the object still matches the ETag you reviewed before opening the dialog. A source that changed underneath you refuses the write with a 409 instead of overwriting whatever is there now. - 05
Metadata keys and sizes follow S3's own limits
Custom metadata keys are lower-cased, limited to 64 characters ofa-z0-9-, capped at 50 keys, 1 KiB per value and 2 KiB total across all of them — S3's own ceiling for thex-amz-meta-*headers, not something S3 Viewer invented. A key or value outside those limits is rejected before anything is sent. - 06
Objects over 5 GB copy in parts, automatically
The same 5 GB ceiling that applies to a plainCopyObjectapplies to a self-copy. S3 Viewer switches to a multipart copy above that size — initiating the multipart upload with the new headers, then copying each part from the source — so a settings edit has no practical size cap.
What's actually happening.
Every header S3 stores alongside an object's bytes — content type, cache-control, content-disposition, content-language, content-encoding, Expires, and custom x-amz-meta-* metadata — is set once, at write time, and there is no API call that changes it without rewriting the object. CopyObject is the write S3 Viewer reuses for this: point the copy source and destination at the same bucket and key, set MetadataDirective to REPLACE, and the object's bytes are copied onto themselves while every header you pass becomes the new one.
The one thing that has to be handled carefully is the precondition. A normal copy protects the destination with IfNoneMatch — refuse if something is already there. That's meaningless here, since the destination is the source. Instead S3 Viewer conditions the write on CopySourceIfMatch, the ETag you reviewed when you opened the settings dialog, so an object someone else changed in the meantime is never silently overwritten with stale headers.
This works the same way on AWS S3, R2, B2 and MinIO: a self-copy with REPLACE is a standard part of the S3 API, not an AWS extension. Where a provider doesn't enforce the source condition itself, S3 Viewer checks it with a HEAD request immediately beforehand instead — the same conditional-or-checked split every mutation in S3 Viewer follows.
Common questions.
Can I change an S3 object's content type after uploading it?
How do I add or remove custom metadata on an S3 object?
Does changing metadata re-upload the file?
What happens to tags, ACLs and storage class when I edit settings?
Can I change content type or metadata on a Cloudflare R2 object?
Why does S3 Viewer ask me to reload after a settings edit fails?
Skip the CLI. Try it in the browser.
S3 Viewer turns the steps above into a single click. Open source, self-hostable, free.
Why teams pick this
More how-tos
Edit a file in place
S3 has no edit API either — here's the read, change, conditional-write pattern for small text files, in the console, the CLI, and S3 Viewer.
Rename an S3 file
Amazon S3 has no rename API — keys are immutable. Here's the standard copy + delete pattern, with metadata and tags preserved.
Upload large files
How large uploads work in S3 Viewer and from the CLI — streaming, retries, and the 5 GB single-PUT cap.