Guide
Supabase email link fails with 403 otp_expired
Updated
The most common cause Supabase gives is email prefetching: an email client or security scanner opens the link before the person does, which uses up the one-time token. This applies to apps made with AI app builders that use Supabase Auth for email links such as password resets and magic links.
Fixed in your code, then tested live. Check my app free
Why it happens
A one-time password is meant for a single use or a limited period. When something accesses the confirmation link first, the token is already used or invalidated, so the real person sees it as expired. Supabase also notes that a mismatch between a device clock and the server time can, less often, make a token appear invalid.
Possible causes
- Email prefetching: email clients or security tools open links in emails to scan them, consuming the token before the person clicks.
- A confirmation URL in the email template that implicitly validates or invalidates the token when it is accessed.
- The token has passed its validity period and can no longer be used.
- The token was already used, so the verification endpoint rejects it.
- A discrepancy between the user's device system clock and the server's time, which Supabase describes as less common.
Official fix steps
- Look for 403 Forbidden responses on the verify endpoint in your API logs. (supabase.com)
- Cross-reference those entries with your authentication logs for otp_expired codes or token invalid or expired messages. (supabase.com)
- Correlate by time and IP: rapid 403 or otp_expired events shortly after an email is sent, before a person could click, suggest prefetching. (supabase.com)
- Confirm your app uses the intended OTP verification method with the correct type. (supabase.com)
- Consult your email service documentation for ways to prevent automated prefetching, such as link attributes or headers that signal scanners not to follow links. (supabase.com)
- Consider invalidating the token only after the user explicitly submits it, rather than on first access of a confirmation URL. (supabase.com)
- If prefetching persists, consider an OTP flow where users copy a code from the email into your app instead of clicking a link. (supabase.com)
You can't see it yourself
You're signed in, your customers aren't. Your own inbox, device and clock are not your customers', so you may never see the error they get. Supabase describes tokens being used up by automated scanners before the person ever clicks the link.
What to do next
App broke after you published it? Our AI agent fixes it in your code, then tests your live app again so you see the result yourself. The first check is free.
Fixed in your code, then tested live. Check my app free
Related: Email link is invalid or has expired · Supabase magic-link emails not delivered to your users · Supabase confirmation email not sending: new users never get it (Lovable, Bolt, Base44)
Sources
VibeFix's check can show this on your live app: its AI agent signs up to your app like a new person, uses it on a phone and a computer, and shows what breaks.
Last checked: 31 October 2026, against the sources listed above.
VibeFix is independent. Lovable, Bolt, Replit, Base44, v0 and Supabase are trademarks of their owners.
Want it fixed?
Our AI agent fixes it in your code and tests your live app again. See pricing.
It starts with a free check that confirms the problem on your live app, no account needed.