The issue

So you are trying to get a remote AWS S3 resource, in this specific case, an image. You do your request and an error is thrown:

Image from origin 'https://site.s3.amazonaws.com' has been blocked from loading by Cross-Origin Resource Sharing policy: No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'http://somewebsite.com' is therefore not allowed access.

Or you could have also run into the following error:

XMLHttpRequest cannot load https://site.s3.amazonaws.com/bucket/some-image.png. No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'http://somewebsite.com' is therefore not allowed access.

In our case we had a recommended configuration by Amazon, and we still couldn’t retrieve the images in our code. If we tried to run the code using Firefox it would work, however when we used Safari and Chrome it would not. Sound familiar? Keep reading.

<?xml version="1.0" encoding="UTF-8"?>
<CORSConfiguration xmlns="http://s3.amazonaws.com/doc/2006-03-01/">
    <CORSRule>
        <AllowedOrigin>*</AllowedOrigin>
        <AllowedMethod>GET</AllowedMethod>
        <MaxAgeSeconds>3000</MaxAgeSeconds>
        <AllowedHeader>Authorization</AllowedHeader>
    </CORSRule>
</CORSConfiguration>

We could embed images directly inside our html <img> tags and it would work <img src="https://site.s3.amazonaws.com/bucket/some-image.png" /> however, when we tried to get the image with Javascript we would get one of the two errors mentioned above.

The error in Chrome
Chrome Error</img>
Same code working in Firefox
Firefox Success</img>

You can find that JS Fiddle here, it gets a remote image and converts it into a Base64 Data URL. To test if these changes helped you solve your issue you can run this Fiddle, in the text box enter your own URL and an image, and see if it’s working.

The solution

First we went into our Amazon CORS Settings, click in our bucket, select ‘Properties’ in the top right area, and expand the ‘permissions’ tab:

AWS S3 Settings</img>

Then we click the Edit CORS Configuration button and change our settings to this:

 <?xml version="1.0" encoding="UTF-8"?>
<CORSConfiguration xmlns="http://s3.amazonaws.com/doc/2006-03-01/">
    <CORSRule>
        <AllowedOrigin>*</AllowedOrigin>
        <AllowedMethod>GET</AllowedMethod>
        <MaxAgeSeconds>3000</MaxAgeSeconds>
        <AllowedHeader>*</AllowedHeader>
    </CORSRule>
</CORSConfiguration>

Then click the Save button. After that you have to make sure that every URL you request from Chrome and Safari uses http:// instead of https://. HTTPS retrieval will not work in these browsers at all.

In our case we had Image URLs with https inside of our database, since we didn’t want to change anything in our database, and AWS S3 allows both http and https requests I solved it with a small regular expression that replaced our https URL string with http.

img.src = url.replace(/^https:\/\//i, 'http://');

After that you will be able to get your images correctly in Chrome and Safari.

Chrome Success</img>