Supabase: CORS errors from browser [2026 fix]

Browser blocks Supabase API calls due to missing CORS headers. Fix: 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 domain isn't in the CORS allowed origins list.

Fix: Add your domain to Supabase Project Settings → API → CORS Allowed Origins (include http://localhost:3000 for local dev).

---

Exact Error Messages You'll See

Open DevTools Console (F12) and look for these:

``` 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: Missing CORS headers in response. Check your Supabase project CORS settings. ```

``` Fetch error: No 'Access-Control-Allow-Origin' header is present on the requested resource with credentials mode 'include'. ```

``` [Error] Failed to load resource: the server responded with a status of (nil) (supabase.co) ```

``` TypeError: Failed to fetch. Response to preflight request doesn't pass access control check. ```

---

Broken Code vs. Fixed Code

Problem: Making requests without proper domain registration

BROKEN:

```javascript // Your app is deployed to https://myapp.com // But you never added it to Supabase CORS settings

import { createClient } from '@supabase/supabase-js'

const supabase = createClient( 'https://abc123.supabase.co', 'your-anon-key' )

// This request gets blocked by browser CORS policy async function getUsers() { const { data, error } = await supabase .from('users') .select('*') if (error) console.log('CORS error:', error) return data } ```

FIXED:

Step 1: Go to Supabase Dashboard → Your Project → Settings → API

Step 2: Under "CORS Allowed Origins", add these entries (one per line): ``` http://localhost:3000 http://localhost:5173 https://myapp.com https://www.myapp.com https://staging.myapp.com ```

Step 3: Your code stays the same—the fix is in Supabase settings, not your app:

```javascript // No code changes needed! Just added domains in Supabase settings import { createClient } from '@supabase/supabase-js'

const supabase = createClient( 'https://abc123.supabase.co', 'your-anon-key' )

// Now this works—the browser sees CORS headers async function getUsers() { const { data, error } = await supabase .from('users') .select('*') if (error) console.log('Error:', error.message) return data } ```

---

Why This Happens

When your browser makes a cross-origin request (your domain calling Supabase's domain), the browser first sends an OPTIONS preflight request. Supabase checks if your origin is in the CORS whitelist. If not, it returns no Access-Control-Allow-Origin header, and the browser kills the actual request.

This is a security feature—not a bug.

---

Critical Setup Checklist

  • ✅ Added your production domain (e.g., https://myapp.com)
  • ✅ Added http://localhost:3000 (or your local dev port)
  • ✅ Included www variant if your app uses it
  • ✅ Included all staging/preview domains
  • ✅ Used exact protocol: http:// vs https:// matters
  • ✅ No trailing slashes: use https://myapp.com not https://myapp.com/
  • ✅ Waited 30 seconds for Supabase to propagate changes
  • ✅ Hard-refreshed browser (Ctrl+Shift+R or Cmd+Shift+R)
  • ---

    Still broken? Check these too

    1. You're using the wrong API key

    Make sure you're using the anon (public) key, not the service role key. Service role keys work server-side only.

    ```javascript // ❌ Wrong—service role key has different CORS rules const supabase = createClient(url, serviceRoleKey)

    // ✅ Correct—anon key is for browser const supabase = createClient(url, anonKey) ```

    Find keys at: Settings → API → Project API Keys

    2. Preflight requests are being blocked by a proxy or firewall

    If you're behind a corporate proxy, it might block OPTIONS requests. Contact your network admin. Locally, disable any HTTP proxy temporarily to test.

    3. You added the domain but browser is still caching old response

    Open DevTools, go to Network tab, right-click → "Clear browser cache". Or open in incognito mode to bypass cache entirely.

    ---

    Related guides

  • [Supabase authentication errors: Invalid JWT tokens](/?guide=supabase-jwt-errors)
  • [RLS policy blocking all reads? Debug row-level security](/?guide=supabase-rls-debug)
  • ---

    Official Resources

  • [Supabase CORS Documentation](https://supabase.com/docs/guides/api#cors)
  • [Supabase Project Settings API Reference](https://supabase.com/docs/reference/api/rest-api)
  • Note on version uncertainty: CORS settings location and UI may differ slightly between Supabase dashboard versions (the setting itself is stable). If you can't find "CORS Allowed Origins" in Settings → API, check your project's actual API configuration page or contact Supabase support.

    ---

    Found a different variation? Drop it in the comments—2am debugging is harder alone.

    🔥 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