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 – Emergency Fix
TL;DR
Problem: Your browser is blocking requests to Supabase because the server isn't sending theAccess-Control-Allow-Origin header.
Fix: Add your frontend domain to Supabase's CORS allowlist in Project Settings → API → CORS, or use the Supabase client library instead of raw fetch.---
Common Error Messages You'll See
Open your browser DevTools (F12 → Console) and look for one of these:
``` Access to XMLHttpRequest at 'https://[project].supabase.co/rest/v1/...' 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 policy: Request header field 'authorization' is not allowed by Access-Control-Allow-Headers. ```
``` CORS error: The value of the 'Access-Control-Allow-Credentials' header in the response is '' which must be either 'true' or 'false'. ```
``` Failed to load https://[project].supabase.co/rest/v1/users: Response to preflight request doesn't pass access control check: Wildcard '*' cannot be used in the value of the 'Access-Control-Allow-Origin' header when the request's credentials mode is 'include'. ```
``` No 'Access-Control-Allow-Methods' header is present on the requested resource. If an OPTIONS request is an opaque response, the CORS headers must be included with it. ```
---
Broken Code vs. Fixed Code
❌ BROKEN: Direct fetch without proper headers
```javascript // This will trigger CORS errors const response = await fetch( 'https://myproject.supabase.co/rest/v1/users', { method: 'GET', headers: { 'Authorization': 'Bearer ' + token } } ); const data = await response.json(); ```
✅ FIXED: Use official Supabase client library
```javascript // Install: npm install @supabase/supabase-js import { createClient } from '@supabase/supabase-js';
const supabase = createClient( 'https://myproject.supabase.co', 'YOUR_PUBLIC_ANON_KEY' );
const { data, error } = await supabase .from('users') .select('*'); ```
Why this works: The official client handles CORS, authentication, and headers automatically.
---
Alternative Fix: Manual CORS Configuration
If you must use raw fetch, whitelist your domain:
1. Go to [Supabase Dashboard](https://app.supabase.com) 2. Select your project → Settings → API 3. Scroll to CORS configuration 4. Add your frontend origin: ``` http://localhost:3000 https://myapp.com ``` 5. Click Save
Then use fetch with proper headers:
```javascript const response = await fetch( 'https://myproject.supabase.co/rest/v1/users', { method: 'GET', headers: { 'Authorization': 'Bearer ' + token, 'Content-Type': 'application/json', 'Prefer': 'return=representation' }, credentials: 'include' // Only if CORS allows credentials } ); ```
⚠️ Important: Never use wildcard * in CORS origins if you're sending credentials (tokens/cookies). Always specify exact domains.
---
Version-Specific Notes
Supabase JS Client (v2.0+): CORS is handled transparently. If you're still getting errors with @supabase/supabase-js@latest, check that your anon key is correct and your origin is whitelisted.
Supabase JS Client (v1.x): Same behavior. We cannot confirm if pre-v1.0 versions handle CORS differently—upgrade if using ancient versions.
Self-hosted Supabase: If running Supabase yourself, CORS is configured in docker-compose.yml under postgrest environment variables. Check PGRST_OPENAPI_SERVER_PROXY_URI and network settings.
---
Still Broken? Check These Too
1. Wrong anon key: Verify your SUPABASE_ANON_KEY is copied correctly (Settings → API Keys). Typos cause 401 errors that look like CORS issues.
2. Forgot to whitelist localhost during development: Many devs fix production but forget to add http://localhost:3000 for local testing. Check both environments separately.
3. Trailing slash mismatch: If your origin in CORS settings is https://app.com but your app runs on https://app.com/, browsers treat them as different origins. Be exact.
Related Guides:
---
Official Documentation
📚 [Supabase CORS Documentation](https://supabase.com/docs/guides/api/cors)
---
Found a different variation? Drop it in the comments—your 2am fix might save the next person.