CORS error when calling a Supabase Edge Function or API from your app
"Blocked by CORS policy" or "No Access-Control-Allow-Origin header" when your app calls an edge function. What it means and how to fix it.
Why it happens
Browsers block web pages from calling another domain unless that server explicitly allows it with CORS headers. Before the real request, the browser often sends a "preflight" OPTIONS request. If your function does not answer it with the right headers, the browser blocks the call.
Supabase documents that to call Edge Functions from the browser, you must handle the OPTIONS preflight and return CORS headers on every response, including error responses.
A frequent hidden cause: the function crashes (e.g., a missing secret) and returns an error without CORS headers, so the browser reports a CORS error instead of the real one. Calling third-party APIs (like OpenAI) directly from the browser also often fails with CORS, and would expose your key anyway.
How to fix it, step by step
- Open DevTools → Network, find the failing request (and the OPTIONS request before it), and check its status code. A 500 or 401 behind a "CORS" message means the real problem is inside the function.
- Check the function's logs in Supabase to see if it crashed.
- At the top of the function, return early for preflight: if (req.method === "OPTIONS") return a response with the CORS headers.
- Add the CORS headers to every response, including try/catch error responses.
- With @supabase/supabase-js v2.95.0 or later, import corsHeaders from "npm:@supabase/supabase-js@^2/cors" (Supabase's recommended way). With older versions, define headers that allow authorization, x-client-info, apikey and content-type.
- Call the function from the frontend with supabase.functions.invoke() so the right headers are sent.
- For third-party APIs, call them from an Edge Function instead of the browser.
Paste-ready prompt for Lovable
I get CORS errors calling my Supabase Edge Function from the browser. Please update every Edge Function to: 1. Import corsHeaders from 'npm:@supabase/supabase-js@^2/cors' (or define them in supabase/functions/_shared/cors.ts allowing authorization, x-client-info, apikey, content-type). 2. Return early for OPTIONS preflight requests with those headers. 3. Include corsHeaders on every response, including errors in try/catch. 4. Make sure the frontend calls functions with supabase.functions.invoke(). 5. Move any direct browser calls to third-party APIs (OpenAI, etc.) into an Edge Function. Then tell me how to confirm the fix in the browser Network tab.
FAQ
Can I just set Access-Control-Allow-Origin to * ?
Supabase's example uses * for simplicity. For an app with logins you can restrict it to your own domain, but the preflight and headers still need to be handled.
Why does it say CORS when my function actually crashed?
If the crash response has no CORS headers, the browser hides the real error. Always attach CORS headers to error responses and check the function logs.
Still broken?
Get a free diagnosis by email within 24 hours. Fixed or refunded.
Get a free diagnosisOr get the weekly fix digest:
Free: the Vibe-Code Fix Checklist.