Supabase: CORS errors from browser [2026 fix]
Browser blocks Supabase API calls due to missing CORS headers. Fix: Add your domain to Supabase project settings or use proper RLS policies.
Supabase CORS Errors from Browser – 2am Emergency Fix
TL;DR
Cause: Your browser is blocking requests to Supabase because your domain isn't whitelisted in CORS settings or you're missing proper authentication headers. Fix: Add your domain to Supabase's CORS allowlist in Project Settings → API → CORS Configuration, or switch from anonymous requests to authenticated requests with proper RLS policies.---
Real Console Error Messages
Here are exact errors you'll see in browser DevTools (F12 → Console):
``` 1. Access to XMLHttpRequest at 'https://xxxxx.supabase.co/rest/v1/users' from origin 'http://localhost:3000' has been blocked by CORS policy: Response to preflight request doesn't pass access control checks: The value of the 'Access-Control-Allow-Origin' header in the response must not be the wildcard '*' when the request's credentials mode is 'include'.
2. Cross-Origin Request Blocked: The Same Origin Policy disallows reading the remote resource at https://xxxxx.supabase.co/rest/v1/posts. (Reason: CORS header 'Access-Control-Allow-Origin' missing). Status code: (null).
3. Failed to fetch (TypeError) Under 'Network' tab: GET https://xxxxx.supabase.co/rest/v1/data 403 Forbidden – CORS policy: Response to preflight request doesn't pass access control checks.
4. Uncaught (in promise) TypeError: Failed to fetch network error (no preflight response from server)
5. The CORS protocol does not allow specifying a wildcard ('*') for credentials. The credentials mode of requests initiated by the XMLHttpRequest is controlled by the withCredentials attribute. ```
---
Broken Code vs. Exact Fix
❌ BROKEN: Anonymous request with credentials
```javascript // This fails because you're sending credentials without proper CORS setup const { data, error } = await supabase .from('users') .select('*') .eq('id', userId);
// Network call includes credentials by default in some setups fetch('https://xxxxx.supabase.co/rest/v1/users', { method: 'GET', credentials: 'include', // ← CORS blocks this headers: { 'apikey': 'YOUR_ANON_KEY' } }); ```
✅ FIXED: Proper authentication + CORS configuration
Option A: Add domain to CORS allowlist (simplest)
1. Go to [Supabase Dashboard](https://app.supabase.com) → Your Project → Settings → API → CORS Configuration 2. Add your domain: ``` http://localhost:3000 https://yourdomain.com https://www.yourdomain.com ```
```javascript // Now this works—no credentials needed const { data, error } = await supabase .from('users') .select('*') .eq('id', userId); ```
Option B: Use authenticated requests with RLS (recommended for production)
```javascript // Sign in first await supabase.auth.signInWithPassword({ email: user@example.com, password: password });
// Now requests include session automatically—no CORS issues const { data, error } = await supabase .from('users') .select('*') .eq('id', userId);
// Direct fetch also works with proper auth header
const res = await fetch('https://xxxxx.supabase.co/rest/v1/users', {
method: 'GET',
headers: {
'Authorization': Bearer ${session.access_token},
'apikey': 'YOUR_ANON_KEY'
}
// NO credentials: 'include'
});
```
---
Still Broken? Check These Too
1. Wrong API Key – Verify you're using your project's anon key (not service key). Service keys should never be exposed to browsers. Check Settings → API Keys in Supabase dashboard.
2. Localhost vs. 127.0.0.1 – If CORS allowlist has localhost:3000 but you're accessing 127.0.0.1:3000, that's two different origins. Add both, or use localhost consistently.
3. Environment Variable Timing – If using .env.local, ensure Next.js/Vite has restarted after you added the Supabase key. CORS errors often hide missing/stale API keys.
4. Stale Browser Cache – Hard refresh (Ctrl+Shift+R or Cmd+Shift+R) to clear preflight cache. Browser caches failed preflight requests.
5. RLS Policy Blocks Everything – If you enabled RLS but policy denies all reads (USING (false)), you'll get 403 errors that look like CORS. Check your RLS policy in Table Editor → Policies.
---
Version-Specific Behavior
I'm uncertain whether Supabase changed CORS defaults between v1.x and v2.x client libraries in 2025–2026. Check your supabase-js version:
```bash npm list @supabase/supabase-js ```
Older versions (<1.25.0) may have stricter CORS validation. If you're on an old version and adding domains doesn't help, try upgrading:
```bash npm install @supabase/supabase-js@latest ```
---
Related Guides
---
Official Documentation
[Supabase CORS Configuration](https://supabase.com/docs/guides/api#cors) [Supabase Authentication & RLS](https://supabase.com/docs/guides/auth/row-level-security)
---
Found a different variation? Drop it in the comments.