Puppeteer is a robust Node.js library that provides high-level APIs for controlling Chrome or Chromium via the Chrome DevTools Protocol. Two powerful capabilities—circumventing same-origin restrictions and entercepting network requests—are essential for scenarios like local development against remote APIs and testing network behavior.
Bypassing Same-Origin Constraints
The same-origin policy is a critical browser security mechanism that prevents documants from different origins from interacting with each other. However, during local development, you may need to call production APIs from localhost. Chrome allows disabling these restrictions through command-line flags.
To launch Pupeteer without same-origin limitations, pass the --disable-web-security flag in the args array:
const puppeteer = require('puppeteer');
const browserConfig = {
headless: 'new',
devTools: true,
defaultViewport: { width: 1366, height: 768 },
args: [
'--disable-web-security',
'--no-sandbox',
'--disable-setuid-sandbox'
]
};
const browserInstance = await puppeteer.launch(browserConfig);
const page = await browserInstance.newPage();
This configuration creates a browser instance where cross-origin requests proceed without CORS restrictions, enabling seamless API communication during development.
Controlling Network Traffic with Request Interception
The setRequestInterception method enables complete control over outgoing requests, allowing you to block, modify, or mock responses before they reach the network.
Blocking Unwanted Resources
You can significantly speed up page loads by aborting requests for non-critical assets like images or fonts:
await page.setRequestInterception(true);
page.on('request', (interceptedReq) => {
const resourceUrl = interceptedReq.url();
const blockedExtensions = /\.(svg|gif|woff2?)$/i;
if (blockedExtensions.test(resourceUrl)) {
interceptedReq.abort();
} else {
interceptedReq.continue();
}
});
await page.goto('https://example.com');
Mocking Server Responses
Instead of letting requests hit actual endpoints, you can return fabricated responses for testing edge cases:
await page.setRequestInterception(true);
page.on('request', (incomingRequest) => {
if (incomingRequest.url().includes('/api/user')) {
incomingRequest.respond({
status: 200,
contentType: 'application/json',
headers: { 'Access-Control-Allow-Origin': '*' },
body: JSON.stringify({
id: 123,
username: 'test-user',
mockData: true
})
});
} else {
incomingRequest.continue();
}
});
Modifying Requests Dynamically
Inspect and alter request parameters mid-flight to test different scenarios or inject authentication tokens:
await page.setRequestInterception(true);
page.on('request', (mutableReq) => {
const currentHeaders = mutableReq.headers();
const modifiedOptions = {
headers: {
...currentHeaders,
'X-Custom-Header': 'injected-value',
'Authorization': `Bearer ${process.env.API_TOKEN}`
}
};
// Conditionally modify POST data
if (mutableReq.method() === 'POST' && mutableReq.postData()) {
try {
const originalData = JSON.parse(mutableReq.postData());
modifiedOptions.postData = JSON.stringify({
...originalData,
timestamp: Date.now(),
environment: 'testing'
});
} catch (e) {
// Continue with original data if parsing fails
}
}
mutableReq.continue(modifiedOptions);
});
This approach allows you to transform request payloads, update authentication credentials, or redirect requests to different endpoints without changing your application code.