Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Use Puppeteer’s page.setExtraHTTPHeaders() for headers on requests initiated by a browser page, and request.headers() to inspect a request object. In Angular, set headers on an individual HttpClient call or use a functional interceptor for shared behavior. These APIs operate at different layers: changing one does not automatically change requests made by the other.

Choose the API that sends the request

Before changing a header, identify which code creates the outgoing request. Puppeteer controls traffic initiated by its browser page. Angular HttpClient configures requests made by Angular application code. A Puppeteer setting is not a general setting for your whole application, and an Angular interceptor does not configure a separate Puppeteer page.

  • Use Puppeteer page-wide headers when browser-page requests need the same additional headers.
  • Use Puppeteer interception when a header should be conditional on a request, such as its URL.
  • Use Angular request options for a one-off HttpClient call.
  • Use an Angular interceptor for cross-cutting behavior shared by selected application requests.

Examples below use Puppeteer’s current API documentation, version 25.11.0 for Page.setExtraHTTPHeaders() and HTTPRequest.continue(), and 25.9.0 for HTTPRequest.headers(). Angular examples use its current official guide’s functional-interceptor approach.

Set headers for every request initiated by a Puppeteer page

Call page.setExtraHTTPHeaders() before navigation. It accepts a record whose values must all be strings and returns a promise, so await it:

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.
import puppeteer from 'puppeteer';

const browser = await puppeteer.launch();
try {
  const page = await browser.newPage();

  await page.setExtraHTTPHeaders({
    'x-client-id': 'demo',
    authorization: 'Bearer example-token',
  });

  await page.goto('https://example.com');
} finally {
  await browser.close();
}

This is the page-wide option: the additional headers apply to every request initiated by that page, not just the first document navigation. Puppeteer lowercases header names, which is ordinarily harmless because HTTP header names are case-insensitive. It does not guarantee the order of outgoing headers. Do not use this method when you need a particular header order or assume it guarantees that a credential is sent only to a particular origin.

Keep credentials scoped deliberately

A page may initiate requests to more than one destination as it loads content and runs scripts. If an authorization value should be sent only for a particular request or destination, use conditional request interception instead of applying it indiscriminately to all page traffic. Treat tokens in source code as secrets: use an appropriate secret-management mechanism in real applications, and avoid logging them while debugging.

Read request headers in Puppeteer

Listen for the page’s request event and inspect the HTTPRequest object. Its headers() method returns an object of headers associated with that request; the exposed header names are lowercase.

page.on('request', request => {
  console.log(request.url(), request.headers());
});

For example, look up request.headers()['x-client-id'], not a capitalized variant. This inspects the request object exposed by Puppeteer; it does not prove that a remote server received or accepted the header. If the question is what reached the server, compare with server-side logs or an appropriate network trace.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Log selectively

Request logs can contain authorization values, cookies, or other sensitive data. For routine diagnostics, log the URL and only the header names or non-sensitive values you need. If you must inspect a credential locally, keep the output private and remove it from logs before sharing a trace.

Change headers for selected Puppeteer requests

Use request interception when the header depends on request details. Enable interception before using request.continue() with overrides, then resolve each intercepted request by continuing, responding, or aborting it. Leaving a request unresolved can stall page loading.

await page.setRequestInterception(true);

page.on('request', request => {
  const url = new URL(request.url());

  if (url.hostname === 'example.com') {
    const headers = {
      ...request.headers(),
      'x-client-id': 'demo',
    };
    void request.continue({ headers });
  } else {
    void request.continue();
  }
});

The hostname check is an example of scoping a change; adapt the condition to the requests you intend to modify. The spread keeps the header values already exposed on the request object while adding the client ID. Puppeteer’s documented override mechanism also allows removing a header by setting its value to undefined in the overrides.

Interception checklist

  • Enable interception before navigation or before the requests you need to control.
  • Make sure every intercepted request reaches a resolution path: continue(), respond(), or abort().
  • Do not attach credentials to unrelated destinations just because they share the same page.
  • If the page stops progressing, check that the handler resolves every request and that asynchronous continuation errors are not being ignored.

Set headers on one Angular HttpClient request

For a one-off request, pass a headers option directly to the HttpClient method. Angular accepts a plain object for straightforward cases:

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.
this.http.get<Config>('/api/config', {
  headers: { 'X-Debug-Level': 'verbose' },
});

For reusable construction or more deliberate updates, create an HttpHeaders value and pass it in the options:

import { HttpHeaders } from '@angular/common/http';

const baseHeaders = new HttpHeaders().set('X-Debug-Level', 'minimal');
const requestHeaders = baseHeaders.set('X-Debug-Level', 'verbose');

this.http.get<Config>('/api/config', { headers: requestHeaders });

HttpHeaders is immutable. Methods such as .set() and .append() return a new instance rather than changing the existing one. Keep the returned value, as in requestHeaders above; calling baseHeaders.set(...) without using its return value will not update baseHeaders.

Apply shared or conditional headers with an Angular interceptor

When multiple Angular requests need the same cross-cutting behavior, use a functional interceptor. Register it with provideHttpClient(withInterceptors([...])). The interceptor below adds a client ID to requests that pass through it:

