Table of Contents

Please enable javascript to display TOC.

Sign Amazon Product Advertising API REST Requests with PHP and Python

published: 08 May 2009, last updated: 29 Dec 2012

The Amazon® Product Advertising API (formerly know as Amazon Associates Webservices) can be used to access Amazon's product data for advertising purposes. By August 15, 2009, all calls to the API must be signed (with HMAC and SHA-256) to authenticate the request. I have written a PHP and a Python function which build authenticated requests.

Since its publication, soon after the announcement from Amazon, the PHP script has been successfully used in production by dozens of websites (including my own). Most other scripts that you will find on the internet are probably based on this one.

Download the Code

If you use this script, a link back to this website would be appreciated but is not required.

PHP Function 2.0 (1.5 kB)

It uses hash_hmac and requires PHP 5 >= 5.1.2 See below for a hash_hmac implementation for older versions of PHP.

Python Function 1.0 (1.5 kB)

Has been tested with Python 2.5 and 2.6 (but should work with newer versions, too) and has been tested on Google App Engine.

Older Versions

PHP Function 1.0 (1.6 kB)

It uses hash_hmac and requires PHP 5 >= 5.1.2 See below for a hash_hmac implementation for older versions of PHP.

Other Downloads

hash_hmac for PHP 4 (0.6 kB)

Implements the hash_hmac function for PHP 4 and PHP 5 < 5.1.2 This uses the free SHA-256 library for PHP 4

SHA256 for PHP 4 (4.9 kB)

Implements the sha256 function for older PHP versions. This is an unmodified version that was downloaded from

PHP Documentation


The function signs your request and returns a URL.

aws_signed_request($region, $params, $public_key, $private_key, $associate_tag=NULL, $version='2011-08-01')



Amazon region ("ca", "com", "", "de", "fr" or "")


An associative array of parameters with the parameter names as keys.


Your public key.


Your private key.


Optional Associate Tag. If NULL, you have to add your AssociateTag to the $params array.


Optional API version.

Return Values

Returns the signed URL as a string.


Here is a simple example. You have to replace $public_key, $private_key and $associate_tag with your own values.



$public_key = '********';
$private_key = '********';
$associate_tag = '********';

// generate signed URL
$request = aws_signed_request('com', array(
        'Operation' => 'ItemLookup',
        'ItemId' => 'B008GG93YE',
        'ResponseGroup' => 'Small'), $public_key, $private_key, $associate_tag);

