Cloudflare R2 and AWS's SDK for .NET

Cloudflare R2 and AWS's SDK for .NET
Photo by Jessica Johnston / Unsplash


If you've tried to use the AWSSDK.S3 package for interacting with Cloudflare R2 from .NET, you've likely ran into this error when uploading a file using PutObject:


This is since R2 doesn't support Streaming SigV4 which is used in chunked uploading. The fix for this is pretty simple, and we just need to disable payload signing within the PutObjectRequest.

class Example {
  private static IAmazonS3 s3Client;

  public static void Main(string[] args) {
    var accessKey = "<ACCESS-KEY>";
    var secretKey = "<SECRET-KEY>";
    var credentials = new BasicAWSCredentials(accessKey, secretKey);
    s3Client = new AmazonS3Client(credentials, new AmazonS3Config {
      ServiceURL = "https://<ACCOUNT-ID>",


  static async Task PutObject() {
    var request = new PutObjectRequest {
      FilePath = @ "/Users/kian/Downloads/example.img",
      BucketName = "sdk-example",
      DisablePayloadSigning = true

    var response = await s3Client.PutObjectAsync(request);

    Console.WriteLine("ETag: {0}", response.ETag);

Presigned URLs - SigV2 authorization is not supported

By default, the AWSSDK.S3 package will default to using SigV2 signing for presigned URLs - this is pretty old and not supported by R2. To fix this, we'll need to tell the package to use SigV4.

static async Task GeneratePresignedPutObject()
	AWSConfigsS3.UseSignatureVersion4 = true;
	var presign = new GetPreSignedUrlRequest
		BucketName = "sdk-example",
		Key = "dog.png",
		Verb = HttpVerb.PUT,
		Expires = DateTime.Now.AddDays(7),
	var presignUrl = s3Client.GetPreSignedURL(presign);

Whilst I'm definitely not an expert with C#, hopefully this unblocks you and you can get back to developing your project!