Configure CORS response headers on AWS Lambda?
Master System Design with Codemia
Enhance your system design skills with over 120 practice problems, detailed solutions, and hands-on exercises.
Introduction
When a browser frontend calls an API backed by AWS Lambda, the browser will allow or block the response based on Cross-Origin Resource Sharing, usually shortened to CORS. The key point is that CORS is enforced by the browser, so the Lambda response and the API Gateway configuration both need to agree on which origins, methods, and headers are allowed.
Return the Right Headers From Lambda
If you are using Lambda proxy integration, your function usually needs to return the CORS headers itself. A minimal Python handler looks like this:
This is enough for a simple GET or POST call when the browser does not need a preflight check. In practice, many requests do trigger preflight because they send JSON, authorization headers, or non-simple methods.
Handle the OPTIONS Preflight Request
Browsers send an OPTIONS request before certain cross-origin requests to ask whether the real request is allowed. If your API does not answer that preflight request correctly, the browser blocks the call before your main business logic even runs.
That pattern works across common API Gateway event shapes and keeps the response logic centralized.
Match API Gateway Configuration to Your Lambda Response
Even when Lambda returns the correct headers, API Gateway can still interfere if the route or integration is misconfigured. For HTTP APIs, CORS can often be configured directly at the API level. For REST APIs, you may need to ensure the OPTIONS method exists and returns the same allowed origins and headers.
The important rule is consistency. If API Gateway says one thing and Lambda returns another, debugging becomes messy because the browser only shows that the CORS check failed, not which layer caused the mismatch.
A practical setup is:
- configure the exact allowed origin in API Gateway
- return that same origin from Lambda
- include
OPTIONSin allowed methods - list any custom request headers explicitly
Using "*" is convenient for public read-only APIs, but it is usually the wrong choice for authenticated browser applications.
Be Careful With Credentials
If the frontend sends cookies or uses credentialed requests, the CORS rules get stricter. In that case, Access-Control-Allow-Origin cannot be "*", and the response must also include Access-Control-Allow-Credentials: true.
Only reflect the incoming Origin header if you actually validate it against a trusted allowlist. Blindly echoing any origin defeats the point of having a policy.
Common Pitfalls
The most common mistake is returning CORS headers on the main GET or POST response but forgetting the OPTIONS response. The browser still blocks the request because the preflight failed first.
Another mistake is mixing "*" with credentials. Browsers reject that combination by design.
Developers also often configure API Gateway but forget that Lambda-generated error responses need CORS headers too. If the success path includes the headers and the error path does not, the frontend sees a generic CORS failure instead of the real API error.
Finally, be careful when testing with tools like curl. Those tools do not enforce browser CORS rules, so a request can appear healthy from the command line while still failing in the browser.
Summary
- Return
Access-Control-Allow-Origin, methods, and headers from Lambda when using proxy integration. - Handle
OPTIONSpreflight requests explicitly. - Keep Lambda and API Gateway CORS settings aligned.
- Do not use
"*"when the request includes credentials. - Add the same CORS headers to error responses so browser clients can read them.

