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