Uploading Files to Cloudflare R2 with AWS SDK for JavaScript v3

Uploading Files to Cloudflare R2 with AWS SDK for JavaScript v3

Cloudflare R2 offers a compelling storage solution that's fully compatible with the S3 API, making it an excellent choice for developers looking for cost-effective object storage. One of the significant advantages of using Cloudflare R2 is its promise of zero egress fees, which can drastically reduce costs for applications that serve a large amount of data.

In this post, we'll explore how to upload files to Cloudflare R2 using the AWS SDK for JavaScript v3, the latest iteration of the SDK that offers a modular, more efficient way to interact with AWS services.

Why Use AWS SDK v3?

The AWS SDK for JavaScript v3 is a rewrite of v2 with some key improvements:

  • Modular Architecture: You can now install only the packages you need, reducing the size of your project.
  • First-class TypeScript support: Making it easier to use in TypeScript projects.
  • Improved API for Promises: Simplifies the code, especially when using async/await.


Before we start, make sure you have:

  • Node.js installed on your development machine.
  • An R2 bucket created in your Cloudflare account.
  • Your R2 Access and Secret Keys.

Step 1: Setting Up Your Project

First, initialize a new Node.js project and install the necessary AWS SDK v3 packages:

mkdir r2-upload-example
cd r2-upload-example
npm init -y
npm install @aws-sdk/client-s3 @aws-sdk/lib-storage

Step 2: Configuring the S3 Client

Create a new file s3Client.js to configure and export the S3 client tailored for R2:

const { S3Client } = require('@aws-sdk/client-s3');

const REGION = "auto"; // R2 does not require a region, but AWS SDK expects one
const s3Client = new S3Client({
  region: REGION,
  endpoint: "https://<your-r2-endpoint>",
  credentials: {
    accessKeyId: "<your-access-key-id>",
    secretAccessKey: "<your-secret-access-key>",
  forcePathStyle: true, // Important for R2 compatibility

module.exports = { s3Client };

Replace <your-r2-endpoint>, <your-access-key-id>, and <your-secret-access-key> with your actual Cloudflare R2 endpoint and credentials.

Step 3: Uploading Files to R2

Now, let's write the code to upload files. Create uploadFile.js:

const { s3Client } = require('./s3Client');
const { Upload } = require('@aws-sdk/lib-storage');
const fs = require('fs');

async function uploadFile(filePath, bucketName, key) {
  const fileStream = fs.createReadStream(filePath);

  try {
    const uploader = new Upload({
      client: s3Client,
      params: {
        Bucket: bucketName,
        Key: key,
        Body: fileStream,

    uploader.on('httpUploadProgress', (progress) => {
      console.log(`Upload progress: ${progress.loaded} of ${progress.total} bytes`);

    await uploader.done();
    console.log(`File uploaded: ${key}`);
  } catch (err) {
    console.error("Error uploading file:", err);

module.exports = { uploadFile };

Step 4: Putting It All Together

Finally, create index.js to use the uploadFile function:

const { uploadFile } = require('./uploadFile');

const bucketName = '<your-bucket-name>';
const filePath = 'path/to/your/file.txt';
const key = 'your/file/key.txt';

uploadFile(filePath, bucketName, key)
  .then(() => console.log("File uploaded successfully"))
  .catch((err) => console.error("Failed to upload file:", err));

Make sure to replace <your-bucket-name>, path/to/your/file.txt, and your/file/key.txt with your bucket name, local file path, and desired key (file name in R2) respectively.


You've now learned how to configure the AWS SDK for JavaScript v3 to upload files to Cloudflare R2, leveraging the modular nature of the SDK for more efficient code. Cloudflare's R2 storage, with its compatibility with the S3 API and the advantage of no egress fees, offers an attractive solution for storing and serving content.

Happy coding!

Did you find this article valuable?

Support Ravi Prakash by becoming a sponsor. Any amount is appreciated!