Block Unneeded Browser Resources with Puppeteer Request Interception
Speed up Puppeteer navigation by aborting images, stylesheets, and fonts before they download.
17 Jul 2025, 09:59 UTC

Problem: Your Puppeteer script downloads assets it never uses
When Puppeteer navigates to a page, Chromium requests everything the page references: hero images, web fonts, stylesheets, tracking beacons, and videos. If your script only needs to read a table, click a button, or assert text content, most of those bytes are wasted. On metered connections or large test suites, the extra requests add seconds to every navigation and increase the chance of a flaky timeout.
Takeaway: Abort non-essential request types before they download
Puppeteer can intercept every network request issued by a page, including subframes and redirects. By calling page.setRequestInterception(true), you pause each request and decide whether to let it continue or abort it. Blocking categories such as image, stylesheet, and font reduces transferred bytes and often shortens load time, without touching the HTML your script actually parses.
Enable interception and abort selectively
Run this in a Node.js script where Puppeteer is installed. No special operating-system permissions are required beyond the ability to launch a browser process.
const puppeteer = require('puppeteer');
(async () => {
const browser = await puppeteer.launch();
const page = await browser.newPage();
// Pause every request so Puppeteer can inspect it.
await page.setRequestInterception(true);
page.on('request', (request) => {
const type = request.resourceType();
const blocked = ['image', 'stylesheet', 'font'];
if (blocked.includes(type)) {
request.abort();
} else {
request.continue();
}
});
await page.goto('https://example.com', { waitUntil: 'networkidle2' });
// Your scraping or test steps go here.
await browser.close();
})();
Place await page.setRequestInterception(true) immediately after creating the page and before navigation. The request event fires for every network request, so the handler runs within Puppeteer's request loop.
Diagnose which resource types appear on your target
Before you block anything, log the categories Chromium assigns. Some XHR and fetch calls are reported as other, so a broad rule can accidentally kill API traffic your page depends on.
page.on('request', (request) => {
console.log(request.resourceType(), request.url());
request.continue();
});
Run the script against a representative page and review the output. If you see requests appearing as other, keep those in the continue() branch and only abort types you have confirmed are unnecessary, such as decorative images or icon fonts.
Trade-offs and limitations
- Layout breakage: Aborting stylesheets or fonts can shift elements, break selectors that depend on rendered dimensions, and invalidate visual regression baselines.
- Hidden API traffic: Requests categorized as
otherinclude many XHR and fetch calls. Blockingotherindiscriminately will break authentication, search, or data endpoints. - Protocol overhead: Interception routes traffic through the DevTools Protocol, adding modest per-request latency and disabling some Chromium network optimizations. On very simple pages, the overhead can outweigh the savings.
- Service workers and redirects: Pages that rely on service workers or specific header chains may fail when requests are aborted or modified.
Verify the result before you ship it
There is no server state to roll back, but you should treat the interception handler as a configuration change and test it on a sample of real pages.
- Run the target navigation with interception disabled and record the finish time and transferred bytes.
- Enable interception with your abort rules and run the same navigation again.
- Compare navigation timing and check the network log for fewer completed requests.
- If the page looks broken or API calls fail, narrow the abort list to only the resource types that are truly non-essential.
To check the result programmatically, log request.resourceType() for at least 20 requests on a sample page and confirm none of your required API endpoints appear in the blocked list.
Closing steps
- Add
await page.setRequestInterception(true)to your Puppeteer setup. - Implement a handler that aborts only verified non-essential types.
- Run a before-and-after comparison on a real page.
- If you see layout shifts or missing data, remove the corresponding type from the abort list.
Request interception is a practical way to cut bandwidth and stabilize Puppeteer navigation, but it works best when you block by evidence rather than assumption.
0 replies
A thoughtful contribution can make all the difference. Be the first to share one.