How to fix net::ERR_INVALID_AUTH_CREDENTIALS in Playwright?
Playwrightnet::ERR_INVALID_AUTH_CREDENTIALS is thrown when a server challenges the browser with HTTP Basic Authentication and the credentials supplied are wrong, missing, or malformed. In Playwright this surfaces during page.goto() when the target URL is protected by HTTP auth at the server or reverse proxy level — common in staging environments, admin panels, or development preview deployments. It is distinct from form-based login failures, which happen at the application layer and don't produce a network-level error code.
Common mistake
test('opens staging app', async ({ browser }) => {
const context = await browser.newContext();
const page = await context.newPage();
// Staging is behind HTTP Basic Auth — no credentials provided
await page.goto('https://staging.example.com');
});
Also commonly broken when environment variables are defined but empty:
const context = await browser.newContext({
httpCredentials: {
username: process.env.STAGING_USER, // undefined if not set in CI
password: process.env.STAGING_PASS,
},
});
The fix
Set httpCredentials on the browser context before navigating, and validate the values are present at startup:
import { test, expect } from '@playwright/test';
// playwright.config.ts — apply globally for the staging project
export default {
projects: [
{
name: 'staging',
use: {
baseURL: 'https://staging.example.com',
httpCredentials: {
username: process.env.STAGING_USER!,
password: process.env.STAGING_PASS!,
},
},
},
],
};
For scripts that create contexts manually:
import { chromium } from '@playwright/test';
async function runStagingCheck() {
const user = process.env.STAGING_USER;
const pass = process.env.STAGING_PASS;
if (!user || !pass) {
throw new Error('STAGING_USER and STAGING_PASS must be set');
}
const browser = await chromium.launch();
const context = await browser.newContext({
httpCredentials: { username: user, password: pass },
});
const page = await context.newPage();
await page.goto('https://staging.example.com');
await expect(page.getByRole('heading', { name: 'Staging' })).toBeVisible();
await context.close();
await browser.close();
}
Why it works
Playwright passes the httpCredentials values in the Authorization: Basic header that Chromium sends when the server issues a 401 WWW-Authenticate challenge. Setting them on the BrowserContext rather than per-request means every page opened from that context automatically handles the challenge. Validating that environment variables are non-empty at startup surfaces misconfigured CI environments immediately rather than producing a confusing network error at test time.
Tips
- Store HTTP auth credentials in CI secret managers (GitHub Actions secrets, GitLab CI variables) and never hardcode them in config files checked into version control.
- If the credentials are correct but you still get this error, confirm the server expects Basic auth and not Digest — Playwright's httpCredentials covers Basic auth only.
- For staging environments that use IP allowlisting in addition to HTTP auth, verify the CI runner's egress IP is permitted.
- A 401 that your app serves at the application layer (not the proxy) won't produce ERR_INVALID_AUTH_CREDENTIALS — it will appear as a normal HTTP response that your test can assert on.