Signed PUT Url for NodeJS

Posted December 10, 2017 10.7k views

I heard you guys only support v2 for putObject signed urls. Which node.js clients should I use to create a signed url so I can upload files on the browser?

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.

Submit an Answer
2 answers

Support for v4 pre-signed URLs is in the works, but you can use v2 signatures with the AWS SDK as well. Depending on the version of the SDK you have installed, it maybe in use by default. (The latest version should when using a custom endpoint. Some older versions used v4 by default everywhere, but this change was reverted in version 2.152.0)

If needed, you can force the signature version when configuring your client:

const s3 = new AWS.S3({
    endpoint: spacesEndpoint,
    accessKeyId: 'YOURACCESSKEY',
    secretAccessKey: 'YOURSECRETKEY',
    signatureVersion: 'v2'

Here’s a quick example for generating a pre-signed putObject URL with a v2 signature:

const AWS = require('aws-sdk')

const spacesEndpoint = new AWS.Endpoint('');
const s3 = new AWS.S3({
    endpoint: spacesEndpoint,
    accessKeyId: 'YOURACCESSKEY',
    secretAccessKey: 'YOURSECRETKEY',
    signatureVersion: 'v2'

var space = 'my-space-name'
var key = 'my-file-name'
var expireSeconds = 60 

s3.getSignedUrl('putObject', {
    Bucket: space,
    Expires: expireSeconds,
    Key: key
}, function (err, url) {
  • @asb thank you for the reply. When I try using this code on the latests aws-sdk I get an error saying only v3 and v4 support signature urls. Is there a specific version you are using?

    • Hey @vallelungabrian! I currently have 2.169.0 installed which should be the latest version. Can you share the exact error message you’re seeing?

      • I was able to generate the signed url fine with that version but when I try uploading the file I get this error:


        for this url
        • Looking at the docs for getSignedUrl, there is this important note:

          Not all operation parameters are supported when using pre-signed URLs. Certain parameters, such as SSECustomerKey, ACL, Expires, ContentLength, or Tagging must be provided as headers when sending a request.

          So the key here is that the headers need to match the signature. For instance, your pre-signed URL has x-amz-acl=private So the upload must contain that header. Say my URL is:


          Using curl for example purposes, my upload must look like:

          curl -X PUT -T "hello.html" \
            -H "x-amz-acl: private" \

          Without including the header, I get the same error as you. With it, the upload succeeds. The same goes for things like content-type.

          • Isn’t that silly that Digital Ocean doesn’t support placing them as a get variable? It basically means I can’t easily give this url to a third party and they blindly enter the url for upload. Now I have to make sure they set the headers too which adds more overhead of support. What was the logic behind this?

          • I definitely agree that it isn’t ideal. Our initial focus with the Spaces API was to ensure that it was inter-operable with the S3 API so that users could continue using the same libraries and tools that they’re already comfortable with. So we’ve inherited some warts there. This kind of feedback will help us as we start thinking about ways to make the Spaces API as intuitive as our others.

          • I was stuck with this header matching enforcement for few hours last night as my code is working on s3 (before finding this post in the morning)

            amazon s3 doesn’t enforce matching x-amz-acl in the header requirement, so i hope digital ocean can update the library or output more descriptive error message in the reply

by Tania Rascia
Create a Node.js app to upload a file to your DigitalOcean Space