Supabase error
No API key found in request
"No API key found in request" with HTTP 401 comes from Supabase's API gateway, which checks every request before it is passed on to the database API, Auth or Storage: this request carried no apikey header at all. Add the header with your project's publishable key (or the legacy anon key) to every call to /rest/v1, /auth/v1 or /storage/v1, or make the call through supabase-js, which adds it for you. If your code builds the header from an environment variable, set that variable in Vercel under the exact name the code reads, for every environment, and redeploy. A key that is sent but not accepted gets "Invalid API key" instead, and a secret or service_role key belongs only in server code.
Checklist
How to fix it, then check the fix
- 01Find the failing request in the browser's Network tab, or in your server or cron logs, and note its path (/rest/v1, /auth/v1 or /storage/v1). Open its request headers and check whether an apikey header is there.
- 02Reproduce it outside the app. The first request has no key and gets this 401; the second sends the publishable key from Settings > API Keys and should not:
curl -i "https://[PROJECT-REF].supabase.co/rest/v1/[TABLE]?select=*&limit=1" curl -i "https://[PROJECT-REF].supabase.co/rest/v1/[TABLE]?select=*&limit=1" \ -H "apikey: [PUBLISHABLE-KEY]" - 03Where the app calls the API with plain fetch, send the key on the apikey header, and stop with a clear error when the variable is empty instead of sending the request without it:
const key = process.env.NEXT_PUBLIC_SUPABASE_PUBLISHABLE_KEY if (!key) throw new Error('NEXT_PUBLIC_SUPABASE_PUBLISHABLE_KEY is not set') const res = await fetch('https://[PROJECT-REF].supabase.co/rest/v1/[TABLE]?select=*', { headers: { apikey: key }, }) - 04Or make the call through supabase-js. It adds the apikey header to every request, and it throws "supabaseKey is required." when the key is empty rather than sending a request without one:
import { createClient } from '@supabase/supabase-js' const supabase = createClient('https://[PROJECT-REF].supabase.co', '[PUBLISHABLE-KEY]') const { data, error } = await supabase.from('[TABLE]').select('*').limit(1) - 05List the variable names your code reads for the key and compare them with the names set in Vercel. NEXT_PUBLIC_SUPABASE_ANON_KEY in the code and NEXT_PUBLIC_SUPABASE_PUBLISHABLE_KEY in Vercel (or the VITE_ versions) leaves the value empty:
grep -rnE "SUPABASE_(ANON|PUBLISHABLE)_KEY|apikey" --include=*.ts --include=*.tsx --include=*.js --exclude-dir=node_modules . - 06Set the value in Vercel under that exact name for Production and Preview, then redeploy. A deployment keeps the variables it was built with, and NEXT_PUBLIC_ and VITE_ values are written into the browser bundle at build time.
- 07If the message shows in a browser tab after an email link or an OAuth sign-in, the browser was sent to a Supabase API address instead of your app. Check that the Site URL under Authentication > URL Configuration starts with https:// and that the redirectTo you pass is on the Redirect URLs list.
- 08For cron jobs and webhook senders that call /rest/v1 or /storage/v1, add the apikey header from a key stored on that server. Keep secret and service_role keys out of browser code: Supabase returns 401 when a secret key is sent from a browser.
Related
Related guides
Sources
Official docs behind this checklist
- Supabase, Creating API routes
- Supabase, JWT signing keys (the API gateway and the apikey header)
- Supabase, API keys
- Supabase, Edge Function 401 error response
- Supabase, Redirect URLs
- supabase-js source: the apikey header on every request
- supabase/supabase issue 17246, the full response body
- Vercel, Environment variables
Browse all launch guides · Read resources · How to make and check your next change
FAQ
FAQ for builders before launch
Why do I get this when I open the REST URL in my browser?
The address bar sends no apikey header, so the gateway stops the request. The hint also mentions a URL parameter, but Supabase's docs describe the query parameter for WebSocket connections; for HTTP calls, send the header with curl or your code. Files in a public bucket are the exception: /storage/v1/object/public/[BUCKET]/[FILE] opens in a browser.
How is this different from "Invalid API key"?
"No API key found in request" means the gateway saw no key. "Invalid API key" means it got a key this project does not accept, such as one copied from another project. Both are 401, and the fix for the second is to copy the URL and key from the same project.
My Edge Function returns 401 to a webhook. Is it the same error?
Usually not. When the built-in JWT check is on and the call has no Authorization header, Supabase answers "Missing authorization header" before your function runs. Supabase recommends turning that check off (verify_jwt = false) and checking the caller in the function code.
Can I send the service_role or secret key to make it go away?
Only from a server. The service_role and secret keys bypass row level security, and Supabase rejects a secret key sent from a browser with 401. In browser code, send the publishable key or the legacy anon key.