S3 ListObjectsV2: List More Than 1,000 Objects in Python, JavaScript, CLI and PowerShell, Prefixes and Folders, s3:ListBucket, and S3 Limits

Logeshwaran
—

S3 ListObjectsV2 returns at most 1,000 objects per call, so to list more you must paginate: when the response says IsTruncated: true, call again with its NextContinuationToken as the ContinuationToken, until it says false. You rarely write that loop yourself: in Python use s3.get_paginator("list_objects_v2"), in JavaScript paginateListObjectsV2, in the AWS CLI aws s3api list-objects-v2 (it pages for you), and in PowerShell Get-S3Object. Use Prefix to list one "folder" and Delimiter="/" to get the folders themselves in CommonPrefixes. The permission you need is s3:ListBucket on the bucket ARN (not bucket/*); there is no IAM action called ListObjects. And the S3 limits people search alongside this: objects up to 50 TB (5 GB in a single PUT, larger with multipart upload), no limit on the number of objects per bucket, and keys up to 1,024 bytes. Below: copy-ready code for each language, prefixes and delimiters, counting objects and sizes without listing millions, speed and cost, and the errors.

Jake's computer shop uploads photos of every repair to S3: before, after, and anything odd in between. Ethan's first script to count them printed exactly 1,000. So did the second, after another busy week. The bucket actually held 23,481 photos. S3 had not lost anything; the script had read only the first page of results. It is the most common S3 surprise there is, and the fix is a few lines in any language.

⚡ Quick Answer

• Python: s3.get_paginator("list_objects_v2").paginate(Bucket=..., Prefix=...). Code.

• JavaScript: paginateListObjectsV2({ client }, { Bucket }). Code.

• CLI: aws s3api list-objects-v2 --bucket b --prefix p --query "Contents[].Key". More.

• Permission: s3:ListBucket on arn:aws:s3:::bucket. Policy.

How paging works · Prefixes and folders · Count without listing · S3 limits · Errors.

New to S3? Our plain-English S3 explainer covers buckets, objects and keys, and the cards below cover the rest.

🧭 NEW HERE? READ THESE FIRST

New to S3 or the AWS command line? These five pages give you the background this one builds on:

📌 Bookmark this; the code for your language and the limits table are the parts you will come back for.

Why you only get 1,000 objects, and how paging works

A bucket can hold billions of objects, so S3 never returns them all at once. Each ListObjectsV2 call returns one page of up to 1,000 keys, in order, plus enough information for you to ask for the next page:

FieldWhereWhat it means
MaxKeysRequestHow many keys you want per page; 1,000 is both the default and the maximum
ContentsResponseThe objects on this page: key, size, last modified, ETag, storage class
IsTruncatedResponsetrue means more pages follow
NextContinuationTokenResponsePass this back as ContinuationToken to get the next page
KeyCountResponseHow many keys (and common prefixes) are on this page
Prefix, Delimiter, StartAfterRequestNarrow the listing to a "folder," group by folders, or start after a given key

Results come back in alphabetical order of key (strictly, UTF-8 binary order) in ordinary buckets, which is why paging works so neatly: each page continues where the last left off. (S3 Express One Zone "directory buckets" are the exception: their listings are not in sorted order.)

The bug in Ethan's first script is the bug in most scripts: one call, read Contents, stop. Everything below is about not stopping until IsTruncated is false, preferably by letting the SDK do it.

Jake: "So it was like reading only the first page of the phone book?"

Ethan: "Exactly, and the first page always has exactly a thousand names, which is how I should have guessed."

Fix a script that stops at 1,000, step by step

  1. Confirm the symptom: if your count is exactly 1,000 (or exactly your MaxKeys), you are reading one page. Print IsTruncated from the response; true confirms it.
  2. Switch to your SDK's paginator (code for each language below), or add the continuation-token loop.
  3. Handle empty pages, which have no Contents, so your code does not crash on an empty prefix.
  4. Test on one small prefix first, such as a single month, and compare with the console's count for that "folder."
  5. Run it on the whole bucket, and if it is slow, split the work by prefix in parallel.
  6. If you only need totals, switch to CloudWatch's free daily metrics instead, as covered further down.

List all objects in Python (boto3)

The paginator handles the continuation tokens for you. This lists every object under a prefix, however many there are:

import boto3

s3 = boto3.client("s3")
paginator = s3.get_paginator("list_objects_v2")

count, total_bytes = 0, 0
for page in paginator.paginate(Bucket="shop-repair-photos", Prefix="2026/"):
    for obj in page.get("Contents", []):
        count += 1
        total_bytes += obj["Size"]

print(f"{count} objects, {total_bytes / 1e9:.2f} GB")

Two details matter. page.get("Contents", []) rather than page["Contents"]: a page with no objects (an empty prefix, for example) has no Contents key at all, and indexing it raises a KeyError. And the paginator makes calls lazily, one page at a time as you loop, so memory use stays small even for millions of objects.

Just the keys, as a list:

keys = [obj["Key"]
        for page in paginator.paginate(Bucket="shop-repair-photos", Prefix="2026/10/")
        for obj in page.get("Contents", [])]

The resource interface pages automatically too, and reads a little shorter:

bucket = boto3.resource("s3").Bucket("shop-repair-photos")
for obj in bucket.objects.filter(Prefix="2026/10/"):
    print(obj.key, obj.size, obj.last_modified)

Filtering with JMESPath: paginators can filter as they go, for example only objects over 5 MB:

pages = paginator.paginate(Bucket="shop-repair-photos")
for obj in pages.search("Contents[?Size > `5000000`][]"):
    print(obj["Key"], obj["Size"])

The filtering still happens on your side; S3 itself can only filter by prefix. Every object is still listed and transferred to you, just discarded afterwards.

Writing the loop yourself (any language)

If you call the API directly, or want to see what the paginator does, the loop is short:

kwargs = {"Bucket": "shop-repair-photos", "Prefix": "2026/"}
while True:
    resp = s3.list_objects_v2(**kwargs)
    for obj in resp.get("Contents", []):
        print(obj["Key"])
    if not resp.get("IsTruncated"):
        break
    kwargs["ContinuationToken"] = resp["NextContinuationToken"]

Keep every other parameter (bucket, prefix, delimiter) identical between calls; only the token changes. Tokens are opaque, so store them as they are, and treat them as short-lived: they are meant for continuing a listing now, not for bookmarking a position for next week. For a resumable position over long periods, save the last key you processed and restart with StartAfter set to it.

List all objects in JavaScript (AWS SDK v3)

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

const client = new S3Client({ region: "us-east-1" });
const paginator = paginateListObjectsV2(
  { client, pageSize: 1000 },
  { Bucket: "shop-repair-photos", Prefix: "2026/" }
);

let count = 0;
for await (const page of paginator) {
  for (const obj of page.Contents ?? []) {
    count++;
  }
}
console.log(count, "objects");

If you prefer to see the loop, the manual version with ListObjectsV2Command follows the same pattern as in Python:

import { ListObjectsV2Command } from "@aws-sdk/client-s3";

let token;
do {
  const res = await client.send(new ListObjectsV2Command({
    Bucket: "shop-repair-photos", Prefix: "2026/", Delimiter: "/", ContinuationToken: token,
  }));
  for (const p of res.CommonPrefixes ?? []) console.log("folder:", p.Prefix);
  for (const o of res.Contents ?? []) console.log("file:", o.Key, o.Size);
  token = res.IsTruncated ? res.NextContinuationToken : undefined;
} while (token);

page.Contents ?? [] plays the same role as Python's .get: empty pages have no Contents. If the client fails before listing anything with "could not load credentials," the problem is credentials, not S3; our JavaScript credentials guide covers that.

List all objects with the AWS CLI

The CLI pages automatically for s3api commands: by default it keeps calling until every object is listed, so list-objects-v2 returns everything, not just 1,000.

# All keys under a prefix, one per line
aws s3api list-objects-v2 --bucket shop-repair-photos --prefix 2026/10/ \
  --query "Contents[].Key" --output text

# Count and total size of everything in the bucket
aws s3 ls s3://shop-repair-photos --recursive --summarize --human-readable | tail -n 2

# Only the first 50, with a token to continue later
aws s3api list-objects-v2 --bucket shop-repair-photos --max-items 50

Useful options: --max-items caps the total returned and prints a NextToken you can pass back with --starting-token; --page-size changes how many objects each underlying call fetches (smaller pages help when a call times out); --no-paginate makes a single call, the API's raw behavior. The higher-level aws s3 ls is friendlier to read, while s3api gives you every field and the --query filter.

The --query option understands JMESPath, so you can get totals without any other tool:

# Number of objects and total bytes under a prefix
aws s3api list-objects-v2 --bucket shop-repair-photos --prefix 2026/10/ \
  --query "[length(Contents[]), sum(Contents[].Size)]"

# Keys and sizes of objects over 5 MB
aws s3api list-objects-v2 --bucket shop-repair-photos \
  --query "Contents[?Size > \`5000000\`].[Key, Size]" --output table

On an empty prefix, Contents is missing and these expressions print null rather than zero, which is the CLI's way of saying "nothing here."

List all objects in PowerShell

With the AWS Tools for PowerShell (the AWS.Tools.S3 module), Get-S3Object follows the continuation tokens for you:

Install-Module AWS.Tools.S3 -Scope CurrentUser
$objects = Get-S3Object -BucketName shop-repair-photos -KeyPrefix "2026/10/"
$objects.Count
($objects | Measure-Object -Property Size -Sum).Sum / 1GB
$objects | Where-Object Size -gt 5MB | Select-Object Key, Size, LastModified

Everything is collected into memory before you see it, which is fine for thousands of objects and slow for millions; for very large buckets, use the inventory approach described below. The CLI commands above also run unchanged in PowerShell, which many Windows users find simpler than installing the module.

Mixing the two works well too: let the CLI do the listing and PowerShell do the shaping, by asking for JSON and converting it:

$list = aws s3api list-objects-v2 --bucket shop-repair-photos --prefix "2026/10/" --output json | ConvertFrom-Json
$list.Contents | Sort-Object Size -Descending | Select-Object -First 10 Key, @{n="MB";e={[math]::Round($_.Size/1MB,1)}}

That prints the ten largest photos of October in megabytes, a quick way to spot the uploads that someone forgot to shrink.

Prefixes, delimiters and "folders"

S3 has no real folders. A key like 2026/10/R-1042-before.jpg is a single name that happens to contain slashes; the console just displays it as folders. Two request settings let you work with that structure:

  • Prefix limits the listing to keys starting with that text. Prefix="2026/10/" lists October's photos. Include the trailing slash, or 2026/1 would also match 2026/10/, 2026/11/ and 2026/12/.
  • Delimiter="/" groups everything below the next slash into CommonPrefixes, so you get the "subfolders" instead of every object inside them.
resp_pages = paginator.paginate(Bucket="shop-repair-photos", Prefix="2026/", Delimiter="/")
for page in resp_pages:
    for p in page.get("CommonPrefixes", []):
        print("folder:", p["Prefix"])      # 2026/01/, 2026/02/, ...
    for obj in page.get("Contents", []):
        print("file:  ", obj["Key"])       # objects directly in 2026/ only

This is how you build a folder browser: list one level with the delimiter, then list a chosen "folder" by using its prefix. Common prefixes count toward the 1,000 per page, so they page too.

Designing keys for listing. Because S3 can only filter by prefix, the way you name objects decides which listings are cheap. Putting the date first (2026/10/19/...) makes "everything from October" one prefix; putting the customer first (acme/2026/...) makes "everything for one customer" one prefix. Pick the order that matches the question you will ask most.

The permission you need: s3:ListBucket

Listing is authorized by s3:ListBucket, and it applies to the bucket, not to the objects. This policy is the classic working pair:

{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Action": "s3:ListBucket",
      "Resource": "arn:aws:s3:::shop-repair-photos",
      "Condition": {"StringLike": {"s3:prefix": ["2026/*", "2026/"]}}
    },
    {
      "Effect": "Allow",
      "Action": "s3:GetObject",
      "Resource": "arn:aws:s3:::shop-repair-photos/*"
    }
  ]
}
  • Bucket ARN for listing, bucket-slash-star for objects. Putting s3:ListBucket on arn:aws:s3:::shop-repair-photos/* does nothing, and listing fails with access denied. This mix-up is the most common S3 permission error there is.
  • There is no s3:ListObjects or s3:ListObjectsV2 action. Both API calls are allowed by s3:ListBucket.
  • The s3:prefix condition limits which "folders" a user may list, handy for giving each customer or team its own prefix.
  • Versioned buckets need s3:ListBucketVersions to list versions.

A side effect worth knowing: without s3:ListBucket, requesting a key that does not exist returns 403 Access Denied instead of 404 Not Found, because S3 will not tell someone who cannot list the bucket whether a key exists. A sudden wave of 403s on missing files often means the list permission was removed, not that the files were.

Counting objects and total size without listing everything

Listing ten million objects takes 10,000 API calls and a long time. When you only need totals or a full catalog, S3 has better tools:

ToolWhat it gives youFreshness
CloudWatch storage metricsNumberOfObjects and BucketSizeBytes per bucket and storage class, freeOnce a day
S3 console bucket metricsThe same numbers, as charts on the bucket's Metrics tabOnce a day
S3 Storage LensOrganization-wide usage and activity dashboards, with prefix-level detail in advanced tiersDaily
S3 InventoryA full list of every object (CSV, ORC or Parquet) delivered to a bucket, queryable with AthenaDaily or weekly
ListObjectsV2The exact current list, with filtering by prefixLive

For a dashboard number ("how many photos do we store?"), CloudWatch's daily metric is free and instant. For a full catalog of a huge bucket, S3 Inventory is far cheaper and faster than listing: you get a daily file, and you can query it with SQL in Athena. Live listing is for when you need the current state of one prefix right now.

Setting up S3 Inventory for a very large bucket

When a bucket holds millions or billions of objects and you need a complete list regularly, S3 Inventory writes it out for you instead of you listing it:

  1. Create (or choose) a destination bucket for the reports, in the same Region. Keeping reports separate from the data keeps them out of your own listings.
  2. Allow S3 to write there: the destination bucket's policy must let the S3 service (s3.amazonaws.com) put objects, limited to your source bucket and account. The console offers to add this when you set up the inventory.
  3. Create the inventory configuration on the source bucket: in the console, open the bucket's Management tab, then Inventory configurations, then Create. Choose a prefix or the whole bucket, daily or weekly, and the fields you want (size, last modified, storage class, encryption status and more).
  4. Pick Parquet or ORC as the format if you will query the reports with Athena; they are smaller and faster to query than CSV.
  5. Wait for the first report, which can take up to 48 hours to arrive. After that, reports appear on schedule with a manifest file listing their parts.
  6. Query it with Athena: create a table over the report location, then answer questions in SQL, such as total size per top-level prefix or every object over a size, without a single list call.

Inventory is billed per million objects listed in each report, a small amount for the visibility it gives. For a bucket the size of Jake's, it is overkill; for a company with a hundred million objects, it is the only sane way to know what is in there.

Making big listings faster and cheaper

Cost: LIST requests are billed per 1,000 requests (about half a cent per 1,000 in US East for S3 Standard), and each request returns up to 1,000 keys. Listing a million objects is a thousand requests, around half a cent; listing a billion is around five dollars, before your own compute time. It is rarely the expensive part, but repeated full listings of very large buckets add up, which is another reason to use Inventory.

Speed: a single listing is sequential, because each page needs the previous page's token. To go faster, list several prefixes in parallel. If your keys start with dates, customers or letters, give each worker its own prefix:

from concurrent.futures import ThreadPoolExecutor

def count_prefix(prefix):
    pages = s3.get_paginator("list_objects_v2").paginate(Bucket="shop-repair-photos", Prefix=prefix)
    return sum(len(p.get("Contents", [])) for p in pages)

months = [f"2026/{m:02d}/" for m in range(1, 13)]
with ThreadPoolExecutor(max_workers=12) as pool:
    print(sum(pool.map(count_prefix, months)))

boto3 clients are safe to share across threads for calls like this. Twelve parallel listings finish in roughly the time of the largest one.

Jake: "Twenty-three thousand photos. Is that a lot for S3?"

Ethan: "It's twenty-four list calls. S3 doesn't notice. The bucket could hold a billion and still not notice."

Listing versions and deleted objects

In a versioned bucket, ListObjectsV2 shows only the current version of each object, and hides objects whose latest version is a delete marker. To see every version, including "deleted" files that can still be restored, use ListObjectVersions, which pages with KeyMarker and VersionIdMarker (and its own paginator, list_object_versions):

for page in s3.get_paginator("list_object_versions").paginate(Bucket="shop-repair-photos", Prefix="2026/10/"):
    for v in page.get("Versions", []):
        print(v["Key"], v["VersionId"], v["IsLatest"])
    for d in page.get("DeleteMarkers", []):
        print("deleted:", d["Key"], d["VersionId"])

That is also the explanation when the console or a listing says a bucket is "empty" but deleting it fails: old versions and delete markers are still inside. To truly empty a versioned bucket, delete every version and delete marker (the console's Empty button does this), or add a lifecycle rule that expires noncurrent versions and removes expired delete markers, and let S3 clean up over the following days at no request cost.

Deleting many objects: the same 1,000 rule

Deleting has the same page size as listing: DeleteObjects removes up to 1,000 keys per call. The tools handle the batching for you:

  • CLI: aws s3 rm s3://shop-repair-photos/2019/ --recursive lists and deletes everything under the prefix, in batches. Add --dryrun first to see what would go.
  • Python: bucket.objects.filter(Prefix="2019/").delete() on the resource interface lists and deletes in batches of up to 1,000.
  • Huge prefixes: a lifecycle rule that expires objects under the prefix is often the best tool for millions of objects. S3 deletes them in the background, and you make no requests at all.

Delete requests themselves are free in S3; the listing needed to find the keys is what you pay for, which is one more reason lifecycle rules win at scale. And on a versioned bucket, a plain delete only adds a delete marker; the data stays (and is billed) until the noncurrent versions are removed too.

S3 limits: object size, object count and key names

LimitValue
Largest object50 TB (since December 2025)
Largest single PUT upload5 GB; larger objects need multipart upload
Multipart uploadUp to 10,000 parts, each 5 MB to 5 GB (the last part can be smaller)
Objects per bucketUnlimited
Total storage per bucketUnlimited
Key (object name) lengthUp to 1,024 bytes of UTF-8
Keys per ListObjectsV2 page1,000
Keys per DeleteObjects call1,000

Key name tips: letters, digits and ! - _ . * ' ( ) plus / are always safe. Spaces, &, +, = and non-ASCII characters work but need URL encoding in some tools, which is where "file not found" bugs come from: a key with a space may arrive as %20 or + in an event or URL. Backslashes, curly braces, carets and control characters cause the most trouble of all, so leave them out of key names. Our S3 event guide shows the encoding trap in Lambda triggers.

Content type, another common search, is not something listing returns: ListObjectsV2 gives key, size, date, ETag and storage class only. To read an object's Content-Type or custom metadata, call HeadObject on it, one call per object.

Common listing errors and fixes

SymptomCauseFix
Exactly 1,000 resultsOnly the first page readUse a paginator, or loop on NextContinuationToken
KeyError: 'Contents'Empty page or prefixpage.get("Contents", [])
AccessDenied on ListObjectsV2s3:ListBucket missing, or on bucket/*Allow it on the bucket ARN
Nothing listed, but objects existPrefix typo, missing or extra slash, wrong caseList without a prefix first and copy a real key's start
"Folders" missing from resultsUsing a delimiter: they are in CommonPrefixesRead CommonPrefixes as well as Contents
Deleted files still counted, or bucket will not deleteVersioning: old versions and delete markers remainUse ListObjectVersions
Listing is very slowMillions of keys, one sequential listingParallelize by prefix, or use S3 Inventory
NoSuchBucket or a redirect errorBucket name typo, or client in the wrong RegionCheck the name; set the bucket's Region on the client
Credentials errors before any listingNo AWS credentials foundSee our boto3 credentials guide

Frequently asked questions

How do I list more than 1,000 objects in S3?

Paginate: repeat ListObjectsV2 with the NextContinuationToken until IsTruncated is false, or use the SDK's paginator, which does it for you.

What is the maximum number of keys ListObjectsV2 returns?

1,000 per call. MaxKeys can be lower but not higher.

How do I list all objects in an S3 bucket with boto3?

Use s3.get_paginator("list_objects_v2").paginate(Bucket=...) and loop over page.get("Contents", []), or bucket.objects.all() with the resource interface.

How do I list S3 objects in JavaScript SDK v3?

Use paginateListObjectsV2({ client }, { Bucket, Prefix }) and a for await loop over the pages.

Does the AWS CLI list more than 1,000 objects?

Yes. aws s3api list-objects-v2 pages automatically and returns everything unless you use --max-items or --no-paginate.

How do I list S3 objects in PowerShell?

Get-S3Object -BucketName NAME -KeyPrefix PREFIX from the AWS.Tools.S3 module, which follows continuation tokens automatically.

What permission is needed to list S3 objects?

s3:ListBucket on the bucket ARN, arn:aws:s3:::bucket-name, not on bucket-name/*. There is no s3:ListObjects action.

What is the maximum object size in S3?

50 TB per object (raised from 5 TB in December 2025). A single PUT can upload up to 5 GB; larger objects use multipart upload.

How many objects can an S3 bucket hold?

An unlimited number, with unlimited total storage.

What is the maximum S3 key length?

1,024 bytes of UTF-8 encoded text.

How do I list folders in an S3 bucket?

Use Delimiter="/" with an optional Prefix. The folders are returned in CommonPrefixes, the files at that level in Contents.

How do I count objects in a large S3 bucket quickly?

Use the free daily CloudWatch metric NumberOfObjects, the bucket's Metrics tab, S3 Storage Lens, or S3 Inventory instead of listing.

What is the difference between ListObjects and ListObjectsV2?

V2 pages with continuation tokens and supports StartAfter; the original uses markers. Both return up to 1,000 keys. Use V2 for new code.

Why does S3 return 403 instead of 404 for a missing object?

Without s3:ListBucket permission, S3 hides whether the key exists and returns Access Denied.

Does ListObjectsV2 return content type?

No. It returns key, size, last modified, ETag and storage class. Use HeadObject for Content-Type and metadata.

How much do S3 LIST requests cost?

They are billed per 1,000 requests, about half a cent per 1,000 for S3 Standard in US East, each returning up to 1,000 keys.

For readers preparing for an AWS certification

We have been covering AWS certifications alongside our fixes, so here is a short extra for readers studying for one. If you only came for the fix, you already have it; feel free to skip this part.

Exams that test this topic: Developer – Associate (DVA-C03 from December 1, 2026) • Solutions Architect – Associate (SAA-C03) • CloudOps Engineer – Associate (SOA-C03).

Here are the exam-style questions this topic tends to raise, with the reasoning you need to answer them:

1. A script that lists an S3 bucket always returns exactly 1,000 objects. What is wrong?

It reads only the first page; ListObjectsV2 must be repeated with the continuation token (or an SDK paginator used).

2. Which IAM action allows listing the objects in an S3 bucket, and on which resource?

s3:ListBucket, on the bucket ARN (arn:aws:s3:::bucket-name).

3. A team needs a daily list of all objects in a bucket with billions of objects, queryable with SQL. What do you use?

S3 Inventory reports, queried with Amazon Athena.

4. What is the largest object S3 can store, and the largest single PUT upload?

50 TB per object (since December 2025); 5 GB per single PUT, with multipart upload for larger objects.

5. Where can you see the number of objects in a bucket without listing it?

The free daily Amazon CloudWatch storage metrics NumberOfObjects and BucketSizeBytes (or S3 Storage Lens).

6. Millions of old objects under one prefix must be removed at the lowest cost. What do you use?

An S3 Lifecycle expiration rule for that prefix.

7. A versioned bucket appears empty but cannot be deleted. Why?

Noncurrent versions and delete markers remain; they must be deleted too.

Exam codes and dates change often. Our AWS certification changes page keeps track of what is current.

πŸ“š ALSO READ

Where to go next, from S3 events to other AWS paging traps:

📌 Bookmark this; the code for your language and the limits table are the parts you will come back for.

The fixed script counted 23,481 photos, 61 GB in all, and listed them by month in parallel in about two seconds. Ethan added the bucket's NumberOfObjects metric to the shop's little dashboard so nobody would need the script for the headline number again. Jake looked at the total and asked whether they should delete the oldest ones. "They cost about a dollar fifty a month," Ethan said. "Some of those photos have settled warranty arguments. Keep them."

📌 If you keep one line from this page

ListObjectsV2 returns 1,000 keys per call, so use the SDK's paginator (or loop on NextContinuationToken until IsTruncated is false), filter with Prefix, group with Delimiter, and grant s3:ListBucket on the bucket ARN itself.

Objects up to 50 TB · 5 GB per single PUT · unlimited objects per bucket · keys up to 1,024 bytes · counts: CloudWatch NumberOfObjects.

Revision note. Written October 19, 2026. If a listing returns exactly 1,000 of anything, it is not a coincidence; it is page one.

Related