Getting SignatureDoesNotMatch when using Custom Csn (Spaces)

We have been using DO Spaces for a few month for our production app. I’m using the following npm library to generated presigned urls: @aws-sdk/s3-request-presigner

After some complaints, today I spent time on migrating to a custom CDN. The problem is that when I setup my CDN with my own domain, I get the following error:

<Error><Code>SignatureDoesNotMatch</Code><Message>The request signature we calculated does not match the signature you provided. Check your key and signing method.</Message><Resource>tangible-platform-files-staging/deals-fund/3786/sample.pdf</Resource><RequestId>not available</RequestId></Error>

The only change between a working link and the message above is changing my env variables to: DO_SPACES_ENDPOINT (my new domain: http://<example>.app) DO_SPACES_BUCKET (my new subdomain)

How do I correctly set up the presigned when using a Custom CDN?

const client = new S3Client({
    region: process.env.DO_SPACES_REGION,
    endpoint: process.env.DO_SPACES_ENDPOINT,
    credentials: {
      accessKeyId: process.env.DO_SPACES_KEY || 'error',
      secretAccessKey: process.env.DO_SPACES_SECRET || 'error',

  const fileKey = <value>;
  const bucketParams = {
    Bucket: process.env.DO_SPACES_BUCKET,
    Key: fileKey,

  const command = new GetObjectCommand(bucketParams);
  const presSignedUrl = await getSignedUrl(client, command, { expiresIn: 3600 });
  return presSignedUrl;

Thank you

Submit an answer

This textbox defaults to using Markdown to format your answer.

You can type !ref in this text area to quickly search our full set of tutorials, documentation & marketplace offerings and insert the link!

Sign In or Sign Up to Answer

These answers are provided by our Community. If you find them useful, show some love by clicking the heart. If you run into issues leave a comment, or add your own answer to help others.

Solution found!

Not sure where this post* found this text in the documentation, but it worked:

You can use presigned URLs with the Spaces CDN. To do so,configure your SDK or S3 tool to use the non-CDN endpoint, generate a presigned URL for a GetObject request, then modify the hostname in the URL to be the CDN hostname (<space-name>.<region>, unless the Space uses a custom hostname).

I assume that the reasoning for this is that DO uses some magic links, i.e. adds the region in the original endpoint. A bit hacky, but happy to have found a solution

In code, this means:

// To use DO CDN, you need to generate a signed url with the original endpoint
// and then swap out the domain
const modifiedUrl = process.env.DO_SPACES_CDN + presSignedUrl.split('.com')[1];]


Try DigitalOcean for free

Click below to sign up and get $200 of credit to try our products over 60 days!

Sign up

Featured on Community

Get our biweekly newsletter

Sign up for Infrastructure as a Newsletter.

Hollie's Hub for Good

Working on improving health and education, reducing inequality, and spurring economic growth? We'd like to help.

Become a contributor

Get paid to write technical tutorials and select a tech-focused charity to receive a matching donation.

Welcome to the developer cloud

DigitalOcean makes it simple to launch in the cloud and scale up as you grow — whether you're running one virtual machine or ten thousand.

Learn more
DigitalOcean Cloud Control Panel