Utilizing headless Chrome to automatically capture AJAX requests

Chrome officially supports running the browser in headless mode, allowing for programmatic control through the Puppeteer API and/or the CRI library.

I've thoroughly explored the documentation but have not discovered a method to programmatically capture AJAX traffic from instances. I am looking to start a Chrome instance from code, navigate to a page, and access background response/request calls and raw data all within the code without using developer tools or extensions.

If you have any suggestions or examples on how this can be accomplished, I would greatly appreciate it. Thank you!

Answer №1

Update

In the comment, @Alejandro highlighted that the function resourceType returns a value in lowercase.

page.on('request', request => {
    if (request.resourceType() === 'xhr')
    // do something
});

Original answer

Puppeteer's API simplifies this process:

page.on('request', request => {
  if (request.resourceType === 'XHR')
    // do something
});

You can intercept requests using setRequestInterception, but it's unnecessary here unless you plan to modify the requests.

An example of intercepting image requests is available for reference.

The definitions of resourceTypes can be found here.

Answer №2

After much searching, I have finally discovered a way to achieve my goal. Utilizing chrome-remote-interface (CRI) and node.js, this can be accomplished with the following minimal code snippet.

const CDP = require('chrome-remote-interface');

(async function () {

    // Make sure you have an open Chrome instance with remote debugging enabled
    // For example, run: chrome --remote-debugging-port=9222
    const protocol = await CDP({port: 9222});

    const {Page, Network} = protocol;
    await Page.enable();
    await Network.enable(); // This is necessary in order to use Network.getResponseBody below

    Page.navigate({url: 'http://localhost/'}); // Replace 'http://localhost/' with your desired URL

    const onDataReceived = async (e) => {
        try {
            let response = await Network.getResponseBody({requestId: e.requestId})
            if (typeof response.body === 'string') {
                console.log(response.body);
            }
        } catch (ex) {
            console.log(ex.message)
        }
    }

    protocol.on('Network.dataReceived', onDataReceived)
})();

Answer №3

Using Puppeteer's listeners can assist in capturing xhr responses by utilizing the response and request events.

It is advisable to first verify if request.resourceType() is either xhr or fetch.

        listener = page.on('response', response => {
            const isXhr = ['xhr','fetch'].includes(response.request().resourceType())
            if (isXhr){
                console.log(response.url());
                response.text().then(console.log)
            }
        })

Answer №4

const browser = await puppeteer.launch();
const page = await browser.newPage();
const clientPage = page["_client"];
clientPage.on("Network.responseReceived", event => {
  if (~event.response.url.indexOf('/api/chart/rank')) {
    console.log(event.response.url);
    clientPage.send('Network.getResponseBody', {
      requestId: event.requestId
    }).then(async response => {
      const data = response.body;
      if (data) {
        try {
          const jsonData = JSON.parse(data);

        }
        catch (e) {
        }
      }
    });
  }
});

await page.setRequestInterception(true);
page.on("request", async request => {
  request.continue();
});
await page.goto('http://www.example.com', { timeout: 0 });

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

How to resolve a TypeError saying "Object(...) is not a function"?

I've been attempting to display material-ui tabs as a component on another page, but I'm encountering an error that causes the code to break when loading the page with this component. I've tried two different methods of rendering this compo ...

Adjusting the color of a box in Threejs through dat.gui.min.js controls

I want to enhance the user experience by allowing them to choose a color from the HEX menu and update the color of the box in the scene using UI controls. Below is the JavaScript code I have implemented for this purpose: // author: Arielle Mueller // date ...

Determining the emptiness of an array in Postman using node.js

When I receive a response, it is in the following format: { "test1": [], "test2": [], "test3": [], "test4": null, "test5": [] } This is the response that I get after making a request. I need to verify whether test1 is empty or not. ...

Prevent the browser back button from being used in a web application that requires CLIENT_CERT authentication

My website utilizes CLIENT_CERT JAAS authentication and is compatible with IE7. After logging out, when I return to the home page and click on the back button, I want to stay on the same non-secure page. I have been able to achieve this using the history. ...

