Supabase: CORS errors from browser [2026 fix]

Browser blocks Supabase requests due to missing CORS headers. Add your domain to Project Settings > CORS or use API Gateway.

Supabase CORS Errors from Browser — 2am Fix

TL;DR

Cause: Your browser is blocking requests to Supabase because your domain isn't whitelisted in CORS settings.

Fix: Add your frontend domain to Supabase Project Settings > API > CORS configuration, or switch to using the built-in API Gateway.

---

Exact Error Messages You'll See

``` 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 check: No 'Access-Control-Allow-Origin' header is present on the requested resource. ```

``` CORS error: 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'. ```

``` Failed to load resource: the server responded with a status of 403 (Forbidden) [Error] Failed to fetch (anonymous) @ index.js:45 ```

``` Access-Control-Allow-Origin: http://localhost:3000 is missing Fetch API cannot load https://xxxxx.supabase.co/rest/v1/... ```

``` Preflight request failed: No 'Access-Control-Allow-Origin' header status code: 0, status text: '' ```

---

The Broken Code vs. The Fix

Scenario 1: Missing CORS Configuration

Broken Code (doesn't tell Supabase to allow your domain): ```javascript // frontend/pages/api/users.js import { createClient } from '@supabase/supabase-js'

const supabase = createClient( 'https://xxxxx.supabase.co', 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...' )

// This request fails with CORS error const { data, error } = await supabase .from('users') .select('*') ```

Exact Fix:

1. In Supabase Dashboard → Your Project → Settings → API → CORS Configuration 2. Add your domain: ``` http://localhost:3000 https://yourdomain.com https://*.yourdomain.com ``` 3. Save & deploy 4. Your code now works without changes

Scenario 2: Using Credentials Without CORS Headers

Broken Code: ```javascript const { data, error } = await fetch( 'https://xxxxx.supabase.co/rest/v1/users', { method: 'GET', headers: { 'apikey': process.env.REACT_APP_SUPABASE_ANON_KEY, 'Authorization': Bearer ${session.access_token} }, credentials: 'include' // ← CORS will fail } ) ```

Exact Fix: ```javascript const { data, error } = await fetch( 'https://xxxxx.supabase.co/rest/v1/users', { method: 'GET', headers: { 'apikey': process.env.REACT_APP_SUPABASE_ANON_KEY, 'Authorization': Bearer ${session.access_token}, 'Content-Type': 'application/json' } // Remove credentials: 'include' if not needed // OR configure CORS to allow credentials } ) ```

Scenario 3: Using API Gateway (Recommended Alternative)

Alternative Fix (avoids CORS entirely):

```javascript // Use Supabase's API Gateway instead of direct REST endpoint const supabase = createClient( 'https://xxxxx.supabase.co', 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...', { realtime: { params: { eventsPerSecond: 10 } } } )

// This bypasses CORS issues entirely const { data } = await supabase.from('users').select('*') ```

---

Step-by-Step: Add Domain to CORS

1. Open Supabase Dashboard 2. Select your project 3. Click Settings (bottom left) 4. Go to API tab 5. Scroll to CORS Configuration 6. Click Add a domain 7. Enter: http://localhost:3000 (dev) or https://yourdomain.com (prod) 8. Click Save 9. Wait 30-60 seconds for propagation 10. Refresh browser and retry

---

Still Broken? Check These Too

1. Localhost domain mismatch: You added http://localhost:3000 but accessing from http://127.0.0.1:3000? They're different origins. Add both.

2. Port number changed: Development servers often shift ports (3000 → 3001). CORS whitelist is exact. Add all possible ports: http://localhost:3000, http://localhost:3001, etc.

3. Browser cache corrupting headers: Hard refresh (Ctrl+Shift+R or Cmd+Shift+R) and clear Site Data. Old CORS rejection responses cache for 10 minutes.

4. Using wildcard incorrectly: https://*.yourdomain.com works, but *.yourdomain.com without protocol doesn't. Always include https:// or http://.

---

Version Notes

I'm uncertain whether CORS behavior changed between Supabase SDK v1 → v2 regarding default credentials handling. Test with your exact version number (check package.json) and report results in comments if you hit unexpected behavior.

---

Related Guides

  • [Supabase authentication session expires instantly [fix]](/?guide=supabase-session-expiry)
  • [RLS policies blocking all queries [debugging]](/?guide=supabase-rls-debug)
  • ---

    Official Documentation

    [Supabase CORS Configuration](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