Supabase: CORS errors from browser [2026 fix]
Browser blocks Supabase requests due to missing CORS headers in your API URL config. Fix: use your actual project URL with https:// prefix, not localhost.
Supabase: CORS errors from browser [2026 fix]
TL;DR
Cause: You're initializing Supabase with an incorrect or missing SUPABASE_URL that doesn't include the full HTTPS endpoint.
Fix: Use your actual Supabase project URL (format: https://xxxxx.supabase.co) in your environment variables, not localhost or a partial path.
---
Real Console Error Messages
``` 1. Access to XMLHttpRequest at 'https://xxxxx.supabase.co/rest/v1/table' from origin 'http://localhost:3000' has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested resource.
2. Uncaught (in promise) Error: Failed to fetch at async getUser() (user.js:5:10)
3. Cross-Origin Request Blocked: The Same Origin Policy disallows reading the remote resource at https://xxxxx.supabase.co/auth/v1/token. (Reason: CORS request did not succeed). Status code: (null).
4. TypeError: Failed to fetch at FetchError (main.js:1:1) at processQueue (main.js:1:1)
5. POST https://xxxxx.supabase.co/rest/v1/users 403 Forbidden Access-Control-Allow-Origin: missing header ```
---
Broken Code vs. Fixed Code
❌ BROKEN: Incomplete or localhost URL
```javascript // .env.local VITE_SUPABASE_URL=localhost:3000 VITE_SUPABASE_ANON_KEY=your-key-here
// src/lib/supabase.ts import { createClient } from '@supabase/supabase-js'
const supabaseUrl = import.meta.env.VITE_SUPABASE_URL const supabaseKey = import.meta.env.VITE_SUPABASE_ANON_KEY
export const supabase = createClient(supabaseUrl, supabaseKey) // Result: CORS error when browser tries to reach localhost:3000 ```
✅ FIXED: Full HTTPS project URL
```javascript // .env.local VITE_SUPABASE_URL=https://abcdefghijklmnop.supabase.co VITE_SUPABASE_ANON_KEY=your-key-here
// src/lib/supabase.ts import { createClient } from '@supabase/supabase-js'
const supabaseUrl = import.meta.env.VITE_SUPABASE_URL const supabaseKey = import.meta.env.VITE_SUPABASE_ANON_KEY
export const supabase = createClient(supabaseUrl, supabaseKey) // Result: CORS headers respected, requests succeed ```
Key differences:
localhost:3000 → ✅ https://abcdefghijklmnop.supabase.cohttps://---
Finding Your Correct Supabase URL
1. Log in to [Supabase Dashboard](https://app.supabase.com)
2. Select your project
3. Click Settings (gear icon) → API
4. Copy the Project URL (format: https://xxxxx.supabase.co)
5. Paste into your .env.local file exactly as shown
6. Do NOT commit .env.local to git—add to .gitignore
---
Version-Specific Notes
@supabase/supabase-js v2.x and v3.x: Both versions require the full HTTPS URL. No differences in CORS behavior between versions.
Next.js App Router: If using server-side createClient() on the server, CORS doesn't apply—but browser-side clients still need the full URL.
Vite vs. Create React App: Env variable prefix differs (VITE_ vs REACT_APP_), but Supabase URL format requirement is identical.
---
Still broken? Check these too
1. RLS (Row Level Security) Policies Blocking Read Access
- Your URL might be correct, but your table has RLS policies denying unauthenticated access. Verify table policies in Supabase Dashboard → Authentication → Policies. Test with anon role enabled.
2. Anon Key Mismatch or Expired
- If you copied the wrong key (e.g., service_role instead of anon), Supabase rejects the request with CORS-like symptoms. Always use the anon public key in browsers, never service_role in client code.
3. Browser Extensions or Corporate Proxy Blocking Requests - VPNs, ad blockers, or corporate proxies can silently drop requests before they reach Supabase. Test in an incognito window without extensions. Check network tab for actual response status vs. blocked state.
---
Related Guides
---
Official Resources
---
Found a different variation? Drop it in the comments—your fix could save someone else 2 hours at 2am.