I have a JS web app and I'm trying to upload a file to AWS S3 from the client.
I've tried everything both locally (localhost:3000) and when deployed to production (Vercel serverless functions).

I first use a fetch to retrieve a presigned url for the file upload, which works perfectly:

module.exports = async (req, res) => {
    let {fileName, fileType} = req.body;
    const post = await s3.createPresignedPost({
        Bucket: BUCKET_NAME,
        Key: fileName,
        ContentType: fileType,
        Expires: 60

Then, in the second fetch:

await fetch(url, {method: 'POST', body: formData}

I'm getting:

fetch has been blocked by CORS policy: No 'Access-Control-Allow-Origin'

I have set up the Permissions -> CORS json in the bucket configuration correctly:

        "AllowedHeaders": [
        "AllowedMethods": [
        "AllowedOrigins": [
        "ExposeHeaders": [

I also verified the bucket name in my code.

I've tried:

  • Both getPresignedUrl & createPresignedPost to generate the url
  • Both PUT & POST requests
  • Setting headers (Content-Type, x-amz-acl) in the fetch request
  • Using different CORS jsons, allowing all origins, expose different headers, allowing all methods (including HEAD, allowing different headers (like "Content-*")
  • Configuring different users with different permissions (specifically what I need, all S3 permissions, etc)
  • Setting bucket policy
  • Clearing Chrome's cache (using Hard Reload) or by code before every try

I've tried everything and went over dozens of articles (1, 2) and browsing through questions here - but it's still not working. Not locally and not in production.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Browse other questions tagged or ask your own question.