Private and password-protected Deploy Previews
If your Netlify project protects its Deploy Previews, every request from your tests gets Netlify’s login or password page instead of your app.
In the deploy log, this usually shows as failing tests and 401 Unauthorized responses.
Check your project’s protection under Project configuration > General > Visitor access > Project visibility. Previews can be public, private, or password protected, separately from production.
Private Deploy Previews
Section titled “Private Deploy Previews”Netlify makes new projects private by default. A private project asks every visitor to sign in with Netlify, and Netlify has no way for automated tests to get past it.
To test private Deploy Previews, change the preview visibility:
- On any plan: make previews public.
- On Pro plans: protect previews with a password instead, and let your tests enter it as described below.
Production can stay private either way.
Password-protected Deploy Previews
Section titled “Password-protected Deploy Previews”Password protection is only available on Netlify Pro plans.
Netlify’s password page is a form that posts a password field.
When the password is right, Netlify sets a cookie that gives access to the whole deploy.
Your tests can post the password once and add that cookie to every browser context and API request.
-
Store the password
Section titled “Store the password”In your Netlify project’s environment variables, add the password as a secret variable named
E2E_NETLIFY_PREVIEW_PASSWORD, scoped to Deploy Previews.Variables that start with
E2E_are sent to Endform’s remote runners automatically.Also add
E2E_NETLIFY_PREVIEW_PASSWORDto the project’sSECRETS_SCAN_OMIT_KEYSvariable. Build tools like Next.js cache the build environment, so Netlify’s secrets scan would otherwise find the password in the build output and fail the build. -
Get the cookie
Section titled “Get the cookie”Add a helper that posts the password and reads the cookie Netlify sets:
netlify-password.ts import type { BrowserContext } from "@playwright/test";let netlifyPasswordCookie: Promise<{ name: string; value: string } | null>;export function getNetlifyPasswordCookie(baseURL: string) {const password = process.env.E2E_NETLIFY_PREVIEW_PASSWORD;if (!password) return Promise.resolve(null);netlifyPasswordCookie ??= fetch(baseURL, {method: "POST",body: new URLSearchParams({ password }),redirect: "manual",}).then((response) => {const [cookie] = response.headers.getSetCookie();if (!cookie) {throw new Error(`Netlify rejected E2E_NETLIFY_PREVIEW_PASSWORD (${response.status})`,);}const [name, value] = cookie.split(";")[0]!.split("=");return { name: name!, value: value! };});return netlifyPasswordCookie;}export async function addNetlifyPasswordCookie(context: BrowserContext,baseURL: string,) {const cookie = await getNetlifyPasswordCookie(baseURL);if (!cookie) return;await context.addCookies([{...cookie,domain: new URL(baseURL).hostname,path: "/",httpOnly: true,secure: true,},]);}Without the variable, for example against production or a local server, nothing changes.
-
Add it to every browser context
Section titled “Add it to every browser context”Override the
contextfixture in thetestyour tests import:tests/test.ts import { test as base } from "@playwright/test";import { addNetlifyPasswordCookie } from "../netlify-password";export const test = base.extend({context: async ({ context, baseURL }, use) => {if (baseURL) await addNetlifyPasswordCookie(context, baseURL);await use(context);},});export { expect } from "@playwright/test";Then import
testandexpectfrom this file instead of@playwright/test, including in setup projects that log in through the UI. -
Add it to direct requests
Section titled “Add it to direct requests”Requests made outside a browser context, such as
fetchcalls in a global setup that create test users, need the cookie as a header:const cookie = await getNetlifyPasswordCookie(baseURL);if (cookie) headers.set("cookie", `${cookie.name}=${cookie.value}`);
The demo repository uses this setup. See setup-utils.ts and tests/test.ts.