Supabase Redirect URLs explained: allow list, wildcards and local config
Supabase's Redirect URLs list is the allow list of places Supabase Auth may send a user after OAuth or a magic link; the redirectTo you pass must match one entry, either exactly or through a glob pattern such as https://example.com/**.
Hosted projects edit it on the URL Configuration page; local CLI projects set it with additional_redirect_urls in supabase/config.toml.
Site URL vs Redirect URLs
| Setting | What it does | Typical value |
|---|---|---|
| Site URL | Default redirect when your code passes no redirectTo; also used to build links in auth emails |
https://example.com |
| Redirect URLs | Extra destinations allowed as redirectTo values |
https://example.com/auth/callback, http://localhost:3000/** |
Neither of these is Google's (or any provider's) redirect URI. The provider always returns to the Supabase callback, https://<project-ref>.supabase.co/auth/v1/callback; the allow list controls the second hop, from Supabase to your app. If your symptom is specifically "production logins end on localhost", go to Supabase Google OAuth redirects to localhost.
How to add or change a redirect URL
Hosted project (dashboard)
- Open Authentication → URL Configuration in the Supabase dashboard (as of Oct 2026).
- Under Redirect URLs, add each URL or pattern your app will pass as
redirectTo. - To change the default destination, edit Site URL on the same page.
- Pass a matching value from your code:
await supabase.auth.signInWithOAuth({
provider: 'google',
options: { redirectTo: 'https://example.com/auth/callback' },
})
Local development and config-as-code (Supabase CLI)
In supabase/config.toml:
[auth]
site_url = "http://localhost:3000"
additional_redirect_urls = [
"http://localhost:3000/auth/callback",
"http://127.0.0.1:3000/auth/callback"
]
- Defaults:
site_url = "http://localhost:3000"andadditional_redirect_urls = ["https://localhost:3000"]. Note the default list entry uses https, while most local dev servers run on plain http, so add your http callback explicitly. - The CLI reference describes
additional_redirect_urlsas a list of exact URLs, so list each callback path explicitly for local work. - Restart the local stack after editing:
supabase stop, thensupabase start. - To apply the same file to a linked hosted project, run
supabase config push, which updates the linked project's configuration from your localconfig.toml. Check the file before pushing: a local value such assite_url = "http://localhost:3000"may overwrite your production setting.
Wildcard (glob) syntax
Supabase matches Redirect URLs entries as glob patterns. The separator characters are . and /.
| Pattern | Matches |
|---|---|
* |
Any run of characters except . and / |
** |
Any run of characters, including . and / |
? |
One character, except a separator |
[!a-z] |
One character not in the range |
\c |
The literal character c (escape) |
Examples from Supabase's docs:
| Entry | Matches | Does not match |
|---|---|---|
http://localhost:3000/* |
/foo, /bar |
/foo/bar, /foo/ (trailing slash) |
http://localhost:3000/** |
/foo, /bar, /foo/bar |
|
http://localhost:3000/? |
/a |
/foo |
http://localhost:3000/[!a-z] |
/1 |
/a |
Supabase recommends ** for local and preview URLs but an exact path for production. Supabase's guide links a glob testing tool so you can check a pattern before saving it.
Preview deployment patterns
Vercel
Keep Site URL on production and add:
http://localhost:3000/**
https://*-<team-or-account-slug>.vercel.app/**
Vercel's generated preview hosts look like <project-name>-<unique-hash>-<scope-slug>.vercel.app (per commit) and <project-name>-git-<branch-name>-<scope-slug>.vercel.app (per branch). Both are a single DNS label before .vercel.app, so *-<scope-slug> matches them, while * can't cross a . into other domains. Then make each preview pass its own URL as redirectTo. In Next.js, NEXT_PUBLIC_* variables are inlined at build time, so scope your production-only NEXT_PUBLIC_SITE_URL to the Production environment or previews will redirect to production. Firebase users with Vercel previews have a different problem: see auth/unauthorized-domain on Vercel.
Netlify
http://localhost:3000/**
https://**--<your-netlify-site>.netlify.app/**
Netlify deploy previews use hosts like deploy-preview-42--<your-netlify-site>.netlify.app, which the **-- prefix covers.
Mobile deep links
Custom schemes work too, for example com.example.app://login-callback/ as the Site URL and com.example.app.staging://login-callback/ as an extra Redirect URL.
Redirect URL not working: troubleshooting
Work through these in order; each one is a common reason a redirectTo is ignored.
- Exact match. Compare the
redirectToyour code sends with the entry character by character:httpvshttps,www.example.comvsexample.com, the port, and the path. - Trailing slash.
http://localhost:3000/*does not matchhttp://localhost:3000/foo/. Use**or add the exact URL. *vs**. Use**when the path has more than one segment (/auth/callback) or the host has extra dots.- Truncated Vercel hostnames. Vercel shortens a generated hostname label that would exceed 63 characters. If a preview with a long project or branch name fails, copy the real preview host from the deployment and check it against your pattern.
- Wrong project. Make sure the dashboard you're editing belongs to the project in your
createClientURL (staging and production are separate projects with separate lists). - Local list differs from hosted.
config.tomlonly affects the local stack until you runsupabase config push. - Emails still point at the Site URL. When using
redirectTowith magic links or confirmations, replace{{ .SiteURL }}with{{ .RedirectTo }}in your email templates. - Errors arrive as a fragment. If sign-in fails, Supabase still redirects to your URL with
error_codeanderror_descriptionin the URL hash. Read them before assuming the redirect itself failed:
const params = new URLSearchParams(window.location.hash.slice(1))
const code = params.get('error_code')
if (code && code.startsWith('4')) {
alert(params.get('error_description'))
}
If Google itself rejects the request with redirect_uri_mismatch, the problem is in Google Cloud, not in this list: see redirect_uri_mismatch.
How to confirm it worked
- Trigger sign-in from each environment (production, a preview, localhost).
- After the provider step, check the browser lands on the
redirectToyou passed, not on the Site URL. - For local work, confirm the change after
supabase stop/supabase start; for hosted projects, reload the URL Configuration page and confirm the entry was saved.
FAQ
Does Supabase support wildcard redirect URLs?
Yes. Entries are glob patterns: * matches within one host label or path segment, and ** matches across . and /. For production, Supabase recommends an exact URL.
What is additional_redirect_urls in config.toml?
It is the CLI equivalent of the dashboard's Redirect URLs list for local (and config-as-code) projects. Its default is ["https://localhost:3000"], and the CLI reference describes it as a list of exact URLs.
How do I change the redirect URL in Supabase?
Change the default destination with Site URL and add allowed destinations under Redirect URLs on the URL Configuration page, then pass the new URL as redirectTo. You don't need to change anything in Google Cloud, whose redirect URI stays the Supabase callback.
Why does my Vercel preview redirect to production?
Usually the preview's redirectTo is built from a production-only variable, or the preview host doesn't match your pattern. Add https://*-<team-or-account-slug>.vercel.app/** and build redirectTo from the preview's own URL.
Sources
- Redirect URLs | Supabase Docs
- CLI configuration reference | Supabase Docs
- supabase config push | Supabase CLI Reference
- Managing config and secrets | Supabase Docs
- Login with Google | Supabase Docs
- Environment variables | Next.js Docs
- Google OAuth redirect URL with Vercel Preview URLs and Supabase | Vercel Community
- Accessing Deployments through Generated URLs | Vercel Docs
- Deploy Previews | Netlify Docs
How this page was made: drafted with AI from the sources listed, reviewed by Pewterkit. Docs checked 27 Oct 2026. Spotted something out of date? Tell us.