September 30, 2026 · 5 min read

How to make a Cloudflare R2 bucket public

R2 buckets are private by default. Nobody can read a file without signed API requests until you explicitly give the bucket a public address. There are two ways to do that, and they can be used side by side.

Option 1: connect a custom domain (recommended)

A custom domain serves the bucket through Cloudflare's network with caching, and lets you use WAF rules or Cloudflare Access later. The domain has to be a zone in the same Cloudflare account as the bucket (a full or partial CNAME setup both work).

  1. In the Cloudflare dashboard, go to R2 Object Storage and select your bucket.
  2. Open Settings and find Custom Domains, then select Add.
  3. Enter a subdomain such as files.example.com and select Continue.
  4. Review the DNS record Cloudflare will create and select Connect Domain.

The status changes from Initializing to Active within a few minutes. After that, an object with the key 2026/09/report.pdf is available at https://files.example.com/2026/09/report.pdf.

Option 2: enable the r2.dev Public Development URL

For a quick test, R2 can give the bucket a Cloudflare-managed address:

  1. Open the bucket's Settings.
  2. Under Public Development URL, select Enable.
  3. Type allow to confirm and select Allow.

The bucket is now reachable at https://pub-<id>.r2.dev/<key>. Cloudflare rate-limits this URL and says it is meant for development, so switch to a custom domain before you share links widely. Pointing your own CNAME at the r2.dev address is not supported.

What public access does and doesn't expose

  • Read only. Public access lets anyone read objects whose key they know. Uploads and deletes still need API credentials.
  • No directory listing. Visiting the root of the domain doesn't list the bucket. Random object names make links hard to guess.
  • Everything in the bucket. Access is per bucket, not per folder. Keep private files in a separate bucket.
  • Caching. By default, Cloudflare caches only certain file extensions. Add a cache rule if you want every file type cached.

Fixing Access Denied on R2 links

If a link returns Access Denied, 401 or 403, check these in order:

  1. The link uses your custom domain or r2.dev URL, not <account-id>.r2.cloudflarestorage.com. That host is the S3 API and always needs a signature.
  2. The custom domain shows Active and access to the bucket is Allowed in the bucket's settings.
  3. The key in the URL matches the object exactly, including folders and letter case.

Common questions

Is it safe to make an R2 bucket public?

It's safe for files you intend to share. Anyone with a link can read that file, but they can't list the bucket, upload or delete. Keep private data in a different bucket.

Does a public R2 bucket cost more?

No. R2 doesn't charge for egress, so public downloads don't add bandwidth costs. Reads count as Class B operations, which have a free monthly allowance.

Can I make only one folder public?

Not with R2's public access, which applies to the whole bucket. Use a separate bucket, or keep the bucket private and share presigned URLs.