netlify login hangs in headless or non-interactive shells: authenticate with NETLIFY_AUTH_TOKEN
netlify login hangs forever in headless shells, SSH sessions, CI runners, and agent sandboxes because it opens a browser for OAuth that never completes. Use this skill when netlify login stalls or an agent must authenticate the Netlify CLI without a browser: create a personal access token in User settings, Applications, Personal access tokens, export it as NETLIFY_AUTH_TOKEN, and set NETLIFY_SITE_ID for deploys.
TL;DR
netlify login never completes in a headless shell, SSH session, CI runner, or agent sandbox because it opens a browser for OAuth and waits forever for an authorization that can never arrive. Skip the interactive login: create a personal access token in the Netlify dashboard (User settings, Applications, Personal access tokens), then export it as NETLIFYAUTHTOKEN. The CLI picks the token up automatically and never prompts.
export NETLIFY_AUTH_TOKEN [your value]
export NETLIFY_SITE_ID=YOUR_SITE_API_ID
netlify statusIf netlify status shows your account instead of prompting for login, you are authenticated.
Symptom
netlify loginThe command prints a message about opening an authorization page and then sits there indefinitely. No error is returned; it just never finishes. This is the expected behavior when there is no browser to complete the OAuth loop.
Fix it
Step 1: stop the hanging command
Press Ctrl+C. Nothing was authenticated, so there is nothing to clean up.
Step 2: create a personal access token in the dashboard
- In a browser, open the Netlify dashboard.
- Go to User settings, then Applications, then Personal access tokens.
- Choose New access token, give it a name that says where it will be used (for example "CI deploy" or "agent sandbox"), and generate it.
- Copy the token now. It is shown once.
Expected: a token string you can paste into the shell. Keep it out of repos and chat logs; it is a secret.
Step 3: export the token in the non-interactive shell
export NETLIFY_AUTH_TOKEN [your value]The CLI reads NETLIFYAUTHTOKEN automatically for every command. Alternatively, most commands accept --auth YOUR_TOKEN directly.
Expected: subsequent commands do not prompt for login.
Step 4: set the site ID for deploys
export NETLIFY_SITE_ID=YOUR_SITE_API_IDNETLIFYAUTHTOKEN only authenticates you; it does not pick a site. Locally, netlify link writes the site ID into .netlify/state.json, but a fresh CI or sandbox shell has no such file, so set NETLIFYSITEID to the site API ID (shown as Project ID in the site configuration). Find the ID with netlify sites:list once the token is set.
Step 5: verify
netlify statusExpected: output shows your Netlify account and any linked site, instead of launching a login prompt.
When this applies
netlify loginhangs with no further output in SSH sessions, Docker containers, CI runners, or agent sandboxes.- Any "waiting for authorization" style stall where no browser window can open.
- Scripted or unattended setups that must authenticate the Netlify CLI once and run hands-off.
When it does NOT apply
- A local machine with a working browser:
netlify loginis the intended flow there; the token path also works but is unnecessary. - Accounts behind Netlify SSO that require interactive SSO login: the personal access token may not satisfy the SSO requirement, and the org admin decides the allowed flow.
- Auth errors (exit code 2) after the token is set: that is a wrong, expired, or revoked token, not the hang. Generate a fresh token.
- Deploy or build failures that happen after authentication succeeds: those are site configuration problems, not login problems.
Version compatibility
- Applies to all recent netlify-cli versions (requires Node.js 18.14.0+). The NETLIFYAUTHTOKEN and NETLIFYSITEID variables have been the documented CI path for years.
- CLI exit codes: 0 success, 1 general error, 2 auth error, 3 project not found, 4 build failed.
Variant phrasings
- "netlify login hangs" / "netlify login stuck waiting for authorization"
- "netlify login no browser" / "netlify login in SSH hangs"
- "netlify CLI headless login" / "authenticate netlify-cli in CI"
Why it happens (root cause)
netlify login implements browser-based OAuth: it opens the authorization page in your default browser and polls for the callback that completes the login. In an environment with no browser, no display, and no way to open a URL interactively, that callback can never happen, so the CLI waits indefinitely. It is not an error or a bug; the command is simply waiting on input that cannot arrive. The personal access token path exists precisely to bypass the interactive flow for machines.
Edge cases
- Token storage: put NETLIFYAUTHTOKEN in the CI provider secret store or the shell profile of the machine, never in the repo, in
netlify.toml, or in build logs. - Token rotation: tokens can be revoked from the same Personal access tokens page. A sudden auth failure on a previously working setup usually means the token was revoked or regenerated.
- Multiple sites: one token works for every site on the account; NETLIFYSITEID decides which site each shell targets. Unset it to switch sites.
netlify logout: clears the locally stored interactive token in the CLI config, but does not touch NETLIFYAUTHTOKEN. If logout seems to do nothing, the env var is still set.- Anonymous deploys: for quick throwaway tests with no sensitive content, the CLI can do an anonymous deploy that expires within an hour; useful to check whether the problem is auth at all.
Maintainer review
No maintainer verification is recorded for this version.
This records the version a maintainer checked. It does not assert that the version is the latest upstream release.