Supabase: CORS errors from browser [2026 fix]
Missing CORS headers in Supabase API calls. Add your domain to project settings or use service_role key server-side.
Supabase CORS Errors from Browser: Emergency Fix
TL;DR
Cause: Your browser requests lack proper CORS headers because your domain isn't whitelisted in Supabase project settings. Fix: Add your domain to Supabase → Project Settings → API → Authorized Redirect URLs or move sensitive calls to a backend with service_role key.---
Exact Error Messages You're Seeing
Check your browser console for these:
``` Access to XMLHttpRequest at 'https://[project-ref].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. ```
``` Failed to load resource: the server responded with a status of 401 (Unauthorized) ```
``` "error": "invalid JWT", "code": "42P01" ```
``` NetworkError when attempting to fetch resource. ```
``` CORS policy: 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'. ```
---
Broken Code → Exact Fix
Issue #1: Direct REST API Call Without Domain Whitelisting
BROKEN: ```javascript const { data, error } = await fetch( 'https://[project-ref].supabase.co/rest/v1/users', { headers: { 'apikey': 'eyJhbGc...', 'Content-Type': 'application/json' } } ); ```
FIXED (Option A - Frontend, requires whitelisting): ```javascript const { data, error } = await fetch( 'https://[project-ref].supabase.co/rest/v1/users', { headers: { 'apikey': 'eyJhbGc...', 'Content-Type': 'application/json', 'Origin': 'https://yourdomain.com' } } ); // FIRST: Add 'https://yourdomain.com' to Supabase Project Settings → API → Additional Redirect URLs ```
FIXED (Option B - Backend, more secure): ```javascript // Frontend const response = await fetch('/api/users', { method: 'GET', headers: { 'Content-Type': 'application/json' } });
// Backend (Node.js/Next.js) import { createClient } from '@supabase/supabase-js';
const supabase = createClient( process.env.SUPABASE_URL, process.env.SUPABASE_SERVICE_ROLE_KEY // Never expose this to frontend );
export default async function handler(req, res) { const { data, error } = await supabase .from('users') .select('*'); if (error) return res.status(400).json({ error }); return res.status(200).json(data); } ```
Issue #2: Using Anon Key Without Proper RLS
BROKEN: ```javascript const supabase = createClient(url, 'eyJhbGc...'); // anon key exposed // Requests fail with 403 because RLS policies block anon access ```
FIXED: ```javascript const supabase = createClient(url, 'eyJhbGc...'); // anon key is fine
// Step 1: In Supabase Dashboard → Authentication → Users // Step 2: Enable "Email Confirmations" or adjust auth settings // Step 3: Check RLS policies on your table: // // CREATE POLICY "Enable read access for all users" ON users // AS SELECT USING (true); // // CREATE POLICY "Enable insert for authenticated users" ON users // AS INSERT WITH CHECK (auth.role() = 'authenticated'); ```
---
Step-by-Step Whitelist Fix
1. Open Supabase Dashboard
2. Select your project → Settings (bottom left)
3. Navigate to API tab
4. Find "Additional Redirect URLs" field
5. Add your domain:
- Development: http://localhost:3000
- Staging: https://staging.yourdomain.com
- Production: https://yourdomain.com
6. Click Save
7. Hard refresh browser (Ctrl+Shift+R or Cmd+Shift+R)
Note: If you're uncertain whether your Supabase version supports this exact setting location, the dashboard layout changed in late 2025—check your Admin settings for "CORS" or "Redirect URLs" tabs if the above path differs.
---
Still Broken? Check These Too
1. [Supabase Authentication Issues Guide](/?guide=supabase-auth) — Your JWT token might be expired or malformed. Verify localStorage contains valid auth data after login.
2. [Session Management & Token Refresh](/?guide=token-refresh) — CORS errors sometimes mask expired tokens. Use supabase.auth.onAuthStateChange() to auto-refresh.
3. Browser Extensions Blocking CORS — Disable CORS-blocking extensions (some privacy tools intentionally block requests). Test in Incognito mode first.
4. Supabase Project Paused — Free-tier projects pause after 1 week of inactivity. Check Dashboard → Project → General for pause status.
5. Incorrect API Key Region — Ensure your SUPABASE_URL matches your project region. Copy-paste from Settings → API → Project URL.
---
Official Documentation
📚 [Supabase CORS Documentation](https://supabase.com/docs/guides/api/cors) 📚 [Supabase Auth & Security Overview](https://supabase.com/docs/guides/auth)
---
Found a different variation? Drop it in the comments
If you hit a CORS error with a different stack trace, service, or Supabase tier behavior—reply below and we'll add it to this guide.