Latenode

Intercepting and Modifying Network Requests in Puppeteer: A Practical Guide

Learn how to intercept and modify network requests in Puppeteer for efficient web automation, testing, and performance optimization.

RaianRaian
Intercepting and Modifying Network Requests in Puppeteer: A Practical Guide

Intercepting and modifying network requests in Puppeteer is a powerful way to manage web automation tasks. It allows you to monitor, block, or adjust HTTP requests and responses in real-time. Here's what you can do:

  • Monitor Network Activity: Log details like URLs, methods, headers, and payloads.
  • Modify Requests: Change headers, redirect URLs, or adjust payloads for API testing and debugging.
  • Block Resources: Prevent loading of images, fonts, or scripts to improve performance.
  • Simulate Responses: Mock server responses for testing or alter content dynamically.
  • Test Error Scenarios: Simulate HTTP status codes like 404 or 500 to test error handling.

Quick Example

<span class="hljs-keyword">await</span> page.<span class="hljs-title function_">setRequestInterception</span>(<span class="hljs-literal">true</span>);
page.<span class="hljs-title function_">on</span>(<span class="hljs-string">&#x27;request&#x27;</span>, <span class="hljs-title function_">async</span> (request) =&gt; {
    <span class="hljs-keyword">if</span> (request.<span class="hljs-title function_">url</span>().<span class="hljs-title function_">includes</span>(<span class="hljs-string">&#x27;/api/test&#x27;</span>)) {
        <span class="hljs-keyword">await</span> request.<span class="hljs-title function_">respond</span>({
            <span class="hljs-attr">status</span>: <span class="hljs-number">200</span>,
            <span class="hljs-attr">contentType</span>: <span class="hljs-string">&#x27;application/json&#x27;</span>,
            <span class="hljs-attr">body</span>: <span class="hljs-title class_">JSON</span>.<span class="hljs-title function_">stringify</span>({ <span class="hljs-attr">success</span>: <span class="hljs-literal">true</span> })
        });
    } <span class="hljs-keyword">else</span> {
        <span class="hljs-keyword">await</span> request.<span class="hljs-title function_">continue</span>();
    }
});

This guide explains how to use Puppeteer’s API for request interception, including practical examples for monitoring, modifying, and testing network interactions.

Puppeteer Tutorial #12 | HTTP Interceptors | Intercept Requests

Monitoring Network Requests

Puppeteer makes it possible to monitor network requests, giving you a clear view of web traffic during automation tasks. Here's how you can track and analyze network activity effectively.

Setting Up Request Listeners

Start by enabling request interception and attaching a listener. Here's an example:

<span class="hljs-keyword">await</span> page.<span class="hljs-title function_">setRequestInterception</span>(<span class="hljs-literal">true</span>);
page.<span class="hljs-title function_">on</span>(<span class="hljs-string">&#x27;request&#x27;</span>, <span class="hljs-title function_">async</span> (request) =&gt; {
    <span class="hljs-keyword">if</span> (request.<span class="hljs-title function_">isInterceptResolutionHandled</span>()) <span class="hljs-keyword">return</span>;
    <span class="hljs-variable language_">console</span>.<span class="hljs-title function_">log</span>(<span class="hljs-string">`Intercepted: <span class="hljs-subst">${request.url()}</span>`</span>);
    <span class="hljs-keyword">await</span> request.<span class="hljs-title function_">continue</span>();
});

Inside the 'request' event listener, you can access and even modify intercepted requests. Just make sure to call request.continue() so the original request isn't blocked.

Filtering Requests by Type

Puppeteer lets you filter network requests based on their type, making it easier to focus on specific traffic. Here's how you can handle requests selectively:

page.<span class="hljs-title function_">on</span>(<span class="hljs-string">&#x27;request&#x27;</span>, <span class="hljs-function"><span class="hljs-params">interceptedRequest</span> =&gt;</span> {
    <span class="hljs-keyword">if</span> (interceptedRequest.<span class="hljs-title function_">isInterceptResolutionHandled</span>()) <span class="hljs-keyword">return</span>;
    <span class="hljs-keyword">const</span> resourceType = interceptedRequest.<span class="hljs-title function_">resourceType</span>();
    <span class="hljs-keyword">switch</span>(resourceType) {
        <span class="hljs-keyword">case</span> <span class="hljs-string">&#x27;image&#x27;</span>:
            <span class="hljs-comment">// Handle image requests</span>
            <span class="hljs-keyword">break</span>;
        <span class="hljs-keyword">case</span> <span class="hljs-string">&#x27;xhr&#x27;</span>:
            <span class="hljs-comment">// Handle API calls</span>
            <span class="hljs-keyword">break</span>;
        <span class="hljs-attr">default</span>:
            interceptedRequest.<span class="hljs-title function_">continue</span>();
    }
});

