Supabase: CORS errors from browser [2026 fix]

Browser blocks requests to Supabase due to missing CORS headers; add your domain to Project Settings > API > CORS or use a server proxy.

Supabase: CORS errors from browser [2026 fix]

TL;DR

Cause: Your browser is blocking requests to Supabase because your domain isn't whitelisted in Supabase's CORS settings. Fix: Add your frontend domain to Supabase Project Settings > API > CORS Allow List in under 60 seconds.

---

Real Console Error Messages

You'll see one (or more) of these exact errors in your browser console:

``` Access to XMLHttpRequest at 'https://[project-id].supabase.co/rest/v1/users' from origin 'http://localhost:3000' has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested resource. ```

``` Failed to load resource: the server responded with a status of 400 (Bad Request) No 'Access-Control-Allow-Origin' header is present on the requested resource ```

``` OPTIONS https://[project-id].supabase.co/rest/v1/users 403 CORS policy: Response to preflight request doesn't pass access control check ```

``` {"code":"PGRST107","message":"Could not find the request"} No 'Access-Control-Allow-Origin' header ```

``` TypeError: Failed to fetch at fetch (app.js:42:1) Caused by: TypeError: Failed to fetch at XMLHttpRequest.send ```

---

Broken Code → Fixed Code

❌ BROKEN (No CORS whitelist configured)

```javascript // Your Next.js/React app at http://localhost:3000 import { createClient } from '@supabase/supabase-js';

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

// This request gets blocked const { data, error } = await supabase .from('users') .select('*'); ```

Result in browser: CORS 403 error. Supabase server never receives the request—browser stops it at the preflight OPTIONS check.

✅ FIXED (Add domain to CORS Allow List)

Step 1: In Supabase Dashboard 1. Go to Project Settings (bottom left) 2. Navigate to API 3. Find CORS Allow List 4. Add your domain: - Local dev: http://localhost:3000 - Production: https://yourdomain.com - Multiple domains: Add each on a new line 5. Click Save

Step 2: Your code stays the same (no changes needed once CORS is fixed)

```javascript // Same code now works const { data, error } = await supabase .from('users') .select('*');

// Browser now allows the request ✓ ```

---

Implementation Details

For Development

``` http://localhost:3000 http://127.0.0.1:3000 http://localhost:3001 ```

For Production

``` https://yourdomain.com https://www.yourdomain.com https://api.yourdomain.com ```

For Vercel/Netlify Previews

``` https://*.vercel.app https://*.netlify.app ```

Note: I'm uncertain about whether wildcard subdomains (*.yourdomain.com) work in all Supabase versions as of 2026—test in your environment and verify in official docs.

---

Still broken? Check these too

1. Wrong Protocol (http vs https)

If your frontend is https://yourdomain.com but you whitelisted http://yourdomain.com, CORS will still block it. Match exactly.

2. Port Mismatch in Local Dev

You're testing on http://localhost:3000 but whitelisted http://localhost:3001. Remove the port from your whitelist to allow any port, or add both explicitly.

3. Supabase Client Initialization Issue [related](/?guide=supabase-auth-setup)

If you're using RLS (Row Level Security) policies, CORS headers alone won't help—you also need proper auth tokens. Verify your createClient() is passing valid credentials.

4. Network Proxy or CDN Stripping Headers

If you're behind Cloudflare, AWS CloudFront, or corporate proxy, it may strip CORS headers. Bypass it or configure the proxy's CORS settings.

5. Browser Cache

Hard refresh: Ctrl+Shift+R (Windows) or Cmd+Shift+R (Mac). Browser may have cached the 403 response.

---

Alternative: Server-Side Proxy (If CORS Whitelist Fails)

If you can't modify Supabase settings or need extra security:

```javascript // Next.js API Route: pages/api/users.js export default async function handler(req, res) { const response = await fetch( 'https://[project-id].supabase.co/rest/v1/users', { headers: { 'Authorization': Bearer ${process.env.SUPABASE_SERVICE_KEY}, 'Content-Type': 'application/json' } } ); const data = await response.json(); res.status(200).json(data); } ```

Then fetch from your own domain: fetch('/api/users')

This bypasses CORS entirely since browser trusts same-origin requests.

---

Official Documentation

[Supabase CORS Configuration Guide](https://supabase.com/docs/guides/api#managing-cors)

[Supabase Project Settings](https://supabase.com/docs/guides/api#api-settings)

---

Quick Checklist

  • [ ] Added your domain to CORS Allow List
  • [ ] Used exact protocol (http/https)
  • [ ] Hard-refreshed browser
  • [ ] Checked Network tab for 403 preflight response
  • [ ] Verified domain has no trailing slash
  • [ ] Waited 30 seconds for Supabase cache to clear
  • 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