import {
  HttpEvent,
  HttpHandlerFn,
  HttpRequest,
} from '@angular/common/http';
import { Observable } from 'rxjs';

export function clientIdInterceptor(
  req: HttpRequest<unknown>,
  next: HttpHandlerFn,
): Observable<HttpEvent<unknown>> {
  const updated = req.clone({
    headers: req.headers.set('X-Client-Id', 'demo'),
  });
  return next(updated);
}

Register it in application configuration, for example:

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.
import { ApplicationConfig } from '@angular/core';
import { provideHttpClient, withInterceptors } from '@angular/common/http';

export const appConfig: ApplicationConfig = {
  providers: [
    provideHttpClient(withInterceptors([clientIdInterceptor])),
  ],
};

Requests and their headers are immutable too. Clone the request with the updated headers and pass that clone to next; do not try to mutate the original request. Interceptors suit shared authentication, logging, or other application-wide behavior, but scope them appropriately, especially when adding credentials.

Observe a response in an interceptor

An interceptor can also inspect the observable returned by next(req). To read response fields, transform that observable and check for the final response event rather than assuming every emitted event is a response:

import { HttpEvent, HttpHandlerFn, HttpRequest, HttpResponse } from '@angular/common/http';
import { Observable, tap } from 'rxjs';

export function responseLogInterceptor(
  req: HttpRequest<unknown>,
  next: HttpHandlerFn,
): Observable<HttpEvent<unknown>> {
  return next(req).pipe(
    tap(event => {
      if (event instanceof HttpResponse) {
        console.log('Response status:', event.status);
      }
    }),
  );
}

This observes a response event; it is not a way to inspect the outgoing request as though Angular and Puppeteer shared a browser-page request object. Keep logs free of tokens and other sensitive values.

What each option controls

Code path Scope Use it when Important limit
Puppeteer page.setExtraHTTPHeaders() Additional headers on every request initiated by the page The same headers should apply across page traffic Not a per-origin guarantee; header order is not guaranteed
Puppeteer interception and request.continue({ headers }) Selected intercepted requests Header changes depend on URL or request details Every intercepted request must be resolved
Angular HttpClient options One application request A header is needed for one call Does not configure unrelated requests or Puppeteer traffic
Angular functional interceptor Requests flowing through the configured Angular client Behavior is shared or conditional across application calls Scope credentials and other sensitive headers carefully
Independent reader supportYour contribution helps us test, update, and keep practical guides available for everyone.Support on Ko-Fi

Troubleshooting common header problems

The header is missing from Puppeteer traffic

  • For page-wide headers, confirm the awaited setExtraHTTPHeaders() call happens before the relevant navigation or request.
  • For an interception override, confirm interception was enabled and that the request takes the branch that supplies the override.
  • Check the lowercase key in request.headers(). The method exposes lowercase names.
  • Do not infer server receipt from Puppeteer’s request object alone; compare with server logs or a network trace when that distinction matters.

The page stalls after enabling interception

Inspect the request handler for paths that return without continuing, responding, or aborting the intercepted request. A conditional handler needs a resolution path for both matching and non-matching URLs. Also handle failures from asynchronous request operations if your application needs to diagnose them.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.
Best Value
The SQL Programming Language: .
  • Used Book in Good Condition

An Angular header update appears to do nothing

Check that you used the value returned by HttpHeaders.set(). Likewise, an interceptor must clone the immutable HttpRequest and pass the clone to next. Verify that the request actually goes through the configured Angular HttpClient rather than a different request-producing layer.

A header is on the wrong requests

Replace a page-wide setting with Puppeteer interception and a URL condition, or narrow the Angular interceptor’s behavior to the intended requests. In either case, do not apply authorization credentials broadly unless every destination in scope is meant to receive them.

Performance, reliability, and cost considerations

For a constant page-wide header in Puppeteer, use the page-wide setting rather than enabling interception solely to add the same value everywhere. Interception gives request-by-request control but requires a handler to resolve every intercepted request, which adds work and creates a possible stall point. In Angular, a direct option keeps a one-call change local; an interceptor centralizes shared behavior but should stay narrow enough that unrelated calls are not altered.

Header APIs configure requests; they do not by themselves guarantee that a server accepts a value or that a request succeeds. Diagnose the request at the layer that actually sends it, and distinguish a client-side request representation from what the server logged.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Or skip the browser setup

If your goal is to get a website screenshot rather than inspect or alter arbitrary browser traffic, ScreenshotNeo offers a screenshot API and MCP server. Its API supports custom headers, cookies, user agents, and Authorization, but it is not a general replacement for Puppeteer request inspection or Angular application networking. A single GET request can return a screenshot or PDF. For example, using cURL:

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

See the ScreenshotNeo documentation for API details. Cookie and consent banners, newsletter popups, and chat widgets are removed before capture; those cleanup steps can be turned off. Bot checks, blank pages, failed loads, timeouts, and cache hits are not billed, and response headers indicate the page verdict and billing status. 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 per month with no card. Paid plans start at $5 for 3,000 shots; all features are available on every plan, and yearly billing gives two months free. Sign up for ScreenshotNeo’s free plan.

Product prices and availability are accurate as of the date/time indicated and are subject to change. Any price and availability information displayed on Amazon at the time of purchase will apply.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.