Supabase: CORS errors from browser [2026 fix]

Browser blocks Supabase requests due to missing CORS headers. Fix: Configure your project's allowed origins in Supabase dashboard or set correct auth headers.

Supabase: CORS Errors from Browser – 2am Production Fix

TL;DR

Cause: Your Supabase project isn't configured to accept requests from your app's domain. Fix: Add your frontend domain to Supabase's CORS allowed origins in Project Settings > API, or ensure you're using the correct API key with proper headers.

---

Real Console Error Messages

Here are the exact errors you'll see in DevTools Console (F12 > Console tab):

``` 1. Access to XMLHttpRequest at 'https://[project-ref].supabase.co/rest/v1/your_table' from origin 'http://localhost:3000' has been blocked by CORS policy: Response to preflight request doesn't pass access control check: Missing header 'access-control-allow-origin'.

2. CORS error: The value of the 'Access-Control-Allow-Origin' header in the response must not be the wildcard '*' when the request's credentials mode (include) is 'include'.

3. Failed to fetch from supabase: TypeError: Failed to fetch (Network tab shows 0 bytes, preflight request returns 403)

4. Access to XMLHttpRequest at 'https://[project-ref].supabase.co/auth/v1/signup' from origin 'https://app.example.com' has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested resource.

5. Cross-Origin Request Blocked: The Same Origin Policy disallows reading the remote resource at https://[project-ref].supabase.co/rest/v1/profiles. (Reason: CORS request did not succeed). Status code: (null). ```

---

Broken Code vs. Exact Fix

Issue 1: Wrong/Missing API Key Type

#### ❌ BROKEN: ```javascript import { createClient } from '@supabase/supabase-js';

const supabase = createClient( 'https://[project-ref].supabase.co', 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...', // Using SERVICE ROLE key in browser! { auth: { persistSession: true } } );

// This triggers CORS because service role keys aren't meant for browser const { data } = await supabase .from('users') .select('*') .catch(err => console.error(err)); ```

#### ✅ FIXED: ```javascript import { createClient } from '@supabase/supabase-js';

const supabase = createClient( 'https://[project-ref].supabase.co', 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...', // Use ANON PUBLIC key in browser { auth: { persistSession: true }, headers: { 'Access-Control-Allow-Origin': '*' // Supabase handles this server-side } } );

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

if (error) console.error('Supabase error:', error.message); ```

Why: Service role keys (sr_...) should only run on your backend. Always use the public ANON key in browser code. [Check your API keys here](https://app.supabase.com/project/_/settings/api).

---

Issue 2: Missing Allowed Origin in Dashboard

#### ❌ BROKEN: ```javascript // Your code is correct, but Supabase dashboard isn't configured // Project Settings > API > CORS Allowed Origins: (empty or wrong domain)

fetch('https://[project-ref].supabase.co/rest/v1/products?select=*', { headers: { 'apikey': 'eyJhbGc...' // public key } }); // Returns 403 with CORS error ```

#### ✅ FIXED: ```javascript // Step 1: Go to Supabase Dashboard // Project Settings > API > CORS Allowed Origins // Add your domains: // - http://localhost:3000 (development) // - http://localhost:5173 (Vite) // - https://myapp.com (production) // - https://*.myapp.com (wildcard for subdomains)

// Step 2: Your code stays the same, now it works: fetch('https://[project-ref].supabase.co/rest/v1/products?select=*', { headers: { 'apikey': 'eyJhbGc...' } }); // Returns 200 with data ```

Important: Leave CORS Allowed Origins empty to disable the check, but this isn't recommended for production security.

---

Issue 3: Credentials Mode Mismatch

#### ❌ BROKEN: ```javascript const supabase = createClient( 'https://[project-ref].supabase.co', 'anon_public_key', { auth: { persistSession: true }, global: { headers: { 'Authorization': 'Bearer token_here' // Triggers credentials check } } } ); // Browser complains: "wildcard '*' not allowed with credentials" ```

#### ✅ FIXED: ```javascript const supabase = createClient( 'https://[project-ref].supabase.co', 'anon_public_key', { auth: { persistSession: true }, // Let Supabase client handle Authorization automatically // Don't manually set Authorization header } );

// Or if using fetch with custom headers: fetch('https://[project-ref].supabase.co/rest/v1/data', { method: 'GET', headers: { 'apikey': 'anon_public_key', // Use apikey, not Authorization 'Content-Type': 'application/json' }, credentials: 'omit' // Don't send credentials if using public key }); ```

---

Still Broken? Check These Too

1. Wrong project URL – Verify you copied the full project URL (includes region). Typos like supaabase.co (two 'a's) won't match allowed origins.

2. Environment variable mismatch – If using .env.local, restart your dev server after editing. Old env values might be cached. Double-check: console.log(import.meta.env.VITE_SUPABASE_URL) matches your dashboard.

3. Auth header conflicts – If you have RLS (Row Level Security) enabled, you need a valid session token. First authenticate: await supabase.auth.signUp() before querying. Unauthenticated users with RLS policies hit CORS failures.

---

Related Guides

  • [Supabase RLS Policy Blocking All Queries](/guide=supabase-rls-denied)
  • [Fixing "Invalid Credentials" During Supabase Auth](/guide=supabase-auth-invalid-creds)
  • ---

    Official Documentation

    [Supabase CORS Configuration Docs](https://supabase.com/docs/guides/api/cors) [Supabase JavaScript Client Docs](https://supabase.com/docs/reference/javascript/introduction)

    ---

    Version Notes

    This guide covers:

  • @supabase/supabase-js v2.x and v3.x (as of 2026)
  • Supabase Dashboard UI current as of January 2026
  • If you're using v1.x, the client initialization syntax differs. Upgrade with: npm install @supabase/supabase-js@latest

    ---

    Found a different variation? Drop it in the comments below—we'll add it to the guide.

    🔥 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