Fix CORS Error in Supabase Edge Functions
Updated April 2026
Reading this article? Verify your fix in real-time. Test your Supabase Edge Function CORS → CORSFixer
Supabase Edge Functions run on Deno and do not add CORS headers automatically. You need to handle the OPTIONS preflight and add headers to every response.
Browser Console
Access to fetch at 'https://yourproject.supabase.co/functions/v1/my-function' from origin 'https://yourapp.com' has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested resource.The standard Supabase CORS pattern
// supabase/functions/my-function/index.ts
import { serve } from "https://deno.land/std@0.168.0/http/server.ts";
const corsHeaders = { "Access-Control-Allow-Origin": "https://yourapp.com", "Access-Control-Allow-Headers": "authorization, x-client-info, apikey, content-type", "Access-Control-Allow-Methods": "GET, POST, PUT, DELETE, OPTIONS",
};
serve(async (req) => { // Handle OPTIONS preflight if (req.method === "OPTIONS") { return new Response("ok", { headers: corsHeaders }); } try { const data = { message: "Hello from Edge Function" }; return new Response(JSON.stringify(data), { headers: { ...corsHeaders, "Content-Type": "application/json", }, status: 200, }); } catch (error) { return new Response(JSON.stringify({ error: error.message }), { headers: { ...corsHeaders, "Content-Type": "application/json" }, status: 500, }); }
});
Allow multiple origins
const ALLOWED_ORIGINS = [ "https://yourapp.com", "https://staging.yourapp.com", "http://localhost:3000",
];
serve(async (req) => { const origin = req.headers.get("Origin") || ""; const allowedOrigin = ALLOWED_ORIGINS.includes(origin) ? origin : ""; const corsHeaders = { "Access-Control-Allow-Origin": allowedOrigin, "Access-Control-Allow-Headers": "authorization, x-client-info, apikey, content-type", "Vary": "Origin", }; if (req.method === "OPTIONS") { return new Response("ok", { headers: corsHeaders }); } // ...
});
Using Supabase client from the browser
If you are calling Supabase Edge Functions from the Supabase JS client, the apikey header is sent automatically. Make sure it is in your Access-Control-Allow-Headers:
"Access-Control-Allow-Headers": "authorization, x-client-info, apikey, content-type"
Deploy and test
supabase functions deploy my-function supabase functions serve my-function --env-file .env.localTest your Supabase Edge Function CORS → CORSFixer