How to Block Requests with Puppeteer
Use Puppeteer request interception to block selected URLs or resource types while letting the rest of the page load.
To block selected network requests with Puppeteer, enable interception before navigation, then inspect each request and call abort() for matches and continue() for everything else. Every intercepted request must be resolved or it will remain stalled.
The examples below use current Puppeteer APIs. For the complete request interception API and version-specific details, see the official Request Interception guide and HTTPRequest API.
Block requests by resource type
Use request.resourceType() when the goal is to block a class of resources, such as images or fonts. The returned type is the rendering engine’s classification; it is not necessarily the file extension or MIME type.
const puppeteer = require('puppeteer');
(async () => {
const browser = await puppeteer.launch({ headless: true });
try {
const page = await browser.newPage();
await page.setRequestInterception(true);
page.on('request', request => {
if (request.isInterceptResolutionHandled()) return;
const blockedTypes = new Set(['image', 'font', 'media']);
if (blockedTypes.has(request.resourceType())) {
request.abort();
} else {
request.continue();
}
});
await page.goto('https://example.com', { waitUntil: 'domcontentloaded' });
await page.screenshot({ path: 'page.png', fullPage: true });
} finally {
await browser.close();
}
})();
Remove resource types from blockedTypes when the page needs them. For example, blocking stylesheets can make the page faster to fetch but changes its layout and may make selectors or visual checks unreliable. Blocking scripts can prevent the application from rendering at all.
Block requests by URL
Use the request URL when you need to target a host, path, or known endpoint. Match parsed URL fields instead of relying on fragile suffixes when query strings, redirects, or alternate URL forms are possible.
const puppeteer = require('puppeteer');
(async () => {
const browser = await puppeteer.launch({ headless: true });
try {
const page = await browser.newPage();
const blockedHosts = new Set(['analytics.example', 'ads.example']);
await page.setRequestInterception(true);
page.on('request', request => {
if (request.isInterceptResolutionHandled()) return;
let shouldBlock = false;
try {
const url = new URL(request.url());
shouldBlock = blockedHosts.has(url.hostname) ||
url.pathname.startsWith('/tracking/');
} catch {
// A malformed or nonstandard URL is allowed by this example.
}
if (shouldBlock) request.abort();
else request.continue();
});
await page.goto('https://example.com', { waitUntil: 'networkidle2' });
await page.screenshot({ path: 'page.png', fullPage: true });
} finally {
await browser.close();
}
})();
Be precise with host matching. A substring check such as url.includes('example.com') can also match notexample.com or a URL whose query string merely contains that text. Compare hostname to an exact host or a deliberately checked subdomain suffix.
Install and run
- Install Node.js and create a project directory.
- Run
npm install puppeteer. Puppeteer downloads a compatible Chrome for Testing by default; installation and browser setup are described in the official installation guide. - Save either example above as
block.js. - Run
node block.js. The screenshot is written topage.png.
On servers or containers, configure the runtime’s required system dependencies as described by Puppeteer’s installation documentation. Avoid adding browser launch flags that disable isolation unless your deployment environment requires and secures that configuration.
Choose the right interception action
| Action | Use it when | Notes |
|---|---|---|
request.abort() |
The matching request should fail without reaching its destination. | Requires interception. It accepts an optional error code and, in cooperative mode, a numeric priority. |
request.continue() |
The request should proceed. | Can take overrides such as headers or method. Resolve all requests you do not block. |
request.respond() |
You need a mock response, such as a local JSON fixture. | Supply a response object. Mocking data: URL requests is unsupported, and respond() is a no-op for those requests. |
For example, a mock response can replace a known API endpoint during a test:
page.on('request', request => {
if (request.isInterceptResolutionHandled()) return;
if (request.url() === 'https://example.com/api/feature') {
request.respond({
status: 200,
contentType: 'application/json',
body: JSON.stringify({ enabled: false })
});
} else {
request.continue();
}
});
Prevent double resolution
Another event listener or package may already have resolved a request. Check request.isInterceptResolutionHandled() before acting. Keep the check and the call to abort(), continue(), or respond() together without an intervening await: another handler could resolve the request while asynchronous work is in progress.
page.on('request', async request => {
// Do asynchronous work first, if needed.
const shouldBlock = await policyCheck(request.url());
// Recheck immediately before resolution; another handler may have acted.
if (request.isInterceptResolutionHandled()) return;
if (shouldBlock) request.abort();
else request.continue();
});
In the async example, do not check the handled state before await policyCheck(...) and rely on that earlier result. The final check must remain adjacent to the resolution call.
Use cooperative interception when handlers must work together
By default, a resolution call without a priority takes effect immediately. In Cooperative Intercept Mode, handlers pass numeric priorities to abort(), continue(), or respond(); the highest priority wins. Ties resolve in this order: abort, respond, then continue. All resolving handlers must provide numeric priorities for cooperative resolution. A handler using legacy resolution can still resolve immediately.
const { DEFAULT_INTERCEPT_RESOLUTION_PRIORITY } = require('puppeteer');
page.on('request', request => {
if (request.isInterceptResolutionHandled()) return;
if (request.url().includes('/tracking/')) {
request.abort('blockedbyclient', 5);
} else {
request.continue({}, DEFAULT_INTERCEPT_RESOLUTION_PRIORITY);
}
});
Use priority voting when multiple known handlers need to express preferences. For a single handler, ordinary immediate resolution is simpler. Continue to check the handled state because a third-party or legacy handler may not participate in cooperative resolution.
Alternative: URL patterns in ConnectOptions
Puppeteer’s ConnectOptions includes allowlist and blocklist URL patterns. These use the standard URLPattern API and, according to the current API reference, work only for Chrome while Puppeteer is attached to Chrome DevTools Protocol targets. Requests outside an allowlist or matching a blocklist fail.
This can be a useful additional guardrail when a URL-pattern policy is enough. Page-level interception is more flexible when you need per-request logic, resource-type matching, or mocked responses. ConnectOptions URL patterns are not a complete network sandbox: browser features or other network paths may bypass the network service. For complete network isolation, Puppeteer recommends a container or operating-system-level sandbox.
Consult the ConnectOptions API reference for the exact option shape for your installed Puppeteer version.
Performance, reliability, and cost
- Performance: Blocking large images, media, or third-party trackers can reduce transferred data and sometimes shorten navigation. The result depends on the site and what it needs to render. Interception adds a handler decision for each request; keep matching logic small and avoid unnecessary asynchronous work.
- Reliability: Install interception and its handler before
goto(), including before any code that can trigger navigation. Explicitly resolve every request. Pick a navigation condition that fits the page:domcontentloadedavoids waiting for every resource, while network-idle conditions can be unreliable on pages with persistent polling or sockets. - Visual correctness: Blocking images, fonts, stylesheets, or scripts changes the rendered output. Validate screenshots and page behavior with the same block rules used in production.
- Cost: Puppeteer is open-source software, but running it consumes your own compute, browser memory, bandwidth, and operational time. The dossier provides no universal benchmark or hosting price; measure against your workload and infrastructure.
Troubleshooting
| Symptom | Likely cause | Fix |
|---|---|---|
| Navigation hangs or times out after enabling interception. | A request was neither continued, aborted, nor fulfilled. | Make every handler resolve every unhandled request, including the allow path. Register it before navigation. |
| Error says the request is already handled or interception resolution failed. | A different listener or package resolved it first, or an async gap allowed a race. | Check isInterceptResolutionHandled() immediately before resolution and keep that check adjacent to the action. |
| Some unwanted traffic still appears. | The URL condition misses query strings, redirects, alternate subdomains, or a different resource type. | Log request.url() and request.resourceType(), then refine matching based on observed requests. Use exact hostname/path rules where possible. |
| The page is blank or controls do not work. | Scripts, stylesheets, or API calls needed for rendering were blocked. | Temporarily allow those types or endpoints, identify required requests, and narrow the rule. |
| ConnectOptions patterns appear ignored. | The browser or target is not supported, or Puppeteer is not attached through the documented Chrome DevTools Protocol path. | Check the current ConnectOptions documentation and use page-level interception if it better fits the environment. |
| Mocked response has no effect. | The request may be a data: URL, for which respond() is unsupported, or another handler may have resolved it. |
Mock a network request and check the handled state immediately before responding. |
Or skip the browser setup
If the goal is a screenshot rather than browser-network testing, ScreenshotNeo is a website screenshot API and MCP server. Its one-call API returns an image or PDF, with request options and 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, popups, and chat widgets are removed before the shot; each step can be turned off.
- Bot checks, blank pages, timeouts, failed loads, and cache hits are never billed. Response headers say which page verdict and billing result applied.
- An MCP server offers
take_screenshot,get_page_info, andcapture_pdftools for Claude, Cursor, and other MCP clients. - 1,000 screenshots a month are free with no card. Paid plans start at $5 for 3,000 screenshots; all features are on every plan.
Create a free account and get 1,000 screenshots a month with no card.
FAQ
Does aborting a request stop it from being sent?
It tells Puppeteer to abort the intercepted request. It is not a general network security boundary; use operating-system or container controls when you need complete network isolation.
Can I block requests before creating a page?
Page interception is enabled on a page with page.setRequestInterception(true). Enable it and attach the handler before navigating so the target page’s requests are covered.
Can I block by file extension?
Yes, with URL matching, but extensions can be misleading when URLs have query strings or endpoints return varied content. Resource type or parsed URL fields may better express the rule.
Can I use the same rule for every page?
Attach a shared setup function to each page you create, and apply it to newly created pages or targets if your workflow opens them. Interception is configured per page.


