AWS API Gateway - CORS POST not working
System Design practice on Codemia
Work through 120+ system design problems with detailed solutions, from rate limiters to multi-region storage.
Introduction
When a browser says your API Gateway POST request is blocked by CORS, the failure is usually not the POST itself. The real problem is that the browser first sends a preflight OPTIONS request, and either that response is wrong or the eventual POST response is missing the required CORS headers.
Why POST Often Triggers a Preflight Request
Simple cross-origin requests can go straight through, but many real POST requests are not "simple" from the browser's perspective. JSON bodies, Authorization headers, and custom headers commonly trigger a preflight check.
The browser sends:
If the server does not respond with matching CORS headers, the browser never sends the real POST.
That is why Postman can succeed while the browser still fails. Postman is not enforcing browser CORS rules.
You Need CORS on Both OPTIONS and POST
A common mistake is configuring CORS only for the preflight route. The browser also checks the actual POST response.
At minimum, the actual response should include headers such as:
- '
Access-Control-Allow-Origin' - optionally
Access-Control-Allow-Credentials
If you are using Lambda proxy integration, your function usually needs to return those headers itself:
For the preflight route, API Gateway can return the response directly or your backend can do it, depending on how the API is set up.
A Good Mental Model for API Gateway CORS
Think of CORS in API Gateway as two checks:
- Can the browser send the request at all
- Is the actual response allowed to be read by the page
The first check is the OPTIONS preflight. The second check is the final POST response.
If either one is missing headers, the browser reports a CORS failure.
Error Responses Must Also Carry CORS Headers
This catches a lot of teams. They configure the successful 200 response correctly, but when the Lambda throws, API Gateway returns 4xx or 5xx without CORS headers.
From the browser, that still looks like "CORS is broken," even though the real application error might be unrelated.
So you need to make sure:
- success responses include CORS headers
- validation errors include CORS headers
- unauthorized responses include CORS headers
- integration failures include CORS headers
If you skip the error paths, debugging becomes confusing very quickly.
Authorizers and Authentication Can Break Preflight
Another common issue is requiring authentication on OPTIONS. Preflight requests are supposed to be a lightweight permission check from the browser, so if the OPTIONS route is blocked by an authorizer or missing configuration, the browser never gets past the preflight stage.
That is why many API Gateway CORS fixes come down to:
- allow anonymous
OPTIONS - return the exact methods and headers the browser asked for
- deploy the stage after making the change
The deploy step matters. In API Gateway, configuration changes are easy to make and just as easy to forget to deploy.
How to Debug It Quickly
Use browser developer tools and inspect the Network tab. Look for:
- whether
OPTIONSwas sent - the status code of the preflight response
- the presence of
Access-Control-Allow-Origin - the allowed methods and headers returned
Then compare that with the real POST response. If OPTIONS succeeds but POST still fails, the final response headers are usually the missing piece.
From the command line, you can also simulate the preflight:
This does not replace browser testing, but it is a fast way to confirm what API Gateway is actually returning.
Common Pitfalls
- Configuring CORS for
OPTIONSonly and forgetting the realPOSTresponse. - Testing in Postman and assuming that means browser CORS is configured correctly.
- Protecting the
OPTIONSroute with authentication or an authorizer. - Returning wildcard origin together with credentials, which browsers reject.
- Forgetting to deploy the API Gateway stage after changing CORS settings.
Summary
- A broken
POSTCORS flow is often really a broken preflightOPTIONSresponse. - Both the preflight response and the real
POSTresponse need correct CORS headers. - Error responses need CORS headers too, not just successful ones.
- '
OPTIONSshould usually be accessible without normal request authentication.' - The fastest debug path is checking the browser Network tab and comparing
OPTIONSwithPOST.
Related reading
- AWS Api Gateway Authorizer Cognito User Pool Not Working message Unauthorized
- AWS API Gateway error API Gateway does not have permission to assume the provided role as S3 proxy
- AWS API Gateway Execution failed due to configuration error No match for output mapping and no default output mapping configured
- aws api gateway lambda multiple endpoint/functions vs single endpoint
- AWS API Gateway limit requests from a single IP
- AWS API Gateway No 'Access-Control-Allow-Origin' header is present
- AWS API Gateway User anonymous is not authorized to execute API
- AWS AssumeRole - User is not authorized to perform stsAssumeRole on resource

System Design Fundamentals
Build a strong foundation in designing scalable, reliable distributed systems.
View the courseTrack what you have practised
A free account saves your progress, solutions and study plan across every problem on Codemia.
System Design practice on Codemia
Work through 120+ system design problems with detailed solutions, from rate limiters to multi-region storage.