Supabase: CORS errors from browser [2026 fix]
Browser blocks Supabase API calls due to missing CORS headers. Add your domain to Supabase project settings or use proper auth headers.
Supabase: CORS errors from browser [2026 fix]
TL;DR
Cause: Your browser is blocking requests to Supabase because your domain isn't authorized in project CORS settings. Fix: Add your domain to Supabase project settings under API → CORS, or ensure you're using authenticated requests with valid session tokens.---
Exact Error Messages (Real Console Output)
``` 1. Access to XMLHttpRequest at 'https://xxxxx.supabase.co/rest/v1/users' from origin 'http://localhost:3000' has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested resource.
2. Fetch API cannot load https://xxxxx.supabase.co/rest/v1/posts. The request client is not permitted to access the resource. CORS header 'Access-Control-Allow-Origin' missing.
3. XMLHttpRequest at 'https://xxxxx.supabase.co/auth/v1/user' from origin 'https://myapp.com' blocked by CORS policy: The value of the 'Access-Control-Allow-Origin' header is '' which must be 'https://myapp.com' (with http/https but not both).
4. Preflight request to https://xxxxx.supabase.co/rest/v1/data returned HTTP 403. The CORS protocol does not allow specifying a wildcard (any) origin when the request's credentials mode is 'include'.
5. Failed to load resource (net::ERR_FAILED). The 'Access-Control-Allow-Credentials' header was missing when request's credentials mode is 'include'. ```
---
The Problem: Broken Code vs. Fixed Code
❌ Broken: Missing CORS Configuration + Wrong Request
```javascript // Frontend: localhost:3000 const { data, error } = await supabase .from('users') .select('*') .eq('id', 123);
// Backend call without auth header (if using direct REST) const response = await fetch( 'https://xxxxx.supabase.co/rest/v1/users?id=eq.123', { method: 'GET', headers: { 'Content-Type': 'application/json', // MISSING: Authorization header // MISSING: apikey header } } ); ```
Supabase Project Settings: CORS list is empty or doesn't include localhost:3000.
✅ Fixed: Add Domain to CORS + Include Auth Headers
Step 1: Update Supabase Project Settings 1. Go to [supabase.com](https://app.supabase.com) → Your Project → Settings → API 2. Find "CORS" section 3. Add your origins: ``` http://localhost:3000 https://myapp.com https://www.myapp.com ``` (One per line. Use full protocol + domain. No trailing slashes.)
Step 2: Use Supabase Client Library (Recommended)
```javascript // Uses built-in CORS handling + auto auth headers import { createClient } from '@supabase/supabase-js';
const supabase = createClient( 'https://xxxxx.supabase.co', 'YOUR_ANON_KEY' // Safe to expose in browser );
const { data, error } = await supabase .from('users') .select('*') .eq('id', 123); ```
Step 3: If Using Direct REST API Calls
```javascript
// Include BOTH required headers
const response = await fetch(
'https://xxxxx.supabase.co/rest/v1/users?id=eq.123',
{
method: 'GET',
headers: {
'Content-Type': 'application/json',
'Authorization': Bearer ${session?.access_token}, // For authenticated users
'apikey': 'YOUR_ANON_KEY' // Always required
}
}
);
const data = await response.json(); ```
---
Why This Happens
Supabase uses browser CORS security to prevent unauthorized apps from accessing your data. The browser enforces this before your request reaches Supabase's servers. You must either:
1. Whitelist your domain in project CORS settings (for browser apps), OR 2. Send proper auth headers if making direct REST calls, OR 3. Use Supabase's JavaScript client which handles both automatically
---
Still broken? Check these too
1. Protocol Mismatch
https://myapp.comhttp://myapp.com ← Different protocols = blocked2. Trailing Slashes or Ports
https://myapp.com:3000/ ← Extra trailing slashhttps://myapp.com:3000 ← No slashhttp://localhost:3000, not http://localhost)3. Stale Configuration or Browser Cache
Ctrl+Shift+R / Cmd+Shift+R), clear console, try again---
Related Guides
Official Documentation
[Supabase CORS Configuration Guide](https://supabase.com/docs/guides/api/cors)
---
Found a different variation? Drop it in the comments — we'll add it to this guide so others don't waste 2am debugging time.