Server Fault is a question and answer site for system and network administrators. It's 100% free, no registration required.

Sign up
Here's how it works:
  1. Anybody can ask a question
  2. Anybody can answer
  3. The best answers are voted up and rise to the top

I have been trying to use the AWS "official" command line tool to test out the recently announced multi-object delete. Here is what I have done:

First, I tested out the with a set of credentials without a hitch:

$ --id=s3 --|xmllint --format -
      % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                     Dload  Upload   Total   Spent    Left  Speed
    100   884    0   884    0     0   4399      0 --:--:-- --:--:-- --:--:--  5703
    <?xml version="1.0" encoding="UTF-8"?>
    <ListBucketResult xmlns="">

Then, I following the's usage instructions: --help
Usage /usr/local/bin/ --id friendly-name (or AWSAccessKeyId) [options] -- [curl-options] [URL]
  --key SecretAccessKey       id/key are AWSAcessKeyId and Secret (unsafe)
  --contentType text/plain    set content-type header
  --acl public-read           use a 'canned' ACL (x-amz-acl header)
  --contentMd5 content_md5    add x-amz-content-md5 header
  --put <filename>            PUT request (from the provided local file)
  --post [<filename>]         POST request (optional local file)
  --copySrc bucket/key        Copy from this source key
  --createBucket [<region>]   create-bucket with optional location constraint
  --head                      HEAD request
  --debug                     enable debug logging
 common curl options:
  -H 'x-amz-acl: public-read' another way of using canned ACLs
  -v                          verbose logging

Then, I tried the following, and always got back error. I would appreciated it very much if someone could point out where I made a mistake?

$ --id=s3 --post multi_delete.xml --
<?xml version="1.0" encoding="UTF-8"?>
<Error><Code>SignatureDoesNotMatch</Code><Message>The request signature we calculated does not match the signature you provided. Check your key and signing method.</Message><StringToSignBytes>50 4f 53 54 0a 0a 0a 54 68 75 2c 20 30 35 20 41 70 72 20 32 30 31 32 20 30 30 3a 35 30 3a 30 38 20 2b 30 30 30 30 0a 2f 7a 65 74 74 61 72 2d 74 2f 3f 64 65 6c 65 74 65</StringToSignBytes><RequestId>707FBE0EB4A571A8</RequestId><HostId>mP3ZwlPTcRqARQZd6gU4UvBrxGBNIVa0VVe5p0rqGmq5hM65RprwcG/qcXe+pmDT</HostId><SignatureProvided>edkNGuugiSFe0ku4eGzkh8kYgHw=</SignatureProvided><StringToSign>POST

Thu, 05 Apr 2012 00:50:08 +0000

The file multi_delete.xml contains the following:

cat multi_delete.xml
<?xml version="1.0" encoding="UTF-8"?>
      <VersionId> </VersionId>>
      <VersionId> </VersionId>

Thanks for any help!


share|improve this question
up vote 0 down vote accepted

This worked for me (Amazon Linux AMI v2012.03; us-east-1):

Download and extract latest


Make executable:

cd s3-curl
chmod +x s3-curl

Create a credential file (.s3curl):

%awsSecretAccessKeys = (
    # personal account
    personal => {

Restrict credentials permissions:

chmod 600 .s3curl

Create POST request body (multidelete.xml):

<?xml version="1.0" encoding="UTF-8"?>

Calculate base64 encoded MD5 sum of POST body:

cat multidelete.xml | openssl dgst -md5 -binary | base64

Construct request, and enable verbose display for curl (I have included the command above inline, instead of the MD5 sum itself):

./ --id=personal --post multidelete.xml --contentMd5 `cat multidelete.xml | openssl dgst -md5 -binary | base64` -- -v


Trying to use PUT (instead of POST) results in a 405 Method Not Allowed:

<?xml version="1.0" encoding="UTF-8"?>
<Error><Code>MethodNotAllowed</Code><Message>The specified method is not allowed against this resource.</Message><ResourceType>MULTI_OBJECT_DELETE</ResourceType><Method>PUT</Method><RequestId>XXXXXXXXXXXXXXXX</RequestId><HostId>XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX</HostId></Error>

Trying to use POST without the Content-MD5 header results in a 400 Bad Request:

<?xml version="1.0" encoding="UTF-8"?>
<Error><Code>InvalidRequest</Code><Message>Missing required header for this request: Content-MD5</Message><RequestId>XXXXXXXXXXXXXXXX</RequestId><HostId>XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX</HostId></Error>

Using a hexadecimal md5 sum results in a 400 Bad Request:

<?xml version="1.0" encoding="UTF-8"?>
<Error><Code>InvalidDigest</Code><Message>The Content-MD5 you specified was invalid.</Message><RequestId>XXXXXXXXXXXXXXXX</RequestId><Content-MD5>703f10f0a4ee8393fc1e3ee8c8e5bc89</Content-MD5><HostId>XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX</HostId></Error>

A valid request/response looks like:

./ --id=personal --post multidelete.xml --contentMd5 `cat multidelete.xml | openssl dgst -md5 -binary | base64` -- -v
* About to connect() to port 80 (#0)
*   Trying connected
* Connected to ( port 80 (#0)
> POST /BUCKET?delete HTTP/1.1
> User-Agent: curl/7.19.7 (i386-redhat-linux-gnu) libcurl/7.19.7 NSS/ zlib/1.2.3 libidn/1.18 libssh2/1.2.2
> Host:
> Accept: */*
> Date: Thu, 05 Apr 2012 01:50:53 +0000
> Content-MD5: cD8Q8KTug5P8Hj7oyOW8iQ==
> Content-Length: 172
> Expect: 100-continue
< HTTP/1.1 100 Continue
< HTTP/1.1 200 OK
< x-amz-request-id: XXXXXXXXXXXXXXXX
< Date: Thu, 05 Apr 2012 01:50:55 GMT
< Content-Type: application/xml
< Transfer-Encoding: chunked
< Server: AmazonS3
<?xml version="1.0" encoding="UTF-8"?>
* Connection #0 to host left intact
* Closing connection #0
<DeleteResult xmlns=""><Deleted><Key>file1.txt</Key></Deleted><Deleted><Key>file2.txt</Key></Deleted></DeleteResult>

Using <Quiet>true</Quiet> results in the following body returned from a successful deletion:

<DeleteResult xmlns=""></DeleteResult>

The only way I could replicate your error message was by using an invalid secret key in my credentials file. However, with that the bucket listing did not work either, unlike yours.

share|improve this answer

Your Answer


By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.