ScreenshotNeo

BlogHow-to

How to Handle HTTP Authentication with Puppeteer

Use Puppeteer’s Page.authenticate() to access HTTP-authenticated pages. See complete code, header and proxy distinctions, troubleshooting, and an API alternative.

By the ScreenshotNeo team4 October 20266 min read

Use Puppeteer’s page.authenticate() before navigating to a page protected by HTTP authentication. Pass an object with string username and password fields. The method returns a promise, so await it before calling page.goto().

import puppeteer from 'puppeteer';

const browser = await puppeteer.launch();
try {
  const page = await browser.newPage();
  await page.authenticate({
    username: process.env.HTTP_AUTH_USERNAME,
    password: process.env.HTTP_AUTH_PASSWORD,
  });

  const response = await page.goto('https://example.com/protected');
  console.log('HTTP status:', response?.status());
} finally {
  await browser.close();
}

The example uses environment variables to keep credentials out of source code. Set HTTP_AUTH_USERNAME and HTTP_AUTH_PASSWORD in the process environment before running it. Puppeteer does not require those particular variable names.

See the official Page.authenticate() API reference and Credentials interface. If the goal is to capture a page without managing a browser, ScreenshotNeo is a website screenshot API and MCP server for developers.

What Page.authenticate() does

Page.authenticate() configures HTTP-auth credentials on the Puppeteer Page that will request the protected resource. Its documented input is either a credentials object or null. The object has two string properties: username and password.

Call it on the page before navigation. If you create another page, configure authentication on that page too. To disable authentication, call await page.authenticate(null).

Complete runnable example

With a Node.js project that has Puppeteer installed and environment variables set, save this as an ES module file such as auth.mjs and run it with Node.js:

import puppeteer from 'puppeteer';

const username = process.env.HTTP_AUTH_USERNAME;
const password = process.env.HTTP_AUTH_PASSWORD;
const targetUrl = process.env.TARGET_URL ?? 'https://example.com/protected';

if (!username || !password) {
  throw new Error('Set HTTP_AUTH_USERNAME and HTTP_AUTH_PASSWORD first.');
}

const browser = await puppeteer.launch();
try {
  const page = await browser.newPage();
  await page.authenticate({ username, password });

  const response = await page.goto(targetUrl, { waitUntil: 'domcontentloaded' });
  if (!response) {
    throw new Error('Navigation did not produce a main-resource response.');
  }

  console.log(`HTTP ${response.status()} ${response.statusText()}`);
  console.log('Final URL:', page.url());
} finally {
  await browser.close();
}

domcontentloaded waits for the initial document to be parsed; it does not guarantee that every image or later application request has finished. Choose a different navigation wait condition if your task needs a different readiness signal. Check the HTTP status and the page content separately: receiving a response does not prove the credentials were accepted.

Authentication, extra headers, and proxy credentials

Need Puppeteer API What the docs establish
Provide HTTP-auth credentials page.authenticate({ username, password }) Credentials are configured on the Page; pass null to disable.
Send additional request headers page.setExtraHTTPHeaders(headers) Headers are sent with every request initiated by that Page. Names are lowercased, and outgoing header order is not guaranteed.
Configure a proxy server proxyServer in BrowserContextOptions The Puppeteer Next documentation says proxy username and password can be set through Page.authenticate().

Use Page.authenticate() when the server’s access challenge calls for HTTP authentication. Use setExtraHTTPHeaders() when the requirement is to attach arbitrary headers to Page-initiated requests. These are distinct documented APIs; the docs do not establish that extra headers reproduce every authentication scheme or server behavior. See the setExtraHTTPHeaders() reference and the Next BrowserContextOptions reference for proxy configuration details.

The cited proxy documentation is explicitly for the Next API. It does not specify every interaction between proxy credentials, origin credentials, multiple origins, or simultaneous challenges. If your setup has more than one kind of credential challenge, validate it against the documentation for the Puppeteer version you use and your server’s behavior.

Common problems and fixes

