Supabase: CORS errors from browser [2026 fix]
Browser blocks Supabase requests due to missing CORS headers. Fix: add your domain to Supabase project settings or use proper authentication headers.
Supabase CORS Errors from Browser - Emergency Fix
TL;DR
Cause: Your browser is blocked from accessing Supabase API because your domain isn't whitelisted in CORS settings or you're missing proper authentication. Fix: Add your frontend domain to Supabase project's CORS allowed origins, or switch to authenticated requests with properAuthorization headers.---
Real Console Error Messages
``` Access to XMLHttpRequest at 'https://your-project.supabase.co/rest/v1/users?select=*' from origin 'http://localhost:3000' has been blocked by CORS policy: Response to preflight request doesn't pass access control check: No 'Access-Control-Allow-Origin' header is present on the requested resource. ```
``` Fetch error: POST https://your-project.supabase.co/auth/v1/signup has been blocked by CORS policy: Request header field content-type is not allowed by Access-Control-Allow-Headers. ```
``` CORS policy: The value of the 'Access-Control-Allow-Credentials' header in the response is '' which must be 'true' when the request's credentials mode is 'include'. Origin 'https://myapp.com' is therefore not allowed access. ```
``` Access to fetch at 'https://your-project.supabase.co/rest/v1/' from origin 'https://staging.example.com' has been blocked by CORS policy: The 'Access-Control-Allow-Origin' header has a value 'https://prod.example.com' that is not equal to the supplied origin. ```
``` No 'Access-Control-Allow-Origin' header is present on the requested resource. If an opaque response serves your needs, set the request's mode to 'no-cors'. ```
---
Broken Code vs. Fixed Code
Problem 1: Missing Domain in CORS Settings
BROKEN: ```javascript // Your frontend is at https://myapp.com // But Supabase project settings only has localhost:3000 whitelisted
const { data, error } = await supabase .from('users') .select('*') .limit(10); // ❌ CORS error: origin not whitelisted ```
FIXED: ```javascript // Step 1: In Supabase Dashboard → Project Settings → API → CORS Allowed Origins // Add: https://myapp.com (remove trailing slashes) // Also add: http://localhost:3000 (for local dev)
// Step 2: Your code stays the same - now it works const { data, error } = await supabase .from('users') .select('*') .limit(10); // ✅ Request succeeds ```
Problem 2: Anonymous Access Without Proper Headers
BROKEN: ```javascript // Public endpoint but missing proper auth setup const response = await fetch( 'https://your-project.supabase.co/rest/v1/public_posts?select=*', { headers: { 'Content-Type': 'application/json' // Missing: apikey header } } ); // ❌ CORS preflight fails ```
FIXED: ```javascript // Option A: Use Supabase client (handles headers automatically) const { data } = await supabase .from('public_posts') .select('*');
// Option B: Raw fetch with proper headers const response = await fetch( 'https://your-project.supabase.co/rest/v1/public_posts?select=*', { headers: { 'Content-Type': 'application/json', 'apikey': 'your-anon-key', // Get from Settings → API Keys 'Authorization': 'Bearer your-anon-key' } } ); // ✅ Headers match CORS whitelist ```
Problem 3: Wrong Environment Domain
BROKEN: ```javascript // Production app running on https://example.com // But CORS settings only has http://localhost:3000
const supabase = createClient( 'https://your-project.supabase.co', 'your-anon-key' ); // ❌ Origin https://example.com blocked ```
FIXED: ```javascript // Add ALL domains to Supabase CORS settings: // - http://localhost:3000 (dev) // - https://staging.example.com (staging) // - https://example.com (production) // - https://subdomain.example.com (if applicable)
// Then your client code works everywhere const supabase = createClient( 'https://your-project.supabase.co', 'your-anon-key' ); // ✅ Works on all whitelisted domains ```
---
Still Broken? Check These Too
1. Wildcard domains don't work - Supabase requires exact domain matches (no *.example.com). Add each subdomain explicitly: staging.example.com, api.example.com, etc.
2. Port matters - localhost:3000 and localhost:3001 are different origins. If switching local ports, update CORS settings or use * for localhost-only testing (never production).
3. Protocol mismatch - http://localhost ≠ https://localhost. Both must be in CORS whitelist if you use both during development. Use matching protocols across environments.
---
Version Notes
I'm uncertain whether Supabase's CORS UI changed between 2024-2026. The CORS settings location should be stable at Project Settings → API → CORS Allowed Origins, but if you can't find it, check the [official Supabase docs](https://supabase.com/docs/guides/api#cors) for current UI location.
---
Related Guides
---
Official Resources
---
Found a different variation? Drop it in the comments — if you're hitting a unique CORS error that doesn't match these patterns, share your exact error message and code so we can add it to this guide.