Some links on this page are affiliate links: if you buy through them we may earn a commission, at no extra cost to you.
Enable request interception before navigation, abort requests whose URL starts with data:image/, and continue every other request. The complete Puppeteer pattern is:
await page.setRequestInterception(true);
page.on('request', request => {
if (request.url().startsWith('data:image/')) {
return request.abort();
}
return request.continue();
});
Install the listener before page.goto(). If you want to block all images rather than only data-URI images, use the request resource type instead; that also blocks ordinary remote image URLs.
What this filter blocks—and what it leaves alone
A data URI embeds bytes directly in a URL, for example data:image/png;base64,.... The narrow filter matches the data:image/ prefix, so it targets image data URIs while allowing HTTP(S) images, scripts, stylesheets, fonts, XHR, and other requests to proceed.
This is different from filtering on request.resourceType() === 'image'. Resource-type filtering catches every image request, including images fetched from a remote server. Choose the URL-prefix test when your requirement is specifically “do not load images embedded as data URIs.”
#1 Best Overall
Complete Puppeteer implementation
Minimal script
const puppeteer = require('puppeteer');
(async () => {
const browser = await puppeteer.launch({headless: true});
const page = await browser.newPage();
await page.setRequestInterception(true);
page.on('request', request => {
if (request.url().startsWith('data:image/')) {
return request.abort();
}
return request.continue();
});
await page.goto('https://example.com', {
waitUntil: 'networkidle2'
});
await page.screenshot({path: 'page.png', fullPage: true});
await browser.close();
})();
The interception switch must be enabled before the page navigates. Registering the handler immediately afterward ensures that requests created during navigation are handled. Replace the example URL with your target.
Why every request must be settled
Puppeteer’s API reference explains: “Once request interception is enabled, every request will stall unless it’s continued, responded to or aborted; or completed using the browser cache.” Your listener therefore needs an outcome on every path. The matching branch calls abort(); the fallback calls continue(). Omitting the fallback can leave page loads waiting indefinitely.
The API reference documents Page.setRequestInterception(), HTTPRequest.abort(), and HTTPRequest.continue() at Puppeteer’s request-interception documentation.
Free tools Windows power users keep installed
One-click scans. No signup required.
TypeScript/modern module form
import puppeteer from 'puppeteer';
const browser = await puppeteer.launch({ headless: true });
const page = await browser.newPage();
await page.setRequestInterception(true);
page.on('request', request => {
const url = request.url();
if (url.startsWith('data:image/')) {
request.abort().catch(() => {});
} else {
request.continue().catch(() => {});
}
});
try {
await page.goto('https://example.com', { waitUntil: 'domcontentloaded' });
await page.screenshot({ path: 'page.png' });
} finally {
await browser.close();
}
The guarded promise handling is useful when a page closes or a request is already completed while your handler is running. In a simple script, returning the promise as in the first example is sufficient; do not call both abort() and continue() for the same request.
Register interception at the right time
- Create the browser and page. Launch Puppeteer and open a new page.
- Enable interception. Await
page.setRequestInterception(true). - Attach the listener. Add the
page.on('request', ...)handler. - Navigate. Call
page.goto()only after the listener exists. - Capture or inspect the page. Continue with screenshots, PDF generation, extraction, or tests.
Turning interception on after goto() cannot retroactively block requests already issued. If your application reuses a page, install the handler once and keep it active, or disable interception before replacing it with another handler.
Rank #2
Choosing a matching strategy
Only data-URI images
page.on('request', request => {
if (request.url().startsWith('data:image/')) {
return request.abort();
}
return request.continue();
});
This preserves external images and all non-image traffic. The prefix also covers common MIME types such as data:image/png, data:image/jpeg, and data:image/svg+xml.
Every image request
page.on('request', request => {
if (request.resourceType() === 'image') {
return request.abort();
}
return request.continue();
});
Use this when the goal is a text-only or image-free render. It is broader: remote images, same-origin images, and other image resources are all candidates. Puppeteer’s API example uses URL filtering and describes that example as naïve; a deliberate resource-type or URL condition is safer than assuming that an extension identifies every image. See the API reference.
Quick wins for a faster PC:
Repair Windows errors before they cause bigger problemsFix Now →Scan for outdated or missing drivers - takes under a minuteDriver Scan →Clear out junk files and repair common Windows errorsFree Scan →Allowlist selected resource types
const allowed = new Set(['document', 'script', 'xhr', 'fetch']);
page.on('request', request => {
if (allowed.has(request.resourceType())) {
return request.continue();
}
return request.abort();
});
Chrome for Developers shows this style for server-side rendering: continue document, script, xhr, and fetch, then abort other types. It blocks substantially more than data-URI images and can change layout, fonts, CSS, and application behavior. Treat it as a separate optimization, not as a replacement for the narrow filter. The guidance is at Chrome for Developers.
Logging and verifying what Puppeteer sees
When you are unsure whether a page creates a data URI, log the URL and resource type before applying the condition:
page.on('request', request => {
const url = request.url();
const type = request.resourceType();
console.log(type, url.slice(0, 160));
if (url.startsWith('data:image/')) {
return request.abort();
}
return request.continue();
});
Use a short prefix in logs rather than printing an entire base64 payload. A data URI can be very large and may contain content you do not want in logs. For a deterministic test, load a local page containing an <img src="data:image/png;base64,...">, listen for request events, and verify the image is not rendered while an ordinary https:// image still is.
Request interception behavior can vary with Puppeteer and Chromium versions or with how a page creates the resource. If your listener never observes the URL, verify the behavior in the exact runtime you deploy instead of assuming every browser path exposes it through the interceptor.
What’s actually slowing this PC down?
Pick the symptom - the matching free tool is one click away.
Common failures and fixes
The page hangs after interception is enabled
Cause: A branch neither aborts, continues, nor responds. Fix: Keep an unconditional fallback such as return request.continue(); also check that no earlier listener handles the request and leaves it unresolved.
External images disappeared too
Cause: The handler tests request.resourceType() === 'image' or aborts every URL containing an image-related string. Fix: Restrict the condition to request.url().startsWith('data:image/').
Data-URI images still appear
Cause: The listener was registered after navigation, the URL uses a different scheme or casing, or the page creates the element after your test. Fix: Enable interception and attach the listener before goto(); log URLs; test the exact page state after scripts run. The documented prefix is lowercase data:image/; if your application can emit uppercase variants, normalize only after confirming that behavior, for example request.url().toLowerCase().startsWith('data:image/').
“Request is already handled” errors
Cause: Multiple listeners or asynchronous code try to settle one request twice. Fix: Use one interception owner, return immediately after abort(), and avoid mixing independent handlers that both call continue(). If several modules must observe requests, have one coordinator make the final decision.
Rank #4
The page breaks after broad blocking
Cause: An allowlist or all-image rule removed a resource the application needs, such as a CSS background, font, or image used by a script. Fix: Start with the data-URI prefix rule, then add narrowly justified conditions. Compare screenshots and console errors before expanding the block.
Trying to use Chrome URL blocklists as a drop-in replacement
Puppeteer’s current ConnectOptions reference describes experimental allowlist and blocklist URL patterns for Chrome 149+. They apply while Puppeteer is attached to CDP targets, and the documentation cautions that network-service controls are not a complete network sandbox. Consider them only when broad browser URL restrictions are appropriate; a request-level data-image filter remains the clearer choice for this task. See Puppeteer ConnectOptions.
Performance, reliability, and security considerations
Performance
Aborting an unwanted request prevents that resource from completing, but the cited documentation does not provide a benchmark for data-URI filtering. Do not promise a fixed speedup. Measure your own workload with and without interception, especially when pages contain large embedded images.
Reliability
Keep the rule deterministic and narrow. Use waitUntil: 'domcontentloaded' when you do not need every network request to settle, or networkidle2 when your capture depends on later application work. Neither setting changes which requests the handler can abort.
Recommended Free Tools
Security boundary
Request interception is a page-loading control, not a complete network sandbox. It does not replace Chromium isolation, operating-system controls, outbound firewall rules, or input validation. Treat target URLs and any custom headers or cookies as untrusted data.
Best Value
Or skip the browser setup
If you only need a clean website screenshot, ScreenshotNeo provides a single API call instead of maintaining Puppeteer interception code:
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 parameters and response details. The service accepts consent banners like a visitor and removes more than 60 known consent platforms, newsletter popups, and chat widgets before capture; each cleanup step can be turned off. Bot checks or CAPTCHAs, blank pages, timeouts, failed loads, and cache hits are not billed, and response headers identify the page verdict and billing result.
For scripts, the same endpoint works with Python:
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)
Or Node.js:
const q = new URLSearchParams({ access_key: 'YOUR_API_KEY', url: 'https://stripe.com' });
const res = await fetch(`https://api.screenshotneo.com/v1/shot?${q}`);
ScreenshotNeo also offers an MCP server with take_screenshot, get_page_info, and capture_pdf tools for Claude, Cursor, and other MCP clients. Every plan includes its features; 1,000 screenshots per month are free without a card, and paid plans start at $5 for 3,000 shots. Create a free ScreenshotNeo account to try it.
Windows Errors? Fix Them Before They Spread
Repair common Windows errors and clear accumulated junk for a smoother, more stable PC - no reinstall needed.Free scan · no reinstallOutdated Drivers Are Slowing You Down
One free scan finds every outdated or missing driver and matches the right update for your exact hardware.Free scan · exact hardware matchFrequently Asked Questions
Does this block CSS images such as background-image data URIs?
The URL-prefix condition targets requests whose URL starts with data:image/. Verify your Chromium/Puppeteer version and page behavior, because resources created through different browser paths may not appear identically in the request event stream.
Can I abort a request and then inspect its response?
No. Once you abort a request it will not produce a normal response. Log the URL before aborting if you need diagnostics.
Is interception enabled per browser or per page?
Call setRequestInterception(true) on each Page that should intercept requests; a separate page requires its own setup.
Quick Recap
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.

