Anatomy of an AWS API Request
Under every SDK call is a plain HTTPS request.
Busca en todas las páginas de la documentación
Under every SDK call is a plain HTTPS request.
This page opens up that request: the endpoint it targets, the headers it carries, and the SigV4 signature that proves who you are.
An AWS API call is an HTTPS request to a service endpoint, usually POST or GET, with a JSON, XML, or query-string body.
What makes it an AWS request is the signature. AWS uses Signature Version 4 (SigV4) to authenticate the caller and verify the request was not altered.
The SDK builds the canonical request, computes the signature from your secret key, and attaches it in the Authorization header.
Your secret key never travels over the wire. Only a derived signature does, so an intercepted request cannot reveal your credentials.
Every response comes back with a request id in its headers, which is the single most useful value to log when something fails.
You rarely sign by hand. But you can generate a presigned URL, which is a signed request you can hand to someone else.
# --- Python (boto3) ---
import boto3
s3 = boto3.client("s3")
url = s3.generate_presigned_url(
"get_object",
Params={"Bucket": "my-bucket", "Key": "report.pdf"},
ExpiresIn=3600, # signature valid for one hour
)
print(url)// --- TypeScript (AWS SDK v3) ---
import { S3Client, GetObjectCommand } from "@aws-sdk/client-s3";
import { getSignedUrl } from "@aws-sdk/s3-request-presigner";
const s3 = new S3Client({});
const url = await getSignedUrl(
s3,
new GetObjectCommand({ Bucket: "my-bucket", Key: "report.pdf" }),
{ expiresIn: 3600 },
);
console.log(url);When to reach for this:
ExpiresIn / expiresIn seconds).This inspects the exact HTTP request boto3 would send, without actually sending it. It is the clearest way to see the anatomy.
# --- Python (boto3) ---
import boto3
s3 = boto3.client("s3", region_name="us-east-1")
# Register a hook that fires just before the signed request goes out.
def show(request, **kwargs):
print(request.method, request.url)
for name, value in request.headers.items():
print(f"{name}: {value}")
s3.meta.events.register("before-send.s3.ListBuckets", show)
s3.list_buckets() # prints method, URL, and signed headers// --- TypeScript (AWS SDK v3) ---
import { S3Client, ListBucketsCommand } from "@aws-sdk/client-s3";
const s3 = new S3Client({ region: "us-east-1" });
// Middleware that logs the fully built, signed HTTP request.
s3.middlewareStack.add(
(next) => async (args) => {
const req = args.request as { method: string; hostname: string; headers: Record<string, string> };
console.log(req.method, req.hostname);
for (const [name, value] of Object.entries(req.headers)) console.log(`${name}: ${value}`);
return next(args);
},
{ step: "finalizeRequest" },
);
await s3.send(new ListBucketsCommand({}));What this demonstrates:
before-send fires after signing, so you see the real headers.finalizeRequest step runs after the signer.Host, X-Amz-Date, Authorization, and usually X-Amz-Content-Sha256.Authorization header contains the signature but never your secret key.Authorization header.| Header | Purpose |
|---|---|
Host | The resolved service endpoint hostname |
X-Amz-Date | Request timestamp, part of the signature scope |
Authorization | Credential scope, signed headers, and the SigV4 signature |
X-Amz-Content-Sha256 | Hash of the request body (required by S3) |
X-Amz-Security-Token | Session token, present when using temporary credentials |
x-amz-request-id (and often x-amz-id-2) headers.response["ResponseMetadata"]["RequestId"].response.$metadata.requestId.ExpiresIn and regenerate when it lapses.X-Amz-Security-Token; omitting it fails auth. Fix: let the SDK resolve full credentials rather than passing only key and secret.RequestId / $metadata.requestId on every error.| Alternative | Use When | Don't Use When |
|---|---|---|
| Presigned URL | A browser or third party needs temporary access | The caller already has its own credentials |
| SDK auto-signing (default) | Normal in-app calls | You need a shareable, credential-free link |
| Manual SigV4 signing | A niche client with no SDK | An SDK exists for your language (almost always) |
AWS Signature Version 4, the signing process that authenticates a request and verifies its integrity by deriving an HMAC-SHA256 signature from your secret key and the request contents.
No. Only a signature derived from it is sent, in the Authorization header. AWS recomputes the same signature server-side to verify you without ever receiving the key.
At minimum Host, X-Amz-Date, and Authorization. S3 adds X-Amz-Content-Sha256, and temporary credentials add X-Amz-Security-Token.
The algorithm, your access key id and credential scope, the list of signed headers, and the computed signature. It does not contain the secret key.
The signature covers the timestamp, so AWS accepts it only within a limited window. This limits the damage if a request is captured and replayed later.
A URL with the SigV4 signature encoded into its query string, granting time-limited access to one operation without sharing credentials. It is ideal for browser uploads and downloads.
Common causes are a skewed system clock, a modified request after signing, or missing session token for temporary credentials. Sync the clock and let the SDK build the whole request.
In boto3 at response["ResponseMetadata"]["RequestId"], and in SDK v3 at response.$metadata.requestId. Log it for debugging and support cases.
Yes. boto3 exposes lifecycle events like before-send, and SDK v3 lets you add middleware at the finalizeRequest step to log the built, signed request.
No. Services use JSON, XML, or query-string encodings depending on their API. The SDK serializes your input into whatever the target service expects.
The signing process is the same, but they add an X-Amz-Security-Token header carrying the session token, which AWS validates alongside the signature.
No. AWS service endpoints require HTTPS. SigV4 assumes TLS protects the request in transit, so only override to HTTP against a local test tool.
Stack versions: This page was written for boto3 1.43.x (Python 3.10+) and the AWS SDK for JavaScript v3 (Node.js 18+).
Revisado por Chris St. John·Última actualización: 23 jul 2026