🧠 Introduction

When working with Amazon S3, two common commands developers use are HeadObjectCommand and GetObjectCommand.
At first glance, they might seem similar β€” both retrieve object information β€” but they serve different purposes.

Let’s explore how they differ and when to use each.


βš™οΈ HeadObjectCommand

HeadObjectCommand retrieves only the metadata of an S3 object, without downloading the file content.

This is ideal when you just want to:

  • Check if a file exists.
  • Get metadata (like Content-Type, Content-Length, Last-Modified, ETag, etc.).
  • Verify object accessibility or permissions.

βœ… Example

import { S3Client, HeadObjectCommand } from "@aws-sdk/client-s3";

const s3 = new S3Client({ region: "ap-southeast-1" });

async function checkFileInfo() {
  try {
    const command = new HeadObjectCommand({
      Bucket: "my-bucket",
      Key: "example/data.json",
    });

    const response = await s3.send(command);
    console.log("βœ… Object found:", response);
  } catch (err) {
    if (err.name === "NotFound") {
      console.log("❌ Object not found");
    } else {
      console.error("⚠️ Error:", err);
    }
  }
}

checkFileInfo();

πŸ’‘ Output (sample)

{
  "AcceptRanges": "bytes",
  "LastModified": "2025-10-31T02:45:10.000Z",
  "ContentLength": 24987,
  "ContentType": "application/json",
  "ETag": "\"d41d8cd98f00b204e9800998ecf8427e\""
}

πŸ‘‰ No file data is returned β€” only metadata.


πŸ“¦ GetObjectCommand

GetObjectCommand retrieves the full object (its content and metadata).
Use it when you actually need to read or process file contents.

βœ… Example

import { S3Client, GetObjectCommand } from "@aws-sdk/client-s3";
import { Readable } from "stream";

const s3 = new S3Client({ region: "ap-southeast-1" });

async function downloadFile() {
  const command = new GetObjectCommand({
    Bucket: "my-bucket",
    Key: "example/data.json",
  });

  const { Body, ContentType } = await s3.send(command);
  console.log("πŸ“¦ Content-Type:", ContentType);

  // Convert stream to string (for small files)
  const streamToString = (stream: Readable) =>
    new Promise((resolve, reject) => {
      const chunks: any[] = [];
      stream.on("data", (chunk) => chunks.push(chunk));
      stream.on("end", () => resolve(Buffer.concat(chunks).toString("utf-8")));
      stream.on("error", reject);
    });

  const content = await streamToString(Body as Readable);
  console.log("πŸ“„ File Content:", content);
}

downloadFile();

βš–οΈ Comparison Table

FeatureHeadObjectCommandGetObjectCommand
PurposeCheck existence / metadataRetrieve full object
Downloads data❌ Noβœ… Yes
Typical usageValidation, info, cache checkFile reading, streaming, processing
PerformanceFaster (metadata only)Slower (includes full data)
CostLower (no data transfer)Higher (data transfer applies)

🧩 When to Use Which?

  • βœ… Use HeadObjectCommand
    When you only need to verify if an object exists or get metadata quickly and cheaply.

  • βœ… Use GetObjectCommand
    When you actually need the object content (to read, download, or process).


πŸ“š References


🧾 Summary

In short:

HeadObjectCommand β†’ metadata only
GetObjectCommand β†’ metadata + file content

Use the right command for your case to optimize performance and cost.


Written by Frank Nguyen
(c) 2025 β€” Notes from real-world AWS projects πŸ’»)