Supabase: CORS errors from browser [2026 fix]
Browser blocks Supabase requests due to missing CORS headers. Add your domain to Project Settings > CORS or use API Gateway.
Supabase CORS Errors from Browser — 2am Fix
TL;DR
Cause: Your browser is blocking requests to Supabase because your domain isn't whitelisted in CORS settings.
Fix: Add your frontend domain to Supabase Project Settings > API > CORS configuration, or switch to using the built-in API Gateway.
---
Exact Error Messages You'll See
``` 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 check: No 'Access-Control-Allow-Origin' header is present on the requested resource. ```
``` CORS error: 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'. ```
``` Failed to load resource: the server responded with a status of 403 (Forbidden) [Error] Failed to fetch (anonymous) @ index.js:45 ```
``` Access-Control-Allow-Origin: http://localhost:3000 is missing Fetch API cannot load https://xxxxx.supabase.co/rest/v1/... ```
``` Preflight request failed: No 'Access-Control-Allow-Origin' header status code: 0, status text: '' ```
---
The Broken Code vs. The Fix
Scenario 1: Missing CORS Configuration
Broken Code (doesn't tell Supabase to allow your domain): ```javascript // frontend/pages/api/users.js import { createClient } from '@supabase/supabase-js'
const supabase = createClient( 'https://xxxxx.supabase.co', 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...' )
// This request fails with CORS error const { data, error } = await supabase .from('users') .select('*') ```
Exact Fix:
1. In Supabase Dashboard → Your Project → Settings → API → CORS Configuration 2. Add your domain: ``` http://localhost:3000 https://yourdomain.com https://*.yourdomain.com ``` 3. Save & deploy 4. Your code now works without changes
Scenario 2: Using Credentials Without CORS Headers
Broken Code:
```javascript
const { data, error } = await fetch(
'https://xxxxx.supabase.co/rest/v1/users',
{
method: 'GET',
headers: {
'apikey': process.env.REACT_APP_SUPABASE_ANON_KEY,
'Authorization': Bearer ${session.access_token}
},
credentials: 'include' // ← CORS will fail
}
)
```
Exact Fix:
```javascript
const { data, error } = await fetch(
'https://xxxxx.supabase.co/rest/v1/users',
{
method: 'GET',
headers: {
'apikey': process.env.REACT_APP_SUPABASE_ANON_KEY,
'Authorization': Bearer ${session.access_token},
'Content-Type': 'application/json'
}
// Remove credentials: 'include' if not needed
// OR configure CORS to allow credentials
}
)
```
Scenario 3: Using API Gateway (Recommended Alternative)
Alternative Fix (avoids CORS entirely):
```javascript // Use Supabase's API Gateway instead of direct REST endpoint const supabase = createClient( 'https://xxxxx.supabase.co', 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...', { realtime: { params: { eventsPerSecond: 10 } } } )
// This bypasses CORS issues entirely const { data } = await supabase.from('users').select('*') ```
---
Step-by-Step: Add Domain to CORS
1. Open Supabase Dashboard
2. Select your project
3. Click Settings (bottom left)
4. Go to API tab
5. Scroll to CORS Configuration
6. Click Add a domain
7. Enter: http://localhost:3000 (dev) or https://yourdomain.com (prod)
8. Click Save
9. Wait 30-60 seconds for propagation
10. Refresh browser and retry
---
Still Broken? Check These Too
1. Localhost domain mismatch: You added http://localhost:3000 but accessing from http://127.0.0.1:3000? They're different origins. Add both.
2. Port number changed: Development servers often shift ports (3000 → 3001). CORS whitelist is exact. Add all possible ports: http://localhost:3000, http://localhost:3001, etc.
3. Browser cache corrupting headers: Hard refresh (Ctrl+Shift+R or Cmd+Shift+R) and clear Site Data. Old CORS rejection responses cache for 10 minutes.
4. Using wildcard incorrectly: https://*.yourdomain.com works, but *.yourdomain.com without protocol doesn't. Always include https:// or http://.
---
Version Notes
I'm uncertain whether CORS behavior changed between Supabase SDK v1 → v2 regarding default credentials handling. Test with your exact version number (check package.json) and report results in comments if you hit unexpected behavior.
---
Related Guides
---
Official Documentation
[Supabase CORS Configuration](https://supabase.com/docs/guides/api/cors)
---
Found a different variation? Drop it in the comments.