Repeated URL causes Node to redirect

I am currently working on a project that involves redirecting users if they enter a specific URL, especially for redirecting from a Heroku domain. During my testing phase on localhost, I noticed that the redirect URL keeps getting repeated: http://localh ...

Tips for populating countryList data in Form.Select component within a React.js application

I have a data file that contains a list of all countries, and I need to display these countries in a select input field, similar to what you see on popular websites when a user logs in and edits their profile information like name, address, and country. H ...

Create an Oval-Shaped Image Cutout

Currently, I have a fabric.JS canvas where objects can be added. However, I am interested in clipping these objects into an oval shape, similar to the clip demos on fabricjs.com. In my current project (JSFiddle), I have been able to crop the object into a ...

"Encountering an issue with AngularJS where the selected ng-model value is

I'm utilizing plain options for the select tag because I only need to display a few options when they meet a certain condition. In order to perform other operations, I require the value of the selected dropdown in the controller. However, the issue is ...

The scrolltop animation does not appear to be functioning properly on iOS devices

I have implemented a JavaScript effect to increase the line-height of each list item on my website as you scroll. It works perfectly on my Macbook and Android Smartphone, but for some reason, it's not working on an iPhone. Can anyone provide a solutio ...

Can a single endpoint be used to provide files to web browsers and data to REST requests simultaneously?

I recently completed a tutorial that lasted 7 hours on creating a blog, following it almost completely. The only step I skipped was setting up separate client/server hosting as suggested in the tutorial. Instead, I have a single Heroku server serving the c ...

Using a JSON file as a database for a project featuring HTML, CSS, and Vanilla JavaScript

Our task was to create a project that exclusively utilized JSON files for data storage. The data structure we were working with resembles the following: [ { "aircraftName": "Boeing 747", "departDate": 1640173020000, ...

Use ng-repeat to extract information from an array and populate it into a datalist

I've already tried searching for a solution to my issue on Google, but I couldn't find anything that really helped me. I'm looking to create an input field that also functions like a dropdown. This way, I can either type in my own data or se ...

Scatter plot showcasing repeated values along the x-axis

When creating a scatter chart using an ajax call, I encountered a situation where some values on the x-axis were duplicated while the values on the y-axis were different. For example: { "cols": [ {"id":"","label":"Sold Year ...

JavaScript was unable to locate the requested URL on the server

After successfully deploying and accessing the URL using Firebase's hosting feature, everything seems to work fine. However, when I try to access a specific endpoint like this: https://*******.web.app/api/send, I encounter the following error message: ...

I am experiencing an issue with applying responsiveFontSize() to the new variants in Material UI Typography

I am looking to enhance the subtitles in MUI Typography by adding new variants using Typescript, as outlined in the documentation here. I have defined these new variants in a file named global.d.ts, alongside other customizations: // global.d.ts import * a ...

BookshelfJS: Establishing a One-to-One Relationship

Within my database, I am working with two tables - User and Address. The User table consists of the following two methods: shippingAddress: function() { var Address = require(appRoot + '/config/db').model('Address'); return thi ...

What is the best way to display a segment of an SVG on a Canvas element?

Main Issue: The main objective here is to display a specific part of an SVG image on a fixed size Canvas element within a web page. Approach I Tried: After considering various options, such as using CanVG, I thought about utilizing the viewBox attribute ...

Tips for smoothly adding new content to a jQuery AJAX autoupdating div

I'm currently working on a div that pulls data from an external PHP file, which loops through results from a MySQL query. My goal is to have this div update every 5 seconds using AJAX, with only the new results smoothly fading in at the top of the lis ...

What is the best way to share information among Vue3 single file component instances?

I am seeking a way to have certain data in my single file component shared among all instances on the page, similar to how static variables work in PHP/C. To achieve this, I understand that in single file components, we declare data as a function like so: ...

Navigating an indefinite amount of state variables in React.js: A comprehensive guide

Receiving data from the server with an unknown number of items in the API leads me to utilize the map method in HTML for rendering. Below is the return section: if (loading) { return ( <div> <div> <Header /> ...