// do request (you could also use curl etc.)
$response = @file_get_contents($request);
if ($response === FALSE) {
    echo "Request failed.\n";
} else {
    // parse XML
    $pxml = simplexml_load_string($response);
    if ($pxml === FALSE) {
        echo "Response could not be parsed.\n";
    } else {
        if (isset($pxml->Items->Item->ItemAttributes->Title)) {
            echo $pxml->Items->Item->ItemAttributes->Title, "\n";


The output of this script should be:

Kindle, 6" E Ink Display, Wi-Fi

Python Documentation


The function signs your request and returns a URL.

aws_signed_request(region, params, public_key, private_key, associate_tag=None, version='2011-08-01')



Amazon region ("ca", "com", "", "de", "fr" or "")


A dictionary of parameters with the parameter names as keys.


Your public key.


Your private key.


Optional Associate Tag. If None, you have to add your AssociateTag to the params dict.


Optional API version.

Return Values

Returns the signed URL as a string.


Here is a simple example. You have to replace public_key, private_key and associate_tag with your own values.


from aws_signed_request import aws_signed_request
import urllib
from xml.dom import minidom

public_key = '********'
private_key = '********'
associate_tag = '********';

# generate signed URL
request = aws_signed_request('com', {
        'Operation': 'ItemLookup',
        'ItemId': 'B008GG93YE',
        'ResponseGroup': 'Small'}, public_key, private_key, associate_tag)

# do request
    response_obj = urllib.urlopen(request);
except IOError:
    print "Request failed."
    response =
    pxml = minidom.parseString(response)
    items = pxml.getElementsByTagName('Title')
    print items[0].firstChild.nodeValue

The output of this script should be:

Kindle, 6" E Ink Display, Wi-Fi


If you have questions regarding these scripts or if you need help with specific problems, do not hesitate to contact me.

Comments (207)

  1. enoxrh on 10 May 2009

    thank your for your's very help to work with SHA algorithm

    1. MUHAMMAD SALMAN on 12 Oct 2010

      ENOXRH , my script is not working , do you plz share with me your script

  2. Mario on 11 May 2009

    Thanks, saved me some time typing (used most of it)! Note, per the docs, the host should be:

    1. Ulrich Mierendorff on 11 May 2009

      Yes, in the documentation they are using, but in the AWS forums, people say ecs.amazonaws is better. But both will work...

      1. Ulrich Mierendorff on 30 Nov 2009

        Wrong information! ecs.amazonaws does not work with "", but does. So the latter is better...

  3. tom on 14 May 2009

    why is str_replace("%7E", "~", rawurlencode($s)) required instead of urlencode($s)?

    1. Ulrich Mierendorff on 14 May 2009

      Amazon requires that you encode the parameters as specified in <a href="" target="_blank">RFC 3986</a>. The space character, for example, has to be encoded as "%20" and not as "+" like urlencode() does. In addition, the following characters are reserved and may not be encoded: "-", ".", "_" and "~". rawurlencode() encodes "~" as "%7E" so we have to replace it.

  4. vanessa on 24 May 2009


    i am testing the signature function on a Server with PHP 4.0. The  hash_hmac function is required > PHP 5.1. What is the function for PHP < 5.1?

    1. Ulrich Mierendorff on 24 May 2009

      If you have access to the mhash function you could use it: <a href="" target="_blank"></a>

      If not, you have to build your own hmac function. On the website I have mentioned above, someone submitted a hmac function for md5. You could modify that by replacing the md5 function with a sha256 function (for example this one: <a href="" target="_blank"></a> and by enclosing the return value with pack("H*", ...).

      1. vanessa on 24 May 2009


        thanks for your info. Is this the only way to do that in PHP 4??

        1. Ulrich Mierendorff on 24 May 2009

          Yes, I think it is the only way. But creating the hmac function as described is not very complicated:  
          // please use the sha256 from: <a href="" target="_blank"></a>

          function hash_hmac($algo, $data, $key, $raw_output=False)
              // RFC 2104 HMAC implementation for php.
              // Creates a sha256 HMAC.
              // Eliminates the need to install mhash to compute a HMAC
              // Hacked by Lance Rushing
              // source: <a href="" target="_blank"></a>
              // modified by Ulrich Mierendorff to work with sha256 and raw output

              $b = 64; // block size of md5, sha256 and other hash functions
              if (strlen($key) > $b) {
                  $key = pack("H*",$algo($key));
              $key  = str_pad($key, $b, chr(0x00));
              $ipad = str_pad('', $b, chr(0x36));
              $opad = str_pad('', $b, chr(0x5c));
              $k_ipad = $key ^ $ipad ;
              $k_opad = $key ^ $opad;
              $hmac = $algo($k_opad  . pack("H*", $algo($k_ipad . $data)));
              if ($raw_output)
                  return pack("H*", $hmac);
                  return $hmac;
          This script should work with PHP 4.

          1. vanessa on 25 May 2009


            thanks a lot, it works wonderful.......


  5. mumuri on 24 May 2009

    thanks for the script, i could not have done it without you !

  6. steve on 27 May 2009

    vielen dank... hat mir sehr viel arbeit erspart ;)

  7. Randy Fay on 29 May 2009

    Thanks so much! you got me over the hump.

  8. Diggiety on 30 May 2009

    I think Amazon is making a big mistake requiring this. I think it is a little too complex, and doesn't this slow down requests when you start hashing values?

    1. Ulrich Mierendorff on 30 May 2009

      This new signing of requests destroys certain application concepts, but I can understand why they implemented such a system. It also prevents misuse of their service.  
      And I do not think that it significantly slows down requests, because hashing does not take that long. Calling the base64-encoded hash_hmac function in PHP 100 times takes around 0.002 seconds.

    2. frank farmer on 15 Jun 2009

      As long as amazon is still limiting the API request rate to 1 request per second per IP, then hashing overhead is moot -- the far greater bottleneck is said rate limit.

      1. Cody Snider on 11 Jul 2009

        Honestly, my framework does a chain of requests for some pages without caching any results. Furthermore, I have a dozen sites using the same framework on the same VPS and I have yet to see a limit applied. I believe this is more of a recommendation than an enforced limit. ;-)

        1. Ulrich Mierendorff on 11 Jul 2009

          The rule is sometimes relaxed a bit and bursts may be allowed, but as soon as you get 503 errors you know that you are doing too many requests...

  9. Lee on 06 Jun 2009

    did not work for me

    1. Ulrich Mierendorff on 09 Jun 2009

      Please provide some more information. Which PHP version are you using? What happens if you run the example (error codes)?

  10. che on 15 Jun 2009

    it doesn't work with Keyword search when the keyword is a phrase with spaces in it. Any idea to modify it?

    1. Ulrich Mierendorff on 15 Jun 2009

      Do you have an example? Something like
      $pxml = aws_signed_request("com", array("Operation"=>"ItemSearch",
                                              "Keywords"=>"Harry Potter"), $public_key, $private_key);
      works for me.

  11. DJ Doena on 16 Jun 2009


    thank you all for your help. I got your code to work under PHP with the usage of the alternat SHA256 code and a different XML parser.

    I've uploaded my test code, if anyone else has trouble to get it to work under PHP4.

    <a href="" target="_blank"></a>

    1. Christoph on 17 Jun 2009


      using PHP 4.4.9 the class results in high load and dies with a fatal error on line 94:
      Fatal error: Maximum execution time of 60 seconds exceeded in /srv/www/htdocs/test/auth/ on line 94.

      Any ideas what could produce this loop (even with the original sample file) ?

      Thanks a lot in advance !

      1. peter on 12 Jul 2009

        Exactly the same problem here on the same version of PHP.
        Any headway with this would be great.  
        Am in over my head with this.

    2. Tom on 23 Sep 2009

      ditto.  this pegs my cpu on php 4.4.9.

  12. Yury on 16 Jun 2009

    Thank you for this script, but there is one problem more than hash_hmac function if the server have php <5

    simplexml_load_string() is also php5 :(

    1. Ulrich Mierendorff on 16 Jun 2009

      Hmm.. I did not know that. But you could try another XML parser. Someone posted a PHP 4 example in the comment above.

  13. jeremy warren on 16 Jun 2009

    you ruck. THis helps a lot.

  14. michael on 16 Jun 2009

    Very cool script. I was trying to get it to work and was having trouble understanding how they want it to work. Your script saved me. Thank you!!!

  15. Tom Greer on 17 Jun 2009

    After reading Amazon's new requirements and looking at the C++, Java and Perl examples, I was envisioning a major project with lots of coding and test time.  Your code is simple, understandable and works flawlessly.  

    Thank you!

  16. bt2 on 17 Jun 2009

    thank you sir. very helpful, saved me an hour or so by being able to drop in this method instead of rewriting my existing loader. good job with taking the array() full of the api params - that's what let me drop this right in.

  17. Tod on 18 Jun 2009

    Just  A note Here do we pass the  $assoctag any more ?

    1. Ulrich Mierendorff on 22 Jun 2009

      Just add this as a parameter to the $params array.

  18. Registry on 18 Jun 2009

    Im using this with PHP5, and getting this error "The request signature we calculated does not match the signature you provided. Check your AWS Secret Access Key and signing method. Consult the service documentation for details."

    I tried cross-check my public/private keys in the amazon product api website but its already correct.

    Im using PHP5 on hostmonster.

    1. Ulrich Mierendorff on 22 Jun 2009

      Could you post an example script that does not work?

    2. Oscar on 30 Jun 2009

      Try obtaining a new signature from Amazon Services.
      BTW, thanks a lot to ULRICH, it worked beautifully, flawless, and couldn't find a better way to use some of the most obscure PHP instructions you utilise so efficiently here.

  19. imymemine on 22 Jun 2009

    Great work!!
    I  could  finally  do it with your help. Thanks. : )

  20. jooloo on 23 Jun 2009

    great func... 10x alot!!!!!

  21. Ringo on 25 Jun 2009

    Thanks so much! Really great script.

  22. hendra on 02 Jul 2009

    thank you so much, lets make profit togather

  23. Suggestions needed on 07 Jul 2009

    I tried out your script and it works, but it seems to return fewer results than when I used the unsigned requests.  Here's an example that's getting fewer results.

    example search index: HomeGarden
    example keyword: newmans own dog food

    UNSIGNED VERSION (finds 46 results):

    $request = ''.$amazon_api.'&Operation=ItemSearch&'.'SearchIndex='.$amazon_index.'&Keywords='.$keywords.'&ItemPage='.$ItemPage.'&MinimumPrice=1&ResponseGroup=Medium,OfferSummary,Offers,VariationSummary';

    $response = file_get_contents($request);
    $parsed_xml = simplexml_load_string($response);

    SIGNED VERSION (returns no results):

    $parsed_xml = aws_signed_request($amazon_region, array("Operation"=>"ItemSearch","SearchIndex"=>$amazon_index,"Keywords"=>$keywords,"ItemPage"=>$ItemPage,"MinimumPrice"=>1,"ResponseGroup"=>"Medium,OfferSummary,Offers,VariationSummary"), $amazon_api, $amazon_secret_key);

    I am using your function unchanged.  Any suggestions on how to fix this?

    1. Suggestions needed on 07 Jul 2009

      The signed version of it isn't displaying as I copied and pasted it, so I'll put it on separate lines so it's more readable:

      $parsed_xml = aws_signed_request($amazon_region,  

      1. Ulrich Mierendorff on 08 Jul 2009

        I've tried your request with $keywords="newmans own dog food"; $ItemPage=; $amazon_index="HomeGarden". It worked and returned 46 results. Maybe there is something wrong with your code.

        1. Thank you, Ulrich! on 08 Jul 2009

          I figured it out.  A few lines before the call, the script was changing spaces in the keyword to %20.  That change is not necessary with your code, so I removed it.

          Thanks for taking the time to respond and for creating this script!

    2. Adam Arnold on 11 Jul 2009

      I to am getting blank results using this, regardless what keywords or which category.

      Getting closer to D day... hope everyone else is able to sort it out :(

      1. Ulrich Mierendorff on 11 Jul 2009

        Hmm.. Please post a complete example so that we can figure it out.

      2. hot4online on 13 Jul 2009

        I was having the same problem as well.  Nothing was showing, but the response had data.  Then I realized that the ItemSearch operation no longer was returning the OfferListingId once I commented out my line that was checking to see if there was an offer berfore displaing it started showing my items.

        if(isset($current->Offers->Offer->OfferListing->OfferListingId)){ //only show items for which there is an offer

        Had to change quit a bit of code since it appears th esigned version of ItemSearch does not return the OfferListingId and just about anything under Offers->Offer  I have not looked to closely but  it just appears all this data is no longer returned.

        I hope this helps.

  24. Horacio on 09 Jul 2009

    I made a SOAP version of the function:
    <a href="" target="_blank"></a>

  25. aaron on 16 Jul 2009

    Doesn't work for me.

  26. USiFF on 17 Jul 2009

    Thank you very much!  Yes, this saved me hours...

  27. Stephane Martin on 20 Jul 2009

    Thanks a lot for this very precious function.
    It works most times for me; however I've got trouble with param names that include a dot '.' like when you do batch requests (see <a href="" target="_blank"></a> or multiple operations requests (see <a href="" target="_blank"></a> Your PHP encodes the dots as '_' before signing the request, which it should probably not.
    In the "create the canonicalized query" section, if you replace the line "$param = str_replace("%7E", "~", rawurlencode($param));" with "$param = str_replace("%7E", "~", $param);" then it works with parameters containing dots, though it may be less future-proof (in case Amazon eventually uses other reserved characters in param names).
    Thanks again!

    1. Ulrich Mierendorff on 20 Jul 2009

      For me, batch requests are working and (rawurlencode(".") === ".") evaluates to true. Are you sure that there is no error in your code?

      1. Stephane Martin on 21 Jul 2009

        You're right, I was misled by PHP considering '_'s instead of '.'s ;)
        You can ignore and even delete my comment, except for "thanks a lot for this very precious function"!

  28. Mark on 22 Jul 2009

    My requests were formatted differently than yours.  Thanks so much for the ideas - here's what I ended up with for PHP - works very well!    

    <a href="" target="_blank"></a>

    I linked back to you in my solution, as your method is very helpful

  29. Kynerion on 22 Jul 2009

    Thanks a lot. I modified all my itemsearch request with your script(s) and find the same results as before. :)

  30. Banksy on 23 Jul 2009

    Thank you very much! I'm finding this tutorial.

  31. Anja on 27 Jul 2009

    "und wenn du glaubst es geht nicht mehr, kommt von irgendwo ein skript noch her"

    Vielen Dank, du hast mich vor dem Sprung aus dem Fenster bewahrt...

  32. Wii&#039;s World on 27 Jul 2009

    Thank you for the code, it worked great and saved me a lot of headaches :)

  33. Yureg, developer on 02 Aug 2009

    Nice function. It helped me in development of my own class. Thank you.

  34. machima on 03 Aug 2009

    thank you so muchB)

  35. CalonDdraig on 03 Aug 2009

    Wow, what an amazing little script... this is really amazing and adapted in no time to replace part of my existing script (using my existing XML parser).  

    Would definitely recommend this script to others!

  36. KniX on 05 Aug 2009

    I have received an error stating that my signature did not match that of Amazon's.  I double checked my keys and I am 100% sure they are correct.

    Here is my request string which looks good as well.  Does any have a clue as to what the issue might be?

    <a href="" target="_blank"></a>

    1. Ulrich Mierendorff on 05 Aug 2009

      Are you using the exactly the same aws_signed_request function or have you modified parts of it?

      If not, it could be possible that your keys are the problem. I've heard that if you signed up for AWS years ago, that the keys may not work with the authentication and that you have to apply for a new pair. But I am not sure if this could be the problem.

      1. KniX on 05 Aug 2009

        You were right!  I regenerated my keys and it just worked.  Very weird but it is definitely an issue on Amazon's part.  Thank you very much for your code and support.

        1. Eric Austin Lee on 19 Aug 2009

          Did you only have to regenerate your secret key, or did you somehow also regenerate your regular access key?  the reason I ask is because it's easy to change your own secret key, but not the access key.  Also, after pouring over this page over and over again and also regenerating my own secret key, it did not seem to work :(

  37. Derrick on 10 Aug 2009


  38. Martin on 12 Aug 2009

    Thanks, you saved me some time figuring out, why my signatures weren't valid.  The str_replace  did the trick.  

    Still waiting for the universal multi language url_encode function, which would work the same on every system and client.

  39. Don H. on 13 Aug 2009

    Thank you so much. I feel that Amazon made this far too complicated and provided poor documentation. Venting over.

    I used your script with a very slight modification. Prior to the signed request, my script started like this:

    $xml = simplexml_load_file(",Tracks,ItemAttributes,EditorialReview");

    Now my script starts like this:
    include "aws_signed.php";
    $myParams = array("Operation"=>"ItemSearch","SearchIndex"=>"DVD","Keywords"=>"B001MVWFAE", "ResponseGroup"=>"Images,Tracks,ItemAttributes,EditorialReview");
    $xml = aws_signed_request("com",$myParams,"ACCESS_KEY","SECRET_KEY");

    and with that change to my script, I modified the end of your function from the $request var on down :

        // create request
        $request = "http://".$host.$uri."?".$canonicalized_query."&Signature=".$signature;

    // parse XML
    $pxml = simplexml_load_file($request);
    if ($pxml === False) {
    return False; // no xml
    else {
    return $pxml;

    Works perfectly. Thanks.

  40. sparx on 13 Aug 2009

    Getting close to the deadline and this definitely saved me some time and headaches!

  41. Developer on 13 Aug 2009

    I'll second  "Don H." - "Amazon made this far too complicated and provided poor documentation." Generally finding ANYTHING in the Amazon documentation is a pain in the arse!
    Thank you for you excellent function - works fine for me, will see after the 15th. Your post saved me hours of development time!
    Thank a lot!

  42. Daniel on 13 Aug 2009

    Thank You. Worked like a charm!

  43. pallavi on 14 Aug 2009

    i am geting the following error. anyone can help me out??
    The request signature we calculated does not match the signature you provided. Check your AWS Secret Access Key and signing method. Consult the service documentation for details.


  44. Richard on 15 Aug 2009

    I am using a php toolkit called asm4. i wonder how to integrate this into my toolkit. thanks

    1. Ulrich Mierendorff on 21 Aug 2009

      I think you have to go through the code and replace all your old Amazon requests with this new function.

  45. pistache on 17 Aug 2009

    it work for me. it is very usefull. thank you ,thank you ,thank you

  46. thankful user on 18 Aug 2009


  47. Dan on 19 Aug 2009

    Thank you. Thank you. Thank you.  Works great!  You are a lifesaver!

  48. Joachim on 19 Aug 2009

    I see I should pay more attention to the aws newsletter. i only realized that the old logic with the SubscriptionId will no longer work when it no longer worked.... I saw me studying the amazon documentation and PHP coding all night long - and then I found your script which made it all a whole lot easier. Thank You :)

  49. Alex on 19 Aug 2009

    Thanks for the script !!! Helped so much !

  50. yuyo on 20 Aug 2009

    Question  after making the changes to he donwloaded file do i need to upload t my server and under which name .


  51. andig on 21 Aug 2009

    Hi Ulrich,
    thought I'd let you know- your function has just made it into videoDB (<a href="" target="_blank"></a>

    Best regards,

    1. Ulrich Mierendorff on 21 Aug 2009

      Cool, this project looks interesting.

  52. Anonymous on 25 Aug 2009

    Your function saved quite a lot of my time when a huge application broke that solely relies upon AWS. Thanks a LOT. I owe you a glass of beer. You accept donations?

    1. Ulrich Mierendorff on 26 Aug 2009

      Hi, Thanks for your comment. My PayPal  address is :)

      1. Sam-Inet on 02 Dec 2009

        Hi Ulrich,

        Do you also have an Associate ID?

        Being able to random rotation it, so you get some scratch would be nice!  Please add it to your about page, we who care will share the love.

        Best Regards,

        1. Ulrich Mierendorff on 17 Dec 2009

          ID rotation is a good idea, but I am not sure, whether it is allowed by Amazon to use the ID on websites that you don't own.

          1. Sam-Inet on 17 Dec 2009

            I think Associate IDs have to be allowed on other domains, as one of the "Amazon Web Services Developer Advisory Council" flogs this:

            <a href="" target="_blank"></a>

            Were the 'free' version captures 10% of revenues for themselves.

            And not sure of the legalities, but if you're truly paranoid, get a new Associate ID for some other domain than your main one and release that?

            I have to think that you'll end up with much more revenue that way than just the random paypal donation.

            my 2 cents,

  53. fede on 25 Aug 2009

    Thanks a lot!

  54. Netzwissen on 27 Aug 2009

    You save my day. I ignored all the mails amazon was sending the last weeks, because I knew, that the amazon api is really complex . But since 2 weeks unsigned requests do not work anymore and I was totally frustrated with the poor examples on the aws homepage, especially in PHP. I found your script and after one hour all requests are working again, thx a lot :)

  55. Discount Supplements on 27 Aug 2009

    Thank you - Trying to add Amazon's prices to our site and this is going to help immensely!

  56. Mubashar on 28 Aug 2009

    Thank you so much, I had wasted 1 day for this functionality and still had no solution. Thank you so much

  57. ohmohm on 28 Aug 2009

    Thank you very much.
    I want to know how to implement PHP function to be synchronized in order to delay to call AWS after previous calling for one second?

    1. Ulrich Mierendorff on 31 Aug 2009

      I did this by storing a timestamp in shared memory for every request. To determine how long I have to wait until I can make a new request I calculate the difference between the timestamp in shared memory and and the current time. If you have more than one PHP instance running, you have to use semaphores or similar technology to ensure atomicity of all operations.

  58. yuyo on 29 Aug 2009

    please help me my store  shows the following and not product comes up..
    Warning: file_get_contents(<a href=",%20text%20books&ItemPage=1&MinimumPrice=1&ResponseGroup=Medium,OfferSummary,Offers,VariationSummary)" target="_blank"></a> [function.file-get-contents]: failed to open stream: HTTP request failed! HTTP/1.1 400 Bad Request in /home2/rpc/public_html/bos/index.php on line 41

    Found Books, Text Books Products.

    Warning: Invalid argument supplied for foreach() in /home2/rpc/public_html/bos/index.php on line 62

    1. Ulrich Mierendorff on 31 Aug 2009

      Have you tried to catch the error (with @) and redo the request if it fails?

  59. Now happy affiliate on 01 Sep 2009

    Dude, you kick ass.  This is the sweetest bit of code I've seen that works, the others want an arm and a leg for this code you've so graciously posted.  May karma reward you.

  60. Sherjeel on 02 Sep 2009

    works great!!!!!!!!!
    5 * from my side

  61. bob on 07 Sep 2009

    great job posting this.  Amazon is such a worthless company when it comes to affiliates.  I just use their site for the content images and text :)  They pissed me off enough I even use their info to send visitors to a competitor affiliate link

  62. Mike on 09 Sep 2009

    This  PHP code works perfectly.  It would have taken me great effort and lots of time to figure out out to program this myself.  You saved me lots of time.  It slipped into my application with ease.  Thank you!

  63. Puzzled on 17 Sep 2009

    Puzzle. Using PHP 5.2.... Function works fine to provide signed $request. I know because if in the php script I use echo $request to see it, then cut-and-paste as a URL into browser, I get a display of all the xml info from Amazon. The view source shows <?xml version="1.0" ?><ItemLookupResponse xmlns= ...[lots of info].... </ItemLookupResponse>
    However, continuing in the php script , I get $pxml coming out as false.... even though I expect there is content in $request. Thus
    $pxml = file_get_contents($request);
    result is bool(false)
    so I have nothing for the script to continue processing.
    So why always false?

    1. Ulrich Mierendorff on 18 Sep 2009

      Maybe there is something wrong with your php configuration. Are you able to load other websites with file_get_contents?

      1. Puzzled on 18 Sep 2009

        Ah... Fixed! Thanks.
        Thanks for pointing me in the right direction. Googling I found that
        In php.ini I had to change
        allow_url_fopen = On
        allow_url_fopen = 1

        I had thought I was using this function successfully previously, but in fact, my working application used an "include" from local host. and not file_get_contents. So when the Amazon script was needing a remote file, I had never needed file_get_contents before.

        1. Ulrich Mierendorff on 18 Sep 2009

          Good to know that everything is now working.  :) And thank you for posting the fix, because other users may have similar problems.

  64. Henrik Kjelsberg on 17 Sep 2009

    Using base64-encoding on a secure hash like sha256 is useless, you only end up with a larger string that really is not safer in any way. Just a thought for improvement ;)

    1. Ulrich Mierendorff on 18 Sep 2009

      This is correct if you base64-encode the hex representation of the hash value. The base64-encoded binary representation of the hash value (which we are using here) is approx. 31% smaller.

  65. Gobezu on 25 Sep 2009

    Thank you soooo much, you saved my day after some good +2 hours

  66. Andy on 15 Oct 2009

    Thank you! I was using some code I'd found on Amazon before and I could not get it to work. This code worked a charm.

  67. narawut on 05 Nov 2009

    Thank you very much, This is the one that i looking for after amazon changed them rule.

  68. Peter on 07 Nov 2009

    Thanks, runs very fine with 1 Product.

    How can i change that code, that i get more than one result?

    Thanks Peter.

    1. Ulrich Mierendorff on 09 Nov 2009

      You have to use the appropriate parameters. You can find more info here: <a href="http:\/\/\/AWSECommerceService\/latest\/DG\/" target="_blank"><a href="</a>" target="_blank"></a></a>

  69. Mike C on 11 Nov 2009

    Thank you!!!  I tried a whole bunch of different scripts and code samples and this is the first and only thing that worked for me!!!  Thanks a million!

  70. Frank Z on 25 Nov 2009

    Thanks!  My site went down because this and your code is going to help me get it back up quickly!  Good show!

    Frank Z (I'd sign on but Google OpenID isn't supported...)

  71. Priya on 27 Nov 2009

    Thats awesome, great script. I did hell lot of digging in amzon to find a right script for php. It resolved my issue in seconds.

    Thanks a lot to the author of script. Its quite simple and efficient.

    you really rock.  


  72. Cheat on 08 Dec 2009

    Great function good work.

    It's worth noting that the params have to be sorted in byte order before a valid key will be generated.  

    i.e not alphabetical, low case letters come before upper case.

    You examples work because the param order is correct at entry but for more complex queries a sort function should be added.

    1. Ulrich Mierendorff on 08 Dec 2009

      Please look at the code, line 50. This should work...

      1. Cheat on 11 Dec 2009

        My Bad! Sorry, I'm not sure how I missed that :)

  73. ดูหนัง on 23 Dec 2009

    Thanks  a lot but I can't run this script it say "Did not work.".

    1. Ulrich Mierendorff on 08 Feb 2010

      Sorry for not replying earlier. The system filtered your comment as spam, and I haven't noticed it.
      To answer your question: This could happen, if the request wasn't correct, for example if you forgot to replace the $public_key and $private_key variables.

  74. Dave on 16 Jan 2010

    Thaaaaaaaaaaaaaaaaaaaaaaank you. I was working on this for 3 days now. The documentation was not clear enough. None of the code workes but your finally is working every time. Thank you so much

  75. Bertrand on 28 Jan 2010

    1 word: thanks

  76. Kay on 07 Feb 2010

    Thank you! I search many times to find such a good example!

  77. Ken2010 on 24 Feb 2010

    Help me Please ............ If in use XAMPP and magento version 1.4 . What 's did I do ? If I want to use Product Advertising API from amazon but I don't know . Where is put this code in magento because I not programmer . Please Hepme Please.

    1. Ulrich Mierendorff on 01 Mar 2010

      Sorry, I cannot help you with this. You may want to ask this question in a forum related to magento or you need to learn PHP.

  78. Christian Knobloch on 26 Feb 2010

    Thanks for the script!!!

  79. mod on 27 Feb 2010

    How can I know all request type and how to query like below astore?
    <a href="" target="_blank">rockwell</a>

    1. Ulrich Mierendorff on 01 Mar 2010

      The documentation ( <a href="" target="_blank"></a> ) contains most of the information you need to build your requests.

  80. Sam on 03 Mar 2010

    used your example above and it returns only one result for me no matter what i put as search string
    $pxml = aws_signed_request("com",    array("Operation"=>"ItemSearch","SearchIndex"=>"Electronics","Keywords"=>"xbox","AssociateTag"=>"xxxxxx"),      
                               $public_key, $private_key);
    f ($pxml === False)
        echo "Did not work.
        if (isset($pxml->Items->Item->ItemAttributes->Title))
            echo $pxml->Items->Item->ItemAttributes->Title, "
            echo "Could not find item.

    1. Ulrich Mierendorff on 03 Mar 2010

      This is not suprising, because the example code only echos one title. You will need to use something like this:
      if (isset($pxml->Items->Item))
          foreach ($pxml->Items->Item as $item)
              if (isset($item->ItemAttributes->Title))
                  echo $item->ItemAttributes->Title, "<br />\\n";

      Additionally, you can use print_r($pxml) to see the complete structure of the object and you can find useful information in the SimpleXML documentation, too.

  81. Faraz on 03 Mar 2010

    $method = "GET";
    $host = "";
    $uri = "/onca/xml";

    $params["Operation"] = "ItemSearch";
    $params["SearchIndex"] = $SearchIndex;
    $params["Keywords"] = $Keywords;
    $params["ResponseGroup"] = "Medium,Offers";;

    $params["Service"] = "AWSECommerceService";
    $params["AWSAccessKeyId"] = $KEYID;
       $params["Timestamp"] = gmdate("Y-m-dTH:i:s");
      $params["Version"] = "2009-03-31";

    $canonicalized_query = array();
    foreach ($params as $param=>$value)
    $param = str_replace("%7E", "~", rawurlencode($param));
       $value = str_replace("%7E", "~", rawurlencode($value));
    $canonicalized_query[] = $param."=".$value;
    $canonicalized_query = implode("&", $canonicalized_query);

    $string_to_sign = $method."

    // calculate HMAC with SHA256 and base64-encoding
    $signature = base64_encode(hash_hmac("sha256", $string_to_sign, $private_key, True));

    // encode the signature for the request
       $signature = str_replace("%7E", "~", rawurlencode($signature));
    echo $request = "http://".$host.$uri."?".$canonicalized_query."&Signature=".$signature;

    This is my code for SearchItem operation but its giving me error "not a valid value for Signature. Please change this value and retry your request".
    I tried every way but unable to fix it.Can anyone plz help what im doing wrong.Thanks.

    1. Ulrich Mierendorff on 03 Mar 2010

      Are you using your correct <i>private</i> key?

  82. Eva on 07 Mar 2010

    I have found problem

    " Fatal error: Cannot redeclare hash_hmac() in /home1/ctwosevo/public_html/subdomain/samsungc3050/aws_signed_request.php on line 42 "

    What should i do?

    1. Ulrich Mierendorff on 07 Mar 2010

      Line 42 of the original aws_signed_request.php does not contain anything called "hash_hmac" (this is used later in the code), so I guess you are using a modified version of the script. If you post this script and your PHP version, we could possibly find a solution.

  83. Nicolas on 12 Apr 2010

    Thanks a lot for thsi vey usefull script !

  84. EL Hakim on 20 Apr 2010

    Thanks for this very useful script! Awesome!

  85. law of attraction on 28 Apr 2010

    Very nice piece of codes, hey, do you have any script that searched Amazon for "No of results " returned against each Keywords? i Want to knwo the stock avaliablity for eachkeyword in my list.

    Any thoughts?

    1. Ulrich Mierendorff on 11 Jul 2010

      Sorry for the late reply. If you make an API request, Amazon will return the total number of results. You could just check if it is 0. There are also some other parameters that can be used to return available products only.

  86. Rohan on 11 May 2010

    Works like a charm! :-) Thanks for writing..

  87. find store sales on 13 May 2010

    Thank you for the code

  88. Victor Epand on 07 Jun 2010

    There is a catch. When using PHP, you must use rawurlencode() rather than urlencode(). Otherwise, Amazon won't recognize the spaces.

  89. Joy on 08 Jul 2010

    It great and very helpful for mu.
    so much thanks.

  90. Kay on 20 Jul 2010

    Thanks for the script. It works very fine ;) Ive just really sad about the signature and the horrible documentation from amazon... But your Script makes me happy :)

  91. James on 06 Aug 2010

    Thanks for the script! Not much example on PHP were available from Amazon... Been scratching my head with the Signature part :S  

    Guess I still got a lot to learn in PHP...

  92. xcomm on 22 Aug 2010

    Thanks for the great Script - you get me going with it.

    One thing happens to me since last week thends me to think that something has changed, maybe on amazon side. This should not depend on my changes as also happens with my first saved version. Also Google is full with the error crawling for aws_signed_request.php:3,

    Fatal error: Cannot redeclare aws_signed_request() (previously declared in aws_signed_request.php:3) in aws_signed_request.php on line 102

    Best regards, xcomm

  93. xcomm on 24 Aug 2010

    Ok, as found here:
      <a href="" target="_blank"></a>

    I enclosed the aws_signed_request() function in aws_signed_request.php with e check and it works fine again.

    function aws_signed_request($region, $params, $public_key, $private_key)

    Best regards, xcomm

  94. Manfred on 25 Aug 2010

    nice, take a look at my script if something is not working here: <a href="" target="_blank"></a>

  95. GTFY on 23 Sep 2010

    Thanks a lot for your code !

  96. Dustin on 01 Oct 2010

    This was a lifesaver.

    1. MUHAMMAD SALMAN on 11 Oct 2010

      Dustin do you tell me that how do you implement this fucntion in your request

  97. JA Thankful Pleb on 09 Oct 2010

    Thanks for sharing this!

  98. MUHAMMAD SALMAN on 10 Oct 2010

    Hi , this is nice api , but my problem is that i could not generate the right signatures so plz help me and brielfy tell me how to generate the exact signature with the parameters.

  99. @prostosergik on 18 Oct 2010

    Great! Thanks! Works!

  100. zbay on 26 Nov 2010

    thanks a lot ! you should be proud by yourself for sharing this as it helps a lot !

  101. Adrian on 21 Jan 2011

    I get all the data I need, thak You. I like that script.

    Is there anyone who could show me an example for making an affiliate-link to amazon; so that I get payed from amazon, if someone is buying anything. I can not find any information about the link syntax. Or is it just enough to do this:

    echo "<a href='" . $pxml->Items->Item->DetailPageURL ."'>Buy me!</a>";

    1. Ulrich Mierendorff on 21 May 2011

      Using the URLs that are returned from the API is recommended, but make sure that you add your AssociateTag to the API-requests.  
      You can also build the links yourself. They have the following format: amazon.{com|ca||fr||de|it}/dp/{ASIN}?tag={Your Associate ID}

  102. cn1109 on 09 Feb 2011

    awesome!  It works! It fixed my signature issue.

  103. derjanni on 23 Mar 2011

    Thank you a thousand times! You saved me approx. 345.390.109.234.888 hours or programming!

  104. Marathon Studios on 25 Mar 2011

    Amazon documentation is INFURIATING, this saved me a whole lot of time.

  105. Shellz on 27 Mar 2011

    Thanks for a great help... It really worked a lot for me

  106. Rishi on 31 Mar 2011

    Please.. say how to get a product's attributes.. because i'm trying to make a table for difference between product X and Y..
    so pls  give code for that..

    ex: consider two brand tv (samsung & Onida)
    attributes i want like size, color, special feature...

    Pls  help.. advance thanks..!

    1. Ulrich Mierendorff on 21 May 2011

      The official documentation contains information on ResponseGroups. You have to chose the correct ResponseGroup(s) and then you will be able to extract these attributes. It also helps to look at the response to see how it is structured.

  107. lusputil on 05 May 2011

    Save a lot of my time. Thx you sire!

  108. Dev D on 07 May 2011

    I didnt get the exact price of the product, i mean the price that set in our price section. How can i get that ?

    1. Ulrich Mierendorff on 21 May 2011

      It could be possible that the information that the API returns is outdated. You should also make sure that you extract the correct offer from the API response. The official documentation contains information about that.

    2. Ulrich Mierendorff on 21 May 2011

      It could be possible that the data from the API is slightly outdated. You should also make sure that you extract the correct offer from the response. The official documentation explains that in detail.

  109. Andrea Pinti on 23 Jun 2011

    It's working perfectly, thanks.
    You can even lookup via ISBN-13 with this query

    $pxml = aws_signed_request("com", array("Operation"=>"ItemLookup","IdType"=>"ISBN","ItemId"=> $your_ISBN,"ResponseGroup"=>"Images,ItemAttributes","SearchIndex"=>"Books"), $public_key, $private_key);

  110. @Liskel on 03 Jul 2011

    first of all: great thing!
    But it doesn't work for me and it doesn't display any error message. There's just happening nothing! I figured around by adding echos somewhere in the code and found out that after

    // calculate HMAC with SHA256 and base64-encoding
    $signature = base64_encode(hash_hmac("sha256", $string_to_sign, $private_key, True));

    nothing happens. The script seems stopped, but it's not loading and there is no error message. (There's also nothing displayed when I switch error_reporting to e_all...

    Really would like to use this!
    If you have any suggestions...
    Thanks in advance

  111. @Liskel on 04 Jul 2011

    I just got it :) My Server didn't support encryption... Don't ask why... On my local machine it's working fine! Thank you very much!

  112. Catalin on 14 Jul 2011

    Man. you're the best. thanks for this script, it saved my life...

  113. Fanuel on 29 Jul 2011

    Thanks again

  114. Boz on 22 Aug 2011

    Hi, this worked for me... but now I can't make it work with (italian site), any idea? Does it need to be update somehow? Thanks!

    1. Ulrich Mierendorff on 31 Aug 2011

      Please replace "ecs.amazonaws.".$region with "".$region. $region should be "it" in your case. I will update the script soon.
      Does this work for you?

  115. Adam Capriola on 26 Aug 2011

    This works perfectly!!

    Is there any need to cache the results? Or is it fine as is?

    1. Ulrich Mierendorff on 31 Aug 2011

      Yes, you should cache the response, because the number of allowed requests per hour is limited. Make sure to read the Product Advertising API License Agreement, it tells you how long you are allowed to cache the data.

  116. Maik on 06 Sep 2011

    Hello. Tried to use but error "Es gab einen Fehler bei der Abfrage. " comes along.
    Is there a possibility to get the exact error ? $pxml->Errors or something ?
    By the way: How do I have to include the private/public keys ?

    In the files I got from amazon, the looked like this:
    ---- Start
    ----- End
    Do I just add the lines like this :
    $private_key= "dwfhlsdjkhlsjfkjghsdlfkjgdlfgkfgldjkldkjgdlfkjgldjfhg";

    Thanks in advance.

    1. Ulrich Mierendorff on 05 Nov 2011

      If an error occurs, the XML will contain an error message. You can extract that from the XML response. For the exact structure of the error messages, please look at the documentation:  <a href="" target="_blank"></a>

      Regarding the private key: I think this is the correct way to construct the key. Just try if it works. If not, it could be possible that you got multiple private/public key pairs from Amazon and that this was the wrong one.

  117. Lsdany on 29 Sep 2011


  118. sangeetakumari on 10 Oct 2011

    can i get LCC no.,publishers details  of a book from amazon api link

    1. Ulrich Mierendorff on 05 Nov 2011

      Please try to use a response group like "Large" and look at the complete XML response. If it does contain these details you will not be able to extract them via the API. If your request works you can then try to limit your response group to something smaller than "Large" to save bandwidth and to speed up your requests.

  119. Aline on 18 Oct 2011

    The signature don't work anymore... =(

    1. Ulrich Mierendorff on 05 Nov 2011

      The generation of the signature is still working but you may have to modify a few things so that the complete functions continues to work with the updated version of the API:

      1. Replace
      $host = "ecs.amazonaws.".$region;
      $host = ''.$region;

      2. Replace
      $params["Version"] = "2009-03-31";
      $params["Version"] = "2011-08-01";

      3. Make sure that you add a parameter named "AssociateTag" with your Amazon Associate Tag as the value to your list of parameters for each request.

      With these modifications it should continue to work. I will soon upload an updated version of the script.

  120. dirk on 28 Oct 2011

    Script scheint nicht mehr zu funktionieren, seit 2 Tagen keine Verbindung mehr zu amazon.

    1. Ulrich Mierendorff on 05 Nov 2011

      Bitte probieren Sie die Modifikationen die ich in folgender Antwort beschrieben habe:  <a href="" target="_blank"></a>

    2. dirk on 19 Nov 2011

      Für "de" geht es leider noch immer nicht.

      1. Ulrich Mierendorff on 21 Nov 2011

        Es sollte mit den genannten Änderungen auch für .de funktionieren. Wenn Sie möchten, können Sie mir Ihr Script einmal per Email schicken. Vll. finden wir dann den Fehler.

  121. andy on 29 Oct 2011


    there is a new api version... anyone a idea how i could make that work?


    1. Ulrich Mierendorff on 05 Nov 2011

      Please look at my answer to a similar question:  <a href="" target="_blank"></a>

  122. Omar Monroy on 09 Nov 2011

    THANK YOU, GRACIAS, MERCI , спасибо  

    Really, I never would have done it without your help


  123. david on 16 Nov 2011

    bless you.

  124. endurado on 21 Nov 2011

    You have to insert a param AssociateTag for making latest API version working. Example:
    $params["AssociateTag"] = "xyz123";
    You may also want to change $params["Version"] or simply comment out for using default version.

    1. Ulrich Mierendorff on 21 Nov 2011

      Correct. I've already mentioned this in a previous comment. Please note that the associate tag should be a valid one, so you have to create an an Amazon Associate account.

      1. dirk on 23 Nov 2011

        Thank you!!!
        Damit klappt es wieder ohne Probleme!!!

  125. Gestur on 02 Dec 2011

    I have created a page that requests 20 or 30 individual product data (30 ASIN). Unfortunately, this slows down the page load. I guess the reason is that every request is an individual signed request. Can anyone confirm that? And is there any solution for this? My idea was to  request all 30 individual product data (30 ASIN) using a single signed request. Is it possible to request multiple products with a single signed request? How does he code looks like? Thanks in advance for any help on this!

    1. Ulrich Mierendorff on 14 Feb 2012

      You can use a comma-separated list of ASINS in your requests to get up to 10 ASINs at once. Also look into "batch-request" with which you can double the number of products returned by the API.
      In addtion, do not forget to implement caching, so that frequent accesses to certain pages do not result in the same API requests over and over again.

  126. steve on 25 Jan 2012

    Thanks a million--as many others have said, this saved me lots of time and headache!

  127. @Coreydodge on 12 Feb 2012

    Thanks you very much, this helped me tremendously where the Amazon docs were not. Well laid out and simple example. Also +1 for endurado mentioning the new AssociateTag addition.

  128. @jamiefolsom on 18 Feb 2012

    You rock. Thank you.

  129. Rene on 04 Apr 2012

    Wonderful it works awesome!! Thank you!!

  130. Raymond Appels on 05 Apr 2012

    Thanks very much. i have been searching for hours, but amazon seems not to be able to explain its code after many years. This was very helpfull

  131. Tereza on 26 Apr 2012

    With a few tweaks, works pretty good.  Thank you.  I am learning coding, and it is amazing, but got it to work with your guidance.  Smart!

  132. Marc on 03 May 2012


    vielleicht genau das Skript, das ich gesucht habe. Leider bekomme ich es nicht zum Laufen... :/

    Die Änderungen aus den Kommentaren habe ich bereits durchgeführt, allerdings bin ich mir nicht ganz sicher, wo ich meinen AssociateTag platzieren muss.

    Freue mich über jeden Tipp!


    1. Ulrich Mierendorff on 06 May 2012

      Der AssociateTag ist einfach ein weiterer Parameter im Array $params. Dann sollte es funktionieren.

      1. Marc on 06 May 2012

        Hm, "Did not work"...

        Dabei nutze ich die komplette Codevorgabe, lediglich meinen Tag sowie die Keys habe ich abgeändert..


        $public_key = "20stelligerKey";
        $private_key = "40stelligerKey";
        $pxml = aws_signed_request("de", array("Operation"=>"ItemLookup","ItemId"=>"B000X9FLKM","ResponseGroup"=>"Small"), $public_key, $private_key);

        1. Marc on 06 May 2012


          // some paramters
          $method = "GET";
          // $host = "ecs.amazonaws.".$region; ALT
          $host = ''.$region;
          $uri = "/onca/xml";
          // additional parameters
          $params["Service"] = "AWSECommerceService";
          $params["AWSAccessKeyId"] = $public_key;
          $params["AssociateTag"] = "meintag-21";
          // GMT timestamp
          $params["Timestamp"] = gmdate("Y-m-d\TH:i:s\Z");
          // API version
          // $params["Version"] = "2009-03-31"; ALT
          $params["Version"] = "2011-08-01";


  133. Shah Alom on 14 Jul 2012

    Hi Thanks for the great article,
    But I need one more help,  
    Can you please tell me How can i get top 50 item info... Currently return 10 item information by default....

    Thanks in advance..

Comments are temporarily closed. Please contact me if your question is not answered.