Supabase: CORS errors from browser [2026 fix]
Browser blocks requests to Supabase due to missing CORS headers. Add your domain to Project Settings > API > CORS Allowed Origins.
Supabase: CORS errors from browser [2026 fix]
TL;DR
Cause: Your browser is blocking requests to Supabase because your app's domain isn't in the CORS allowed origins list.
Fix: Add your domain to Supabase Project Settings > API > CORS Allowed Origins (include https:// and exact domain/port).
---
Real Console Error Messages
You'll see one of these in your browser console:
``` Access to XMLHttpRequest at 'https://your-project.supabase.co/rest/v1/table_name' 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'. ```
``` No 'Access-Control-Allow-Origin' header is present on the requested resource. If an opaque response serves your needs, set the request's mode to 'no-cors'. ```
``` The CORS protocol does not allow specifying a wildcard ('*') for the header 'Access-Control-Allow-Credentials' when the 'Access-Control-Allow-Origin' header is '*'. ```
``` Failed to fetch user session from https://your-project.supabase.co/auth/v1/user: No 'Access-Control-Allow-Origin' header is present on the requested resource. ```
---
Broken Code vs. Fixed Code
Scenario 1: Missing CORS Configuration (Most Common)
Broken: ```javascript // Your React/Vue/Svelte app running at http://localhost:3000 import { createClient } from '@supabase/supabase-js';
const supabase = createClient( 'https://your-project.supabase.co', 'your-public-anon-key' );
const { data, error } = await supabase .from('posts') .select('*'); // CORS error thrown here ↑ ```
Fixed (in Supabase Dashboard):
1. Go to Project Settings (gear icon)
2. Click "API" in left sidebar
3. Scroll to "CORS Allowed Origins"
4. Click "Add origin" and enter: http://localhost:3000
5. For production, add: https://yourdomain.com (without trailing slash)
6. Save
Your code stays the same—the fix is purely configuration.
Scenario 2: Localhost + Port Mismatch
Broken: ```javascript // App running on http://localhost:3000 // But CORS only has http://localhost added (without :3000) const supabase = createClient(...); await supabase.from('users').select(); // Still CORS error ```
Fixed: Add BOTH of these as separate origins in Supabase:
http://localhost:3000http://localhost:5173 (if you use Vite)http://localhost:8000 (if you use different ports for testing)Note: Exact port matters. localhost:3000 ≠ localhost:3001.
Scenario 3: Development vs. Production Domain
Broken: ```javascript // Works locally with http://localhost:3000 // Deployed to https://myapp.vercel.app // But CORS only has localhost, not your Vercel domain await supabase.from('data').select(); // CORS error in production ```
Fixed: Add all these origins: ``` http://localhost:3000 https://myapp.vercel.app https://www.myapp.vercel.app (if applicable) ```
---
Still Broken? Check These Too
1. Using wildcard * with credentials – If you need to send cookies/auth tokens, you cannot use *. List explicit domains instead. We're uncertain if Supabase auto-rejects * with credentials in v2026 or silently fails; test both approaches.
2. Trailing slashes and protocols – Ensure you use https:// for production. yourdomain.com ≠ https://yourdomain.com. Check [CORS authentication best practices](/?guide=cors-auth).
3. Browser cache & Service Workers – Clear browser cache (Ctrl+Shift+Delete), disable service workers in DevTools, or do a hard refresh (Ctrl+Shift+R). Old CORS responses get cached.
4. Supabase-js client version – Ancient versions (<2.0) had different CORS behavior. Update: npm install @supabase/supabase-js@latest. See our [Supabase client version guide](/?guide=supabase-versions) for migration steps.
5. Using direct fetch instead of SDK – If you're calling /rest/v1/ endpoints with raw fetch() instead of the JS client, ensure you include the apikey header:
```javascript // Raw fetch approach const response = await fetch( 'https://your-project.supabase.co/rest/v1/posts', { headers: { 'apikey': 'your-public-anon-key', 'Content-Type': 'application/json' } } ); ```
---
Key Takeaways
localhost during dev, full domain during prod---
Official Resources
---
Found a different variation? Drop it in the comments—community fixes help everyone at 2am.