Symptom Likely explanation What to do
The page still asks for credentials or shows an access-denied page Credentials may be missing, incorrect, or not accepted by the target server. Confirm both environment variables are present and contain the expected values. Inspect the response status and page content. The exact result depends on the server.
username or password is undefined The process environment does not contain the configured variable. Set both values in the environment that launches Node.js. The sample deliberately throws before launching the browser when either is absent.
The request fails and there is no HTTP status to inspect A transport or navigation failure may have prevented an HTTP response. Handle the navigation error separately from HTTP status checks, and confirm the target is reachable from the browser environment.
The navigation returns an HTTP error status An HTTP error response is still a response; it is not necessarily a network-level request failure. Inspect response.status() and the returned page. Puppeteer documents that statuses such as 404 or 503 can complete with requestfinished; do not rely on requestfailed alone. See the HTTPRequest reference.
Adding extra headers does not resolve the authentication challenge Extra headers and the documented HTTP-auth API serve different purposes. Use page.authenticate() for HTTP authentication. Use extra headers only when the server expects additional request headers.
Automation becomes slower after enabling authentication Puppeteer’s documentation says authentication turns on request interception behind the scenes and might affect performance. Measure the effect in your own workload. The API documentation gives no numeric slowdown, so do not assume a particular overhead.

Performance, reliability, and credential handling

Puppeteer explicitly warns that request interception is enabled behind the scenes to implement authentication and that this might affect performance. The documentation provides no benchmark or quantified overhead. If capture speed matters, measure your actual pages and workflow rather than extrapolating a number.

For reliability, distinguish three outcomes: navigation produced no response, navigation produced an HTTP response with an error status, or the response succeeded but the page content is not what you expected. Checking response.status() helps identify the HTTP outcome; validating page content may still be necessary for an application-specific success condition.

Keep credentials outside committed source code. The environment-variable approach in the examples is one practical option; use the secret-management approach appropriate to your deployment. Avoid logging credential values when diagnosing failures.

Or skip the browser setup

For a screenshot rather than browser automation, ScreenshotNeo accepts one GET request with a URL and returns a PNG, JPEG, WebP, or PDF. Its API supports custom headers, cookies, user agents, and Authorization, along with controls such as viewport, full-page capture, waiting, and caching. See the ScreenshotNeo API documentation.

curl -G "https://api.screenshotneo.com/v1/shot" -d access_key=YOUR_API_KEY --data-urlencode url=https://stripe.com -o shot.webp
import requests

r = requests.get(
    "https://api.screenshotneo.com/v1/shot",
    params={"access_key": "YOUR_API_KEY", "url": "https://stripe.com"},
    timeout=90,
)
open("shot.webp", "wb").write(r.content)
const q = new URLSearchParams({ access_key: 'YOUR_API_KEY', url: 'https://stripe.com' });
const res = await fetch(`https://api.screenshotneo.com/v1/shot?${q}`);
  • Cookie banners are accepted and removed before capture, along with 60+ known consent platforms, newsletter popups, and chat widgets; each step can be turned off.
  • Bot checks, blank pages, timeouts, failed loads, and cache hits cost nothing. Responses indicate the page verdict and billing status in headers.
  • An MCP server provides take_screenshot, get_page_info, and capture_pdf tools for Claude, Cursor, and other MCP clients.
  • The free plan includes 1,000 screenshots a month with no card. Paid plans start at $5 for 3,000 screenshots; all features are on every plan.

Sign up free for 1,000 screenshots a month, with no card required.

FAQ

Can I turn authentication off after setting it?

Yes. Call await page.authenticate(null) to disable authentication on that Page.

Does Page.authenticate() prove that access succeeded?

No. It configures credentials. Check the response status and, when needed, validate the resulting page content.

Does Puppeteer document a fixed performance penalty?

No. The API reference warns that authentication enables request interception behind the scenes and might affect performance, but gives no measured amount.

Are custom headers and HTTP authentication interchangeable?

No equivalence is established in the cited documentation. Choose the API based on whether the requirement is HTTP-auth credentials or additional headers on Page-initiated requests.