Skip to main content

HeadObject

HeadObject returns an object's headers without its body: the same answer as GetObject, minus the data. It is the quick way to find out whether an object exists, how big it is, its ETag, content type and x-amz-meta-* metadata, or whether a condition holds before a download starts - all without transferring a single byte of the object.

Good to know on STRG
  • Every object is stored in STANDARD, so there is no storage class to keep track of.
  • The response-* overrides take Latin-1 text; a value outside it answers 500 InternalError, and the filename*=UTF-8''... form carries any other file name.
  • Anyone can read the metadata of an object in a bucket whose Bucket Protection is off, without signing - response-* overrides need a signed request or a presigned URL.
  • An unsigned request can be answered from a cache for up to 5 minutes, when the object's own Cache-Control allows it.
  • A key with a . or .. path segment (a/../b) cannot be put in a URL, so it answers 400 InvalidURI.
  • A bucket in another region answers 404, rather than a 301 redirect.
  • x-amz-expected-bucket-owner is welcome and has nothing to check: a key only ever reaches buckets of its own account.
  • A query parameter HeadObject does not take answers 501 NotImplemented, so a client knows straight away.

When you'd use it​

  • A sync or backup tool deciding what to upload. Before sending a file, a nightly backup compares the stored object's size, ETag and Last-Modified with the local copy, and uploads only what changed.
  • Checking that an object is there. A web app that has just received an upload confirms the object exists before showing its link; a missing one answers 404.
  • Planning a large download. A download manager reads Content-Length - and, with partNumber, x-amz-mp-parts-count - and then fetches the object in ranges or parts with GetObject, several at once.
  • An agent reading its own notes. An agent keeping files in a bucket stores a summary in x-amz-meta-* metadata, and reads it back with HeadObject without downloading each file.

Request​

HEAD /photos/2024/cat.jpg HTTP/1.1
Host: my-bucket.s3.eu-central-1.strg.com
Authorization: AWS4-HMAC-SHA256 Credential=...
x-amz-date: 20260926T120000Z
x-amz-content-sha256: e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855

The path-style form is HEAD /my-bucket/photos/2024/cat.jpg on s3.eu-central-1.strg.com, which a bucket name containing a dot needs - Addressing explains both. A presigned HEAD URL works too.

Permissions​

The access key needs Read objects (objects:read). For a key limited to certain buckets or to a key prefix, the bucket and the object key are within them; anything else answers 403 AccessDenied. Access keys has the details.

The Object Lock headers appear in the response when the key also holds Read retention (object-retention:read), for the retention headers, or Read legal holds (object-legal-hold:read), for the legal hold header. Without them the response simply leaves the object's lock out. Object Lock explains both.

Unsigned requests​

A request with no signature at all - no Authorization header and no presigned query - reads the metadata of an object in a bucket whose Bucket Protection is off, just as GetObject reads the object. A protected bucket answers 403, and a bucket that does not exist, or is in another region, 404. response-* overrides need a signature, so an unsigned request carrying one answers 400. Anonymous reads covers every case.

An unsigned HEAD can be answered from a cache rather than from the stored object, when the object was stored with a Cache-Control that lets a shared cache keep it (max-age or s-maxage above zero, and none of no-store, no-cache or private). A cached answer is kept for the shorter of that lifetime and 5 minutes, and the response still carries the object's own Cache-Control. The cache is never cleared early: for up to 5 minutes after an object is overwritten or deleted, Bucket Protection is turned on, or the bucket's CORS rules change, anonymous readers can still get the previous answer. An object stored without Cache-Control is never cached, and a request carrying If-Match, If-Unmodified-Since or any x-amz-* header, or a query parameter other than versionId, always reads the stored object.

A bucket created a moment ago can answer unsigned requests with 404 for a few seconds, until every endpoint has heard about it.

URI parameters​

NameTypeRequiredDescription
BucketStringYesThe bucket that holds the object.
KeyStringYesThe object's key. A key with a . or .. path segment (a/../b) cannot be put in a URL and answers 400 InvalidURI.
versionIdStringNoA specific version of the object. Without it, the current version is used.
partNumberIntegerNo1-10,000. Describes that part of an object uploaded by multipart upload: Content-Length is the part's size.
response-cache-controlStringNoSets Cache-Control on the response.
response-content-dispositionStringNoSets Content-Disposition on the response. Latin-1 characters only - a value outside it answers 500 InternalError - and the filename*=UTF-8''... form carries a non-ASCII file name.
response-content-encodingStringNoSets Content-Encoding on the response.
response-content-languageStringNoSets Content-Language on the response.
response-content-typeStringNoSets Content-Type on the response.
response-expiresStringNoSets Expires on the response.