By categorizing and prioritizing resource types, you can streamline your network monitoring efforts and focus on what matters most.

Logging Request Data

Once you've filtered the requests, logging their key details can help you uncover useful patterns. Here's a quick overview of some important request properties:

Request PropertyDescriptionAccess Method
URLFull request URLrequest.url()
MethodHTTP method (e.g., GET, POST)request.method()
HeadersRequest headersrequest.headers()
Post DataPayload sent with the requestrequest.postData()

For example, if you want to monitor API requests for pricing data:

page.<span class="hljs-title function_">on</span>(<span class="hljs-string">&#x27;request&#x27;</span>, <span class="hljs-title function_">async</span> (request) =&gt; {
    <span class="hljs-keyword">if</span> (request.<span class="hljs-title function_">url</span>().<span class="hljs-title function_">includes</span>(<span class="hljs-string">&#x27;/api/prices&#x27;</span>)) {
        <span class="hljs-keyword">const</span> requestData = {
            <span class="hljs-attr">url</span>: request.<span class="hljs-title function_">url</span>(),
            <span class="hljs-attr">method</span>: request.<span class="hljs-title function_">method</span>(),
            <span class="hljs-attr">postData</span>: request.<span class="hljs-title function_">postData</span>()
        };
        <span class="hljs-variable language_">console</span>.<span class="hljs-title function_">log</span>(<span class="hljs-string">&#x27;Price Request:&#x27;</span>, requestData);
    }
    <span class="hljs-keyword">await</span> request.<span class="hljs-title function_">continue</span>();
});

This method allows you to analyze traffic in detail. Always check request.isInterceptResolutionHandled() to prevent conflicts with other handlers.

Changing Outgoing Requests

With Puppeteer, you can tweak outgoing requests to better suit your needs when interacting with web servers.

Header Modifications

You can adjust HTTP headers to include tokens, change user agents, or add custom values.

<span class="hljs-keyword">await</span> page.<span class="hljs-title function_">setExtraHTTPHeaders</span>({
    <span class="hljs-string">&#x27;Authorization&#x27;</span>: <span class="hljs-string">&#x27;Bearer YOUR_TOKEN&#x27;</span>,
    <span class="hljs-string">&#x27;Custom-Header&#x27;</span>: <span class="hljs-string">&#x27;CustomValue&#x27;</span>
});

For more granular control over individual requests:

page.<span class="hljs-title function_">on</span>(<span class="hljs-string">&#x27;request&#x27;</span>, <span class="hljs-title function_">async</span> (request) =&gt; {
    <span class="hljs-keyword">if</span> (request.<span class="hljs-title function_">isInterceptResolutionHandled</span>()) <span class="hljs-keyword">return</span>;
    <span class="hljs-keyword">const</span> headers = request.<span class="hljs-title function_">headers</span>();
    headers[<span class="hljs-string">&#x27;Authorization&#x27;</span>] = <span class="hljs-string">&#x27;Bearer YOUR_TOKEN&#x27;</span>;
    <span class="hljs-keyword">await</span> request.<span class="hljs-title function_">continue</span>({ headers });
});

"Request interception facilitates modification of outgoing requests' properties, such as setting custom headers, altering request methods, or adjusting the request payload." - Saairaamprasad [1]

Next, let’s look at rerouting requests by redirecting URLs.

URL Redirections

Redirect specific requests using the following approach:

<span class="hljs-keyword">await</span> page.<span class="hljs-title function_">setRequestInterception</span>(<span class="hljs-literal">true</span>);
page.<span class="hljs-title function_">on</span>(<span class="hljs-string">&#x27;request&#x27;</span>, <span class="hljs-title function_">async</span> (request) =&gt; {
    <span class="hljs-keyword">if</span> (request.<span class="hljs-title function_">url</span>().<span class="hljs-title function_">includes</span>(<span class="hljs-string">&#x27;/api/original&#x27;</span>)) {
        <span class="hljs-keyword">await</span> request.<span class="hljs-title function_">continue</span>({
            <span class="hljs-attr">url</span>: request.<span class="hljs-title function_">url</span>().<span class="hljs-title function_">replace</span>(<span class="hljs-string">&#x27;/api/original&#x27;</span>, <span class="hljs-string">&#x27;/api/new&#x27;</span>)
        });
    } <span class="hljs-keyword">else</span> {
        <span class="hljs-keyword">await</span> request.<span class="hljs-title function_">continue</span>();
    }
});

This method helps you change API endpoints or reroute requests dynamically.

Request Data Changes

You can also modify payloads for POST and PUT requests. Here’s how:

page.<span class="hljs-title function_">on</span>(<span class="hljs-string">&#x27;request&#x27;</span>, <span class="hljs-title function_">async</span> (request) =&gt; {
    <span class="hljs-keyword">if</span> (request.<span class="hljs-title function_">isInterceptResolutionHandled</span>()) <span class="hljs-keyword">return</span>;

    <span class="hljs-keyword">if</span> (request.<span class="hljs-title function_">url</span>().<span class="hljs-title function_">includes</span>(<span class="hljs-string">&#x27;/api/prices&#x27;</span>) &amp;&amp; request.<span class="hljs-title function_">method</span>() === <span class="hljs-string">&#x27;POST&#x27;</span>) {
        <span class="hljs-keyword">let</span> postData = request.<span class="hljs-title function_">postData</span>();
        <span class="hljs-keyword">if</span> (postData) {
            postData = postData.<span class="hljs-title function_">replace</span>(<span class="hljs-regexp">/11001/g</span>, <span class="hljs-string">&#x27;90210&#x27;</span>);
            <span class="hljs-keyword">await</span> request.<span class="hljs-title function_">continue</span>({ postData });
            <span class="hljs-keyword">return</span>;
        }
    }
    <span class="hljs-keyword">await</span> request.<span class="hljs-title function_">continue</span>();
});

Here’s a quick reference for modifying different request properties:

Request PropertyHow to ModifyCommon Use Cases
Headerscontinue({ headers })Adding authentication tokens, custom identifiers
URLcontinue({ url })Redirecting endpoints, rerouting requests
Post Datacontinue({ postData })Updating form data, altering API payloads

Note: Changing requests can affect performance, so it’s best to intercept only when necessary. These methods provide you with precise control over outgoing requests in your automation workflows.

Managing Server Responses

Puppeteer allows you to handle and modify server responses, making it a powerful tool for web automation. This section builds on earlier techniques for request modification and focuses on controlling server responses to give you full control over network interactions.

Response Monitoring

You can track incoming server responses by setting up a response event listener:

page.<span class="hljs-title function_">on</span>(<span class="hljs-string">&#x27;response&#x27;</span>, <span class="hljs-title function_">async</span> (response) =&gt; {
    <span class="hljs-keyword">const</span> url = response.<span class="hljs-title function_">url</span>();
    <span class="hljs-keyword">const</span> status = response.<span class="hljs-title function_">status</span>();
    <span class="hljs-variable language_">console</span>.<span class="hljs-title function_">log</span>(<span class="hljs-string">`Response from <span class="hljs-subst">${url}</span>: <span class="hljs-subst">${status}</span>`</span>);

    <span class="hljs-keyword">if</span> (response.<span class="hljs-title function_">url</span>().<span class="hljs-title function_">includes</span>(<span class="hljs-string">&#x27;/api/prices&#x27;</span>)) {
        <span class="hljs-keyword">const</span> data = <span class="hljs-keyword">await</span> response.<span class="hljs-title function_">json</span>();
        <span class="hljs-comment">// Process response data</span>
    }
});

This snippet logs details like the URL, status codes, and headers, helping you analyze how the server behaves. Beyond monitoring, you can modify response content dynamically to suit your needs.

Modifying Response Content

To customize how responses are handled, use interception. Here's an example:

page.<span class="hljs-title function_">on</span>(<span class="hljs-string">&#x27;request&#x27;</span>, <span class="hljs-title function_">async</span> (request) =&gt; {
    <span class="hljs-keyword">if</span> (request.<span class="hljs-title function_">url</span>().<span class="hljs-title function_">includes</span>(<span class="hljs-string">&#x27;/api/prices&#x27;</span>)) {
        <span class="hljs-keyword">await</span> request.<span class="hljs-title function_">respond</span>({
            <span class="hljs-attr">status</span>: <span class="hljs-number">200</span>,
            <span class="hljs-attr">contentType</span>: <span class="hljs-string">&#x27;application/json&#x27;</span>,
            <span class="hljs-attr">body</span>: <span class="hljs-title class_">JSON</span>.<span class="hljs-title function_">stringify</span>({
                <span class="hljs-attr">price</span>: <span class="hljs-number">99.99</span>,
                <span class="hljs-attr">currency</span>: <span class="hljs-string">&#x27;USD&#x27;</span>,
                <span class="hljs-attr">zipCode</span>: <span class="hljs-string">&#x27;90210&#x27;</span>
            })
        });
        <span class="hljs-keyword">return</span>;
    }
    <span class="hljs-keyword">await</span> request.<span class="hljs-title function_">continue</span>();
});

This technique is particularly useful for testing APIs by mocking responses or tweaking data in specific scenarios.

Testing HTTP Status Codes

Once you’ve mastered modifying content, you can simulate various HTTP status codes to test error handling. Here’s how:

Status CodeUse CaseImplementation Example
200Success responsestatus: 200, body: JSON.stringify(successData)
404Missing resourcestatus: 404, body: 'Not Found'
500Server errorstatus: 500, body: 'Internal Server Error'

For example:

page.<span class="hljs-title function_">on</span>(<span class="hljs-string">&#x27;request&#x27;</span>, <span class="hljs-title function_">async</span> (request) =&gt; {
    <span class="hljs-keyword">if</span> (request.<span class="hljs-title function_">url</span>().<span class="hljs-title function_">includes</span>(<span class="hljs-string">&#x27;/api/test-endpoint&#x27;</span>)) {
        <span class="hljs-keyword">await</span> request.<span class="hljs-title function_">respond</span>({
            <span class="hljs-attr">status</span>: <span class="hljs-number">404</span>,
            <span class="hljs-attr">contentType</span>: <span class="hljs-string">&#x27;text/plain&#x27;</span>,
            <span class="hljs-attr">body</span>: <span class="hljs-string">&#x27;Not Found!&#x27;</span>
        });
        <span class="hljs-keyword">return</span>;
    }
    <span class="hljs-keyword">await</span> request.<span class="hljs-title function_">continue</span>();
});

"Request interception in Puppeteer allows you to observe, modify, or block outgoing HTTP requests and incoming responses. This feature is handy when optimizing page loading, simulating various network conditions, or handling dynamic content loading." – Saairaamprasad [1]

Pro Tip: While intercepting responses can be powerful, use it sparingly. Overusing interception might slow down your automation scripts or introduce unnecessary complexity.

sbb-itb-23997f1

Request Interception Guidelines

Request interception is a powerful tool, but it requires careful use to ensure smooth performance and maintain reliability. Below are practical steps for managing sessions, improving speed, and resolving common issues.

Managing User Sessions

Here’s how you can handle user sessions effectively:

<span class="hljs-keyword">await</span> page.<span class="hljs-title function_">setRequestInterception</span>(<span class="hljs-literal">true</span>);
page.<span class="hljs-title function_">on</span>(<span class="hljs-string">&#x27;request&#x27;</span>, <span class="hljs-title function_">async</span> (request) =&gt; {
    <span class="hljs-keyword">if</span> (!request.<span class="hljs-title function_">isInterceptResolutionHandled</span>()) {
        <span class="hljs-keyword">const</span> headers = request.<span class="hljs-title function_">headers</span>();
        headers[<span class="hljs-string">&#x27;Authorization&#x27;</span>] = <span class="hljs-string">&#x27;Bearer &#x27;</span> + yourAuthToken;
        <span class="hljs-keyword">await</span> request.<span class="hljs-title function_">continue</span>({ headers });
    }
});

Always check the interception status before modifying headers to avoid conflicts with other interceptors.

Speed Optimization

Blocking unnecessary resources can significantly cut down page load times - sometimes by as much as 500 milliseconds [3]. Here’s an example:

<span class="hljs-keyword">await</span> page.<span class="hljs-title function_">route</span>(<span class="hljs-string">&#x27;**/*&#x27;</span>, <span class="hljs-function">(<span class="hljs-params">route</span>) =&gt;</span> {
    <span class="hljs-keyword">const</span> resourceType = route.<span class="hljs-title function_">request</span>().<span class="hljs-title function_">resourceType</span>();
    <span class="hljs-keyword">if</span> ([<span class="hljs-string">&#x27;image&#x27;</span>, <span class="hljs-string">&#x27;stylesheet&#x27;</span>, <span class="hljs-string">&#x27;font&#x27;</span>].<span class="hljs-title function_">includes</span>(resourceType)) {
        route.<span class="hljs-title function_">abort</span>();
        <span class="hljs-keyword">return</span>;
    }
    route.<span class="hljs-title function_">continue</span>();
});
Resource TypeActionImpact
ImagesBlockSpeeds up page loading
StylesheetsSelective loadingSaves bandwidth
AnalyticsBlockReduces network overhead
API CallsAllowKeeps essential functionality

When performance issues occur, these resource management strategies can help.

Troubleshooting Tips

Improper handling is a common source of issues. Here are some practical fixes:

"Once request interception is enabled, every request will stall unless it's continued, responded or aborted."

  • Antoine Vastel, Head of Research at Castle [4]
  1. Resolution Handling: Use isInterceptResolutionHandled checks to prevent race conditions.
  2. Multiple Handlers: Assign priorities when using multiple intercept handlers:
<span class="hljs-keyword">await</span> request.<span class="hljs-title function_">continue</span>({
    <span class="hljs-attr">priority</span>: <span class="hljs-number">1</span>,
    <span class="hljs-attr">headers</span>: modifiedHeaders
});
  1. Stalled Requests: Ensure all requests are resolved properly:
page.<span class="hljs-title function_">on</span>(<span class="hljs-string">&#x27;request&#x27;</span>, <span class="hljs-title function_">async</span> (request) =&gt; {
    <span class="hljs-keyword">try</span> {
        <span class="hljs-keyword">if</span> (!request.<span class="hljs-title function_">isInterceptResolutionHandled</span>()) {
            <span class="hljs-keyword">await</span> request.<span class="hljs-title function_">continue</span>();
        }
    } <span class="hljs-keyword">catch</span> (error) {
        <span class="hljs-variable language_">console</span>.<span class="hljs-title function_">error</span>(<span class="hljs-string">&#x27;Request handling error:&#x27;</span>, error);
        <span class="hljs-keyword">await</span> request.<span class="hljs-title function_">abort</span>();
    }
});

Keep your interception logic straightforward. Overcomplicated rules can slow things down and make your code harder to maintain.

Key Takeaways

Puppeteer's request interception provides developers with powerful tools to refine web automation tasks. These tools allow for:

  • Request Modification: Adjust headers, methods, and payloads to control data flow effectively.
  • Response Handling: Customize server responses for various testing needs.
  • Resource Management: Improve performance by selectively handling requests.

Practical Applications

Request interception has proven helpful in many scenarios. For instance, in a recent e-commerce case, modifying product price requests based on zip codes demonstrated its utility [2].

Some common uses include:

  • Mocking API responses for testing
  • Enhancing data scraping by modifying headers
  • Boosting load speeds by blocking unnecessary resources
  • Strengthening security with custom authentication tokens

These examples highlight how request interception can address both development and operational challenges, paving the way for advanced automation techniques.

Using Puppeteer with Latenode

Latenode simplifies implementing these strategies. Here's a sample workflow to show how Puppeteer integrates with Latenode:

<span class="hljs-comment">// Example workflow setup in Latenode</span>
<span class="hljs-keyword">await</span> page.<span class="hljs-title function_">setRequestInterception</span>(<span class="hljs-literal">true</span>);
page.<span class="hljs-title function_">on</span>(<span class="hljs-string">&#x27;request&#x27;</span>, <span class="hljs-title function_">async</span> (request) =&gt; {
    <span class="hljs-keyword">if</span> (request.<span class="hljs-title function_">resourceType</span>() === <span class="hljs-string">&#x27;fetch&#x27;</span>) {
        <span class="hljs-keyword">const</span> modifiedHeaders = {
            ...request.<span class="hljs-title function_">headers</span>(),
            <span class="hljs-string">&#x27;Custom-Header&#x27;</span>: <span class="hljs-string">&#x27;Modified-Value&#x27;</span>
        };
        <span class="hljs-keyword">await</span> request.<span class="hljs-title function_">continue</span>({ <span class="hljs-attr">headers</span>: modifiedHeaders });
    }
});

This example demonstrates how you can modify request headers dynamically to suit your specific needs.

Related posts

Raian

Researcher, Nocode Expert

Author details →