aws-sdk-js
You must generate an Access Key before getting started. All examples will utilize access_key_id and access_key_secret variables which represent the Access Key ID and Secret Access Key values you generated.
If you are interested in the newer version of the AWS JavaScript SDK visit this dedicated aws-sdk-js-v3 example page.
JavaScript or TypeScript users may continue to use the aws-sdk ↗ npm package as per normal. You must pass in the R2 configuration credentials when instantiating your S3 service client:
import S3 from "aws-sdk/clients/s3.js";
const s3 = new S3({ // Provide your Cloudflare account ID endpoint: `https://${ACCOUNT_ID}.r2.cloudflarestorage.com`, // Retrieve your S3 API credentials for your R2 bucket via API tokens (see: https://developers.cloudflare.com/r2/api/tokens) accessKeyId: `${ACCESS_KEY_ID}`, secretAccessKey: `${SECRET_ACCESS_KEY}`, signatureVersion: "v4",});
console.log(await s3.listBuckets().promise());//=> {//=> Buckets: [//=> { Name: 'user-uploads', CreationDate: 2022-04-13T21:23:47.102Z },//=> { Name: 'my-bucket', CreationDate: 2022-05-07T02:46:49.218Z }//=> ],//=> Owner: {//=> DisplayName: '...',//=> ID: '...'//=> }//=> }
console.log(await s3.listObjects({ Bucket: "my-bucket" }).promise());//=> {//=> IsTruncated: false,//=> Name: 'my-bucket',//=> CommonPrefixes: [],//=> MaxKeys: 1000,//=> Contents: [//=> {//=> Key: 'cat.png',//=> LastModified: 2022-05-07T02:50:45.616Z,//=> ETag: '"c4da329b38467509049e615c11b0c48a"',//=> ChecksumAlgorithm: [],//=> Size: 751832,//=> Owner: [Object]//=> },//=> {//=> Key: 'todos.txt',//=> LastModified: 2022-05-07T21:37:17.150Z,//=> ETag: '"29d911f495d1ba7cb3a4d7d15e63236a"',//=> ChecksumAlgorithm: [],//=> Size: 279,//=> Owner: [Object]//=> }//=> ]//=> }You can also generate presigned links that can be used to share public read or write access to a bucket temporarily.
// Use the expires property to determine how long the presigned link is valid.console.log(await s3.getSignedUrlPromise("getObject", { Bucket: "my-bucket", Key: "dog.png", Expires: 3600,}),);// You can also create links for operations such as putObject to allow temporary write access to a specific key.// Specify ContentType to restrict uploads to a specific file type.console.log( await s3.getSignedUrlPromise("putObject", { Bucket: "my-bucket", Key: "dog.png", Expires: 3600, ContentType: "image/png", }),);https://my-bucket.<ACCOUNT_ID>.r2.cloudflarestorage.com/dog.png?X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Credential=<credential>&X-Amz-Date=<timestamp>&X-Amz-Expires=3600&X-Amz-SignedHeaders=host&X-Amz-Signature=<signature>https://my-bucket.<ACCOUNT_ID>.r2.cloudflarestorage.com/dog.png?X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Credential=<credential>&X-Amz-Date=<timestamp>&X-Amz-Expires=3600&X-Amz-SignedHeaders=content-type%3Bhost&X-Amz-Signature=<signature>You can use the link generated by the putObject example to upload to the specified bucket and key, until the presigned link expires. When using a presigned URL with ContentType, the client must include a matching Content-Type header in the request.
curl -X PUT "https://my-bucket.<ACCOUNT_ID>.r2.cloudflarestorage.com/dog.png?X-Amz-Algorithm=..." \ -H "Content-Type: image/png" \ --data-binary @dog.pngWhen generating presigned URLs for uploads, you can limit abuse and misuse by:
-
Restricting Content-Type: Specify the allowed content type in the presigned URL parameters. The upload will fail if the client sends a different
Content-Typeheader. -
Configuring CORS: Set up CORS rules on your bucket to control which origins can upload files. Configure CORS via the Cloudflare dashboard ↗ by adding a JSON policy to your bucket settings:
[ { "AllowedOrigins": ["https://example.com"], "AllowedMethods": ["PUT"], "AllowedHeaders": ["Content-Type"], "ExposeHeaders": ["ETag"], "MaxAgeSeconds": 3600 }]Then generate a presigned URL with a Content-Type restriction:
const putUrl = await s3.getSignedUrlPromise("putObject", { Bucket: "my-bucket", Key: "user-upload.png", Expires: 3600, ContentType: "image/png",});When a client uses this presigned URL, they must:
- Make the request from an allowed origin (enforced by CORS)
- Include the
Content-Type: image/pngheader (enforced by the signature)
Was this helpful?
- Resources
- API
- New to Cloudflare?
- Directory
- Sponsorships
- Open Source
- Support
- Help Center
- System Status
- Compliance
- GDPR
- Company
- cloudflare.com
- Our team
- Careers
- © 2025 Cloudflare, Inc.
- Privacy Policy
- Terms of Use
- Report Security Issues
- Trademark
-