The rejection: Google hasn't verified this app

Fix “Google hasn't verified this app” on Cursor

Cursor is your editor, not your host — so there's no 'Cursor fix'. The blocker lives in two places you control: how your chosen host serves the homepage, and your Google Cloud OAuth configuration.

Platform: CursorStack: Whatever you write — Cursor is the editor, not the host
01 — Why this happens

Whatever you built in Cursor is deployed somewhere else, and that's where the verification issue lives. If you shipped a client-rendered SPA to a static host, you'll hit the empty-shell homepage rejection; if you shipped Next.js to Vercel, you're likely stuck on a *.vercel.app subdomain instead. Diagnose by your deploy target, not by Cursor.

02 — What Google says

Each fix below traces to a requirement Google publishes.

Nothing here is our opinion. Every requirement links to Google’s own page — open it and verify the fix yourself before you resubmit.

Your app must run on a domain you own and have verified — the top private domain, like yourdomain.com. Google's review treats a shared platform subdomain like *.lovable.app or *.vercel.app as not yours.

Google requirement · R1Read it on Google’s docs

Verify the domain in Search Console with the same Google account that owns the Cloud project; verifying under a personal account that isn't on the project fails silently.

Google requirement · R2Read it on Google’s docs

Your homepage must return meaningful, server-rendered HTML to an automated fetch — a JS-only shell, a bot challenge, a robots block, or an invalid TLS certificate all read as 'unresponsive'.

Google requirement · R9Read it on Google’s docs

Declare every scope your code actually requests — an undeclared runtime scope is a rejection.

Google requirement · R20Read it on Google’s docs

Publish the app from 'Testing' to 'In production' before submitting — Testing caps you at 100 users, shows the unverified screen, and expires refresh tokens after 7 days.

Google requirement · R31Read it on Google’s docs
03 — The fix

Do these in order, on Cursor.

  1. 01

    Identify how your host renders the homepage

    Run curl -A "Googlebot" https://yourdomain.com. Real descriptive text means you're fine; an empty shell means you shipped a client-only SPA and need server-rendering or a static landing page.

  2. 02

    Deploy to a domain you own

    Whatever host you chose, connect a custom domain and verify it in Search Console with the account that owns your Cloud project. Don't submit a platform subdomain.

  3. 03

    Reconcile scopes with your code

    Because you wrote the integration by hand, it's easy to request a scope in code that you never declared on the consent screen. Declare exactly the scopes your code requests — no more, no fewer.

  4. 04

    Finish the consent screen and submit

    Matching app name, a monitored support email, privacy policy on your own domain, then publish to production and submit — each is its own documented requirement, and the related guides below cover them one by one.

Check it before you resubmit

See exactly what Google’s crawler sees — free.

Paste your URL and scopes. The pre-check fetches your homepage the way Google does, finds your privacy-policy link, and flags the blockers this rejection is about — in seconds, no signup.

Questions

Straight answers.

Is there a Cursor-specific setting for OAuth verification?

No. Cursor only edits code. Verification depends entirely on your Google Cloud OAuth configuration and how your deploy host serves your homepage.

I hand-wrote the Google sign-in — what trips people up?

Requesting a scope in code that was never declared on the consent screen. Google rejects undeclared runtime scopes, so the two lists must match exactly.