Supabase: CORS errors from browser [2026 fix]

Browser blocks requests to Supabase API due to missing CORS headers; add your domain to project settings or use proper client initialization.

Supabase: CORS errors from browser [2026 fix]

TL;DR

Cause: Your browser is blocking requests to Supabase because your domain isn't in the CORS allowlist. Fix: Add your domain to Project Settings → API → CORS or initialize the client with correct credentials.

---

Exact Console Error Messages

Here are the real errors you'll see at 2am:

``` Access to XMLHttpRequest at 'https://[project].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. ```

``` CORS error: Cross-Origin Request Blocked: The Same Origin Policy disallows reading the remote resource at https://[project].supabase.co/rest/v1/auth/v1/token (Reason: CORS request did not succeed). ```

``` Fetch error: Failed to fetch at Object.<anonymous> (http://localhost:3000/app.js:45:12) TypeError: Failed to fetch ```

``` Access to fetch at 'https://[project].supabase.co/rest/v1/posts?select=*' from origin 'https://myapp.com' has been blocked by CORS policy: The value of the 'Access-Control-Allow-Credentials' header in the response is '' which must be either 'true' or 'false'. ```

``` SubabaseAuthClient: Failed to fetch user: cors error - https://[project].supabase.co/auth/v1/user ```

---

Broken Code vs. Exact Fix

Problem 1: Client initialized without proper CORS config

BROKEN: ```javascript // ❌ This will fail with CORS errors const supabase = createClient( 'https://xyz123.supabase.co', 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...' );

const { data, error } = await supabase .from('users') .select('*'); ```

FIXED: ```javascript // ✅ Correct initialization with explicit config const supabase = createClient( 'https://xyz123.supabase.co', 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...', { auth: { autoRefreshToken: true, persistSession: true, detectSessionInUrl: true }, headers: { 'Content-Type': 'application/json' } } );

const { data, error } = await supabase .from('users') .select('*'); ```

Problem 2: Domain not in CORS allowlist

BROKEN: ``` // Your app runs at https://myapp.com // But Supabase dashboard shows: // API CORS Allowlist: (empty or only localhost) ```

FIXED: ``` Steps in Supabase Dashboard: 1. Go to Project Settings → API 2. Find "CORS Allowlist" section 3. Add these entries: - http://localhost:3000 (dev) - https://myapp.com (prod) - https://www.myapp.com (if applicable) 4. Click "Save" 5. Wait 30 seconds for propagation ```

Problem 3: Wrong auth header format

BROKEN: ```javascript // ❌ Sending JWT incorrectly const response = await fetch( 'https://xyz123.supabase.co/rest/v1/users', { headers: { 'Authorization': 'Bearer ' + token // ← Missing 'Bearer' space handling } } ); ```

FIXED: ```javascript // ✅ Use Supabase client (handles headers automatically) const { data, error } = await supabase .from('users') .select('*');

// OR if raw fetch is required: const response = await fetch( 'https://xyz123.supabase.co/rest/v1/users', { method: 'GET', headers: { 'Authorization': Bearer ${token}, 'apikey': 'your_public_anon_key', 'Content-Type': 'application/json' } } ); ```

---

Version-Specific Behavior

Note on uncertainty: CORS header handling changed between Supabase JS client v1.x and v2.x. We're referencing v2.x+ (current as of 2026). If you're on v1.x, credentials mode may need { credentials: 'include' } in fetch options—verify your package.json.

---

Still broken? Check these too

1. Environment variables mismatch – Confirm your NEXT_PUBLIC_SUPABASE_URL and NEXT_PUBLIC_SUPABASE_ANON_KEY are exactly correct in .env.local and redeployed. A single typo blocks all requests.

2. Browser extensions blocking requests – Disable ad blockers, privacy extensions (uBlock, Privacy Badger), or corporate proxies. They often strip CORS headers.

3. Trailing slash in domain – Ensure SUPABASE_URL is https://xyz.supabase.co not https://xyz.supabase.co/. Trailing slashes can break preflight requests.

---

Quick Debug Checklist

  • [ ] Domain is in Supabase Dashboard CORS Allowlist
  • [ ] Using createClient() from @supabase/supabase-js
  • [ ] Environment variables loaded (check DevTools → Network tab request headers)
  • [ ] No typos in URL or keys
  • [ ] Browser DevTools → Network shows preflight request (OPTIONS) passing
  • [ ] Cleared browser cache (Ctrl+Shift+R or Cmd+Shift+R)
  • ---

    Related guides

  • [Supabase Authentication setup](/?guide=supabase-auth-setup)
  • [Fix RLS Policy errors](/?guide=supabase-rls-errors)
  • Official docs: [Supabase CORS Documentation](https://supabase.com/docs/guides/api#cors)

    ---

    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