Supabase: CORS errors from browser [2026 fix]

Browser blocks Supabase API calls due to missing CORS headers. Fix: Add your domain to Supabase project settings or use proper RLS policies.

Supabase CORS Errors from Browser – 2am Emergency Fix

TL;DR

Cause: Your browser is blocking requests to Supabase because your domain isn't whitelisted in CORS settings or you're missing proper authentication headers. Fix: Add your domain to Supabase's CORS allowlist in Project Settings → API → CORS Configuration, or switch from anonymous requests to authenticated requests with proper RLS policies.

---

Real Console Error Messages

Here are exact errors you'll see in browser DevTools (F12 → Console):

``` 1. 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 checks: The value of the 'Access-Control-Allow-Origin' header in the response must not be the wildcard '*' when the request's credentials mode is 'include'.

2. Cross-Origin Request Blocked: The Same Origin Policy disallows reading the remote resource at https://xxxxx.supabase.co/rest/v1/posts. (Reason: CORS header 'Access-Control-Allow-Origin' missing). Status code: (null).

3. Failed to fetch (TypeError) Under 'Network' tab: GET https://xxxxx.supabase.co/rest/v1/data 403 Forbidden – CORS policy: Response to preflight request doesn't pass access control checks.

4. Uncaught (in promise) TypeError: Failed to fetch network error (no preflight response from server)

5. The CORS protocol does not allow specifying a wildcard ('*') for credentials. The credentials mode of requests initiated by the XMLHttpRequest is controlled by the withCredentials attribute. ```

---

Broken Code vs. Exact Fix

❌ BROKEN: Anonymous request with credentials

```javascript // This fails because you're sending credentials without proper CORS setup const { data, error } = await supabase .from('users') .select('*') .eq('id', userId);

// Network call includes credentials by default in some setups fetch('https://xxxxx.supabase.co/rest/v1/users', { method: 'GET', credentials: 'include', // ← CORS blocks this headers: { 'apikey': 'YOUR_ANON_KEY' } }); ```

✅ FIXED: Proper authentication + CORS configuration

Option A: Add domain to CORS allowlist (simplest)

1. Go to [Supabase Dashboard](https://app.supabase.com) → Your Project → Settings → API → CORS Configuration 2. Add your domain: ``` http://localhost:3000 https://yourdomain.com https://www.yourdomain.com ```

```javascript // Now this works—no credentials needed const { data, error } = await supabase .from('users') .select('*') .eq('id', userId); ```

Option B: Use authenticated requests with RLS (recommended for production)

```javascript // Sign in first await supabase.auth.signInWithPassword({ email: user@example.com, password: password });

// Now requests include session automatically—no CORS issues const { data, error } = await supabase .from('users') .select('*') .eq('id', userId);

// Direct fetch also works with proper auth header const res = await fetch('https://xxxxx.supabase.co/rest/v1/users', { method: 'GET', headers: { 'Authorization': Bearer ${session.access_token}, 'apikey': 'YOUR_ANON_KEY' } // NO credentials: 'include' }); ```

---

Still Broken? Check These Too

1. Wrong API Key – Verify you're using your project's anon key (not service key). Service keys should never be exposed to browsers. Check Settings → API Keys in Supabase dashboard.

2. Localhost vs. 127.0.0.1 – If CORS allowlist has localhost:3000 but you're accessing 127.0.0.1:3000, that's two different origins. Add both, or use localhost consistently.

3. Environment Variable Timing – If using .env.local, ensure Next.js/Vite has restarted after you added the Supabase key. CORS errors often hide missing/stale API keys.

4. Stale Browser Cache – Hard refresh (Ctrl+Shift+R or Cmd+Shift+R) to clear preflight cache. Browser caches failed preflight requests.

5. RLS Policy Blocks Everything – If you enabled RLS but policy denies all reads (USING (false)), you'll get 403 errors that look like CORS. Check your RLS policy in Table Editor → Policies.

---

Version-Specific Behavior

I'm uncertain whether Supabase changed CORS defaults between v1.x and v2.x client libraries in 2025–2026. Check your supabase-js version:

```bash npm list @supabase/supabase-js ```

Older versions (<1.25.0) may have stricter CORS validation. If you're on an old version and adding domains doesn't help, try upgrading:

```bash npm install @supabase/supabase-js@latest ```

---

Related Guides

  • [Supabase RLS policies not working](/?guide=supabase-rls-debug)
  • [Fix auth token issues in production](/?guide=supabase-token-refresh)
  • ---

    Official Documentation

    [Supabase CORS Configuration](https://supabase.com/docs/guides/api#cors) [Supabase Authentication & RLS](https://supabase.com/docs/guides/auth/row-level-security)

    ---

    Found a different variation? Drop it in the comments.

    🔥 0d
    LIVE
    ↓ PlanetScale rage spiking •⚠ Vercel pricing complaints •↑ Railway gaining fast •↑ Supabase happiness rising •↑ Resend loved by devs •↓ PlanetScale rage spiking •⚠ Vercel pricing complaints •↑ Railway gaining fast •↑ Supabase happiness rising
    DEVELOPER PAIN RADAR // Loading...

    Developers complain.
    Opportunities appear.

    We track what developers are struggling with today — and what opportunities that creates.

    —
    guides today
    —
    avg happiness
    🔥 Pain
    📖 Guides
    🔭 Explore
    👤 Mine
    🔥 Pain Radar — rage scores today
    ↗ share
    💡 Opportunity Feed — pain = market gap
    📈 Tool Momentum
    all scores →
    📖 Latest Guide
    all guides →
    📖 All Guides
    📊 Tool Scores
    + Submit
    📰 Hacker News
    ➕ Submit a Tool
    ← back