HeadBucket
HeadBucket is the lightest way to ask "is this bucket here, and may I use it?". A bucket that
exists in the endpoint's region and that your access key can reach answers 200 OK with no body,
and nothing else is read or changed. Most S3 clients and tools make this call before they start
working with a bucket.
- Each endpoint answers for the buckets in its own region. A bucket in another region answers
404 Not Foundrather than a redirect, so the bucket's own regional endpoint is the one to ask. x-amz-bucket-regioncomes with every200, and it is always the endpoint's region - the region the bucket was just found in.- A bucket name held by someone else answers
404 Not Found, exactly like a name nobody holds, so the answer never says whether another customer has it. - HeadBucket is always a signed request. Anonymous visitors to a public bucket read its objects with GetObject and HeadObject instead.
x-amz-expected-bucket-owneris welcome and has nothing to check: a key only ever reaches buckets of its own account.
When you'd use it
- S3 clients and SDK tools. Sync and backup tools commonly check that their target bucket is there before they upload anything, and HeadBucket gives them a quick, cheap answer.
- Create-if-missing scripts. A deploy script or an agent setting up its storage can ask
whether the bucket already exists, and call CreateBucket only on a
404. - Checking a key. A health check or a newly configured application can confirm that its
access key reaches the bucket it was given:
200means it does,403that the key is not allowed to. - Finding where a bucket lives. A script handed only a bucket name can ask each regional
endpoint in turn; the one that answers
200is the bucket's region.
Request
HEAD / 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 on s3.eu-central-1.strg.com -
Addressing explains both.
Permissions
The access key needs List buckets (buckets:list), which every access key holds, whether it
covers all buckets or only some. A key limited to certain buckets can check those buckets, and any
other bucket answers 403 Forbidden. Access keys has the
details.
URI parameters
| Name | Type | Required | Description |
|---|---|---|---|
Bucket | String | Yes | The bucket to check. |
HeadBucket takes no query parameters. Apart from a presigned URL's X-Amz-* parameters and the
JavaScript SDK's x-id, a query parameter answers 501 Not Implemented, so a client knows
straight away.
Request headers
| Name | Type | Required | Description |
|---|---|---|---|
x-amz-expected-bucket-owner | String | No | Welcome, with nothing to check: an access key only ever reaches its own account's buckets. |
Request body
None.
Response
A bucket that exists in the endpoint's region and that your key can reach answers 200 OK with
no body.
Response headers
| Name | Description |
|---|---|
x-amz-bucket-region | The bucket's region - always the region of the endpoint you called, such as eu-central-1. Sent with 200 OK. |
x-amz-request-id | The request ID, handy for a support request. |
x-amz-id-2 | The same request ID. |
x-amz-bucket-arn | Not part of the answer. |
x-amz-bucket-location-type | Not part of the answer. |
x-amz-bucket-location-name | Not part of the answer. |
x-amz-access-point-alias | Not part of the answer. |
Response body
None.
Errors
A HEAD response never has a body, so the error code in the table does not reach your client -
the HTTP status does. The AWS CLI and boto3 report the status itself (404, 403) as the error
code; the JavaScript SDK reports NotFound or Forbidden for those two, with the status in
$metadata.httpStatusCode. The table lists the situation behind each status.
| Code | HTTP status | When |
|---|---|---|
NoSuchBucket | 404 | The bucket does not exist, belongs to someone else, or is in a region other than the endpoint's - including when your account has nothing stored in this endpoint's region yet. |
AccessDenied | 403 | The access key is limited to buckets that do not include this one, your account is not active, the request is unsigned, or a presigned URL has expired. |
InvalidAccessKeyId | 403 | The access key does not exist, has expired or been revoked, or was created so recently that it is not yet usable in this endpoint's region: you already store data in this region, and the key is still being set up there. The Access Keys page shows Setting up in region until it is Ready in region, usually within a few minutes - When a key starts working has the details. |
SignatureDoesNotMatch | 403 | The request signature does not match. |
RequestTimeTooSkewed | 403 | The request time is more than 15 minutes from the server's. |
AuthorizationHeaderMalformed | 400 | The signature's credential scope names a region other than the endpoint's. |
InvalidBucketName | 400 | The bucket name is not a valid STRG bucket name - names are 3-58 characters. |
NotImplemented | 501 | The request carries a query parameter this operation does not take. |
SlowDown | 503 | Too many requests at once; a retry after the Retry-After interval goes through. |
ServiceUnavailable | 503 | A temporary failure; a retry usually succeeds. |
Differences from Amazon S3
| Aspect | Amazon S3 | STRG |
|---|---|---|
| Bucket in another region | Answered from any region, with x-amz-bucket-region naming the bucket's region | 404 Not Found, with no x-amz-bucket-region. The bucket's own regional endpoint answers it; the SDKs' region-redirect retry does not come into play |
x-amz-bucket-region | Sent on success and on most errors | Sent with 200 OK, and always the endpoint's region |
| Bucket owned by another account | 403 Forbidden | 404 Not Found, the same as a name nobody holds |
| Unsigned requests to public buckets | Accepted where the bucket allows public listing | Always signed; an unsigned request answers 403 Forbidden. Public buckets are read anonymously through GetObject and HeadObject - Anonymous reads |
x-amz-expected-bucket-owner | Checked against the bucket owner | Welcome, with nothing to check - a key only reaches its own account's buckets |
x-amz-bucket-arn, x-amz-bucket-location-type, x-amz-bucket-location-name, x-amz-access-point-alias | Returned where they apply | Not part of the answer |
Examples
- AWS CLI
- Python (boto3)
- JavaScript (AWS SDK v3)
aws s3api head-bucket \
--bucket my-bucket \
--endpoint-url https://s3.eu-central-1.strg.com \
--region eu-central-1
{
"BucketRegion": "eu-central-1"
}
When the bucket is not there, the command exits non-zero with
An error occurred (404) when calling the HeadBucket operation: Not Found.
import boto3
from botocore.exceptions import ClientError
s3 = boto3.client(
"s3",
endpoint_url="https://s3.eu-central-1.strg.com",
region_name="eu-central-1",
)
try:
response = s3.head_bucket(Bucket="my-bucket")
print(f"my-bucket exists in {response['BucketRegion']}")
except ClientError as error:
if error.response["Error"]["Code"] == "404":
print("my-bucket is not in eu-central-1")
else:
raise
import { HeadBucketCommand, S3Client } from "@aws-sdk/client-s3";
const client = new S3Client({
endpoint: "https://s3.eu-central-1.strg.com",
region: "eu-central-1",
});
try {
const response = await client.send(new HeadBucketCommand({ Bucket: "my-bucket" }));
console.log(`my-bucket exists in ${response.BucketRegion}`);
} catch (error) {
if (error.$metadata?.httpStatusCode === 404) {
console.log("my-bucket is not in eu-central-1");
} else {
throw error;
}
}
Finding which region a bucket is in works the same way with HeadBucket as with
GetBucketLocation: each regional endpoint is
asked in turn, and the one answering 200 is the bucket's. STRG has two regions, us-east-1
and eu-central-1, listed with their endpoints in
Regions and endpoints, so it takes at most two requests.
An endpoint for a region where your account has no bucket at all answers 404 as well, which is
the truth: the bucket is not there.
Related
- GetBucketLocation - the bucket's region, in an XML body
- ListBuckets
- HeadObject
- S3 API overview - every difference from Amazon S3
- Access keys