Supabase: CORS errors from browser [2026 fix]
Browser blocks Supabase requests due to missing CORS headers. Fix: Configure allowed origins in Supabase dashboard or use proper auth headers.
Supabase CORS Errors from Browser – 2am Emergency Fix
TL;DR
Cause: Your browser is blocking requests to Supabase because the origin domain isn't whitelisted in CORS settings. Fix: Add your frontend domain to Supabase project's CORS allowed origins in the dashboard, or use authenticated requests with proper session headers.---
Real Console Error Messages
You'll see one of these in DevTools Console (F12):
``` Access to XMLHttpRequest at 'https://your-project.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 check: No 'Access-Control-Allow-Origin' header is present on the requested resource. ```
``` CORS error: The value of the 'Access-Control-Allow-Origin' header in the response must not be the wildcard '*' when the request's credentials mode (include) is 'include'. ```
``` Fetch error: Failed to fetch Cause: Cross-Origin Request Blocked: The Same Origin Policy disallows reading the remote resource at https://your-project.supabase.co/rest/v1/. (Reason: CORS header 'Access-Control-Allow-Origin' missing). Status code: (null). ```
``` No 'Access-Control-Allow-Credentials' header is present on the requested resource when credentials mode is 'include'. ```
``` 401 Unauthorized - CORS preflight failed because authentication wasn't included in the OPTIONS request. ```
---
Broken Code vs. Exact Fix
Scenario 1: Missing CORS Configuration (Most Common)
❌ Broken – No origin whitelisting: ```javascript // supabase/client.ts import { createClient } from '@supabase/supabase-js';
const supabase = createClient( 'https://your-project.supabase.co', 'your-anon-key' );
// Frontend at http://localhost:3000 → CORS error! await supabase.from('users').select('*'); ```
✅ Fixed – Configure in Supabase Dashboard:
1. Go to Project Settings → API → CORS
2. Under "Allowed origins" add:
- http://localhost:3000 (dev)
- https://yourapp.com (production)
3. Save. Redeploy your frontend.
```javascript // Code stays the same—configuration is the fix const supabase = createClient( 'https://your-project.supabase.co', 'your-anon-key' );
await supabase.from('users').select('*'); // Now works! ```
Scenario 2: Credentials Mode Mismatch
❌ Broken – Wildcard with credentials:
```javascript
// CORS origin set to '*' in Supabase dashboard
// But fetch includes credentials
const response = await fetch(
'https://your-project.supabase.co/rest/v1/users',
{
headers: { 'Authorization': Bearer ${token} },
credentials: 'include' // Incompatible with wildcard origin
}
);
```
✅ Fixed – Explicit origin + credentials:
```javascript
// Supabase dashboard CORS: Add exact domain, NOT '*'
// Then use this code:
const response = await fetch(
'https://your-project.supabase.co/rest/v1/users',
{
headers: { 'Authorization': Bearer ${token} },
credentials: 'include' // Now safe
}
);
```
Scenario 3: Missing Authorization Header
❌ Broken – RLS policy rejects unauthenticated request: ```javascript // User not authenticated, table has RLS policy const { data, error } = await supabase .from('posts') .select('*'); // Returns 401 + CORS error ```
✅ Fixed – Authenticate first: ```javascript // Sign in user await supabase.auth.signInWithPassword({ email: 'user@example.com', password: 'password' });
// Now request has session token in Authorization header const { data, error } = await supabase .from('posts') .select('*'); ```
---
Still Broken? Check These Too
1. Environment mismatch: You added https://app.example.com to CORS but deployed to https://app2.example.com. Verify exact domain in browser URL bar matches Supabase CORS list. Check for www prefix mismatches too.
2. Cached responses: Browser/CDN cached a failed response. Hard refresh: Ctrl+Shift+R (Windows) or Cmd+Shift+R (Mac). Clear browser DevTools cache if still stuck.
3. Service worker intercepting: If using Next.js, SvelteKit, or custom service workers, they may strip headers. Disable temporarily: DevTools → Application → Service Workers → Unregister. If that fixes it, check your service worker fetch handler.
---
Key Points (Version Note)
As of 2026, Supabase's CORS implementation follows standard browser security. The dashboard UI for CORS settings is stable, but always verify your project's current API settings panel matches this guide's screenshots—UI occasionally reorganizes between major versions.
---
Resources
---
Found a different variation? Drop it in the comments — if you hit a unique CORS scenario not covered here, let us know and we'll add it.