CORS

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.local
Test your Supabase Edge Function CORS → CORSFixer