The response-* overrides apply to a 200 or 206 answer only, never to a 304 or an error, and need a signed request or a presigned URL: an unsigned request carrying one answers 400. Any other query parameter, apart from presigning's own X-Amz-*, answers 501 NotImplemented.

Request headers​

NameTypeRequiredDescription
If-MatchStringNoAnswers only if the object's ETag matches; otherwise 412.
If-None-MatchStringNoAnswers only if the object's ETag differs; otherwise 304.
If-Modified-SinceTimestampNoAnswers only if the object changed after this time; otherwise 304.
If-Unmodified-SinceTimestampNoAnswers only if the object has not changed since this time; otherwise 412.
RangeStringNoA byte range, such as bytes=0-1023. Only the headers change: Content-Length and Content-Range describe the range. A range that cannot be satisfied answers 416.
x-amz-server-side-encryption-customer-algorithmStringFor SSE-C objectsAES256. Required for an object stored with a customer-provided key (SSE-C).
x-amz-server-side-encryption-customer-keyStringFor SSE-C objectsThe base64-encoded 256-bit key the object was stored with.
x-amz-server-side-encryption-customer-key-MD5StringFor SSE-C objectsThe base64-encoded MD5 digest of that key.
x-amz-checksum-modeStringNoENABLED asks for the object's stored checksum.
x-amz-request-payerStringNoHas no effect: STRG has no Requester Pays buckets, so there is never a need to send it.
x-amz-expected-bucket-ownerStringNoWelcome, with nothing to check: an access key only ever reaches its own account's buckets.

A signed request signs every x-amz-* header it carries; one left unsigned answers 403. Authentication has the details.

Request body​

None.

Response​

A HEAD response never has a body, successful or not.

Response headers​

NameDescription
Content-LengthThe object's size in bytes - or the part's with partNumber, or the range's with Range.
Content-Type, Cache-Control, Content-Disposition, Content-Encoding, Content-Language, ExpiresAs stored with the object, or as set by a response-* override.
Content-RangeWith Range, the range the answer describes.
Accept-Rangesbytes.
ETagThe object's entity tag.
Last-ModifiedWhen the object was last written.
x-amz-meta-*The object's user metadata, one header per entry.
x-amz-version-idThe version described.
x-amz-delete-markertrue when the version addressed is a delete marker.
x-amz-server-side-encryptionAES256 when the object is encrypted with STRG-managed keys.
x-amz-server-side-encryption-customer-algorithm, x-amz-server-side-encryption-customer-key-MD5For an SSE-C object, echoing the key you sent.
x-amz-checksum-crc32, x-amz-checksum-crc32c, x-amz-checksum-crc64nvme, x-amz-checksum-sha1, x-amz-checksum-sha256, x-amz-checksum-typeThe checksum stored with the object, if it was uploaded with one. Never on a 304.
x-amz-checksum-sha512, x-amz-checksum-md5, x-amz-checksum-xxhash64, x-amz-checksum-xxhash3, x-amz-checksum-xxhash128Not returned: uploads use the checksum algorithms in the row above.
x-amz-mp-parts-countWith partNumber, the number of parts in a multipart object.
x-amz-storage-classAbsent or STANDARD: every object is STANDARD.
x-amz-object-lock-mode, x-amz-object-lock-retain-until-dateThe object's retention, when it has one and the key holds Read retention.
x-amz-object-lock-legal-holdON or OFF, when the key holds Read legal holds.
x-amz-object-lock-event-hold, x-amz-object-lock-event-hold-duration-days, x-amz-object-lock-event-hold-duration-yearsNot returned: STRG has no event holds.
x-amz-tagging-countNot returned: objects carry no tags.
x-amz-server-side-encryption-aws-kms-key-id, x-amz-server-side-encryption-bucket-key-enabledNot returned: STRG encrypts with its own managed keys (AES256) or yours (SSE-C), never SSE-KMS.
x-amz-restore, x-amz-archive-statusNot returned: there are no archive storage classes, so every object is ready to read.
x-amz-replication-statusNot returned: STRG has no bucket replication.
x-amz-website-redirect-locationNot returned: STRG has no website hosting.
x-amz-expirationNot guaranteed when a lifecycle policy applies, so a client is better off not depending on it.
x-amz-missing-metaNot returned.
x-amz-request-chargedNot returned: STRG has no Requester Pays buckets.
x-amz-request-idThe request ID, handy for a support request.
Access-Control-Allow-Origin, Access-Control-Allow-Credentials, Access-Control-Expose-Headers, VaryFor a browser request whose Origin the bucket's CORS rules allow, signed or unsigned. CORS rules has the details.

Response body​

None.

Errors​

A HEAD error has no body, so only the HTTP status reaches your client: the AWS SDK for JavaScript reports a 404 as NotFound, and boto3 raises a ClientError whose code is the status ("404"). The table names the S3 error behind each status, and the situation it comes from.

CodeHTTP statusWhen
-304If-None-Match matched, or the object is unchanged since If-Modified-Since. Not an error: the object simply has not changed.
PreconditionFailed412If-Match did not match, or the object changed since If-Unmodified-Since.
InvalidRange416The Range cannot be satisfied.
NoSuchKey404The object or version does not exist, or the current version is a delete marker.
NoSuchBucket404The bucket does not exist, it is in a region other than the endpoint's, or the account has no storage in this endpoint's region yet.
AccessDenied403The access key lacks Read objects, the bucket or key is outside its buckets or prefix, the account is not active, or an x-amz-* header of a signed request is unsigned. For an unsigned request: the bucket's Bucket Protection is on, or the bucket's owner has an invoice at the stage where every operation pauses.
InvalidAccessKeyId403The access key does not exist, has expired or been revoked - or it was created moments ago and is not usable yet in a region where the account already stores data, in which case the same request works shortly afterwards.
SignatureDoesNotMatch403The request signature does not match.
RequestTimeTooSkewed403The request time is more than 15 minutes from the server's.
AuthorizationHeaderMalformed400The signature's credential scope names a region other than the endpoint's.
InvalidRequest400An unsigned request carries a response-* override.
InvalidURI400The key contains a . or .. path segment, signed or unsigned.
-400An unsigned request names a bucket deleted moments ago, or the request is otherwise malformed.
InternalError500A response-* override carries a character outside Latin-1.
NotImplemented501The request carries a query parameter HeadObject does not take.
SlowDown503Too many requests. The Retry-After header says when a retry is welcome; the AWS SDKs retry on their own.
ServiceUnavailable503A temporary failure; the same request can be retried.

Differences from Amazon S3​

A few things work a little differently on STRG, each listed here with what it means for your requests.

AspectAmazon S3STRG
Storage classSeveral; the header names any but STANDARDSTANDARD for every object
Bucket in another region301 redirect with x-amz-bucket-region404. A bucket is reached through its own regional endpoint
Anonymous requestsAllowed on a public objectAllowed in a bucket whose Bucket Protection is off; 403 otherwise
Anonymous answersAlways the stored objectCan come from a cache for the shorter of the object's Cache-Control lifetime and 5 minutes, so for up to 5 minutes an overwritten or deleted object can be described as it was, and a bucket just protected can still answer
Keys with . or .. segmentsAllowed400 InvalidURI. DeleteObjects deletes such a key
response-* overridesAny valueLatin-1, otherwise 500. filename*=UTF-8''... carries a non-ASCII file name
Unknown query parametersIgnored501 NotImplemented, so a client knows straight away
Tags, SSE-KMS, event holds, archive and replication headersReturned where they applyNever returned, since STRG has none of these features to report on
x-amz-expected-bucket-ownerChecked against the bucket ownerWelcome, with nothing to check

Examples​

Reading the metadata of photos/2024/cat.jpg in my-bucket, and telling a missing object apart from other failures:

aws s3api head-object \
--bucket my-bucket \
--key photos/2024/cat.jpg \
--endpoint-url https://s3.eu-central-1.strg.com \
--region eu-central-1

A missing object exits with an error naming (404) and Not Found.

A specific version takes --version-id (CLI), VersionId= (boto3) or VersionId (JavaScript), with the version's ID.

Checking by its ETag whether an object changed since it was last seen. An unchanged object answers 304, which the SDKs raise as an error:

aws s3api head-object \
--bucket my-bucket \
--key photos/2024/cat.jpg \
--if-none-match '"85f30635602dc09bd85957a6e82a2c21"' \
--endpoint-url https://s3.eu-central-1.strg.com \
--region eu-central-1

Reading the metadata of an object in a bucket whose Bucket Protection is off, without credentials:

aws s3api head-object \
--bucket my-bucket \
--key photos/2024/cat.jpg \
--no-sign-request \
--endpoint-url https://s3.eu-central-1.strg.com \
--region eu-central-1
View as Markdown