> ## Documentation Index
> Fetch the complete documentation index at: https://interceptor-docs.requestly.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Modify HTTP Headers in Web Automation Using Requestly Interceptor

In this guide, we’ll walk through how to integrate Requestly Interceptor into any browser-based automation framework (Selenium, Playwright, Puppeteer, etc.) to programmatically modify request and response headers.

### Steps to Use Requestly Interceptor for Header Modification in Automation

> [!TIP]
>
> We also offer an NPM package, **@requestly/rq-automation**, to make this easier.\
> [`Learn more →`](https://github.com/requestly/requestly-automation)

**1. Install Chrome for Testing**

Download [**Chrome for Testing**](https://googlechromelabs.github.io/chrome-for-testing), the automation-friendly version of Chrome.

> [!NOTE]
>
> **Why Chrome for Testing?**
>
> Starting with Chrome 137, official Chrome builds **no longer support the** `--load-extension` flag due to security concerns. [`There commit →`](https://chromium.googlesource.com/chromium/src/+/290ed8046692651ce76088914750cb659b65fb17%5E%21/chrome/browser/extensions/extension_service.cc)
>
> To load extensions in automation tools (Selenium, Playwright, Puppeteer, etc.), you **must use Chrome for Testing** or Chromium.
>
> Regular Chrome will block extension loading via automation. Use Chrome for Testing to avoid breakages and ensure compatibility.

**2. Install the Automation Tool of Your Choice**

> [tab] Selenium
>
> ```bash theme={null}
> npm install selenium-webdriver
> ```

> [tab] Playwright
>
> ```bash theme={null}
> npm install playwright
> ```

> [tab] Puppeteer
>
> ```bash theme={null}
> npm install puppeteer
> ```

**3. Download the Requestly Interceptor CRX Extension**

> [!TIP]
>
> If you're using our NPM package, you don’t need to download it. Simply call the function `getExtension()`.

Download the CRX file of the [Requestly Interceptor Extension](https://requestly.com/downloads/crx/).

**4. Configure the Browser with the Extension**

Use your automation tool’s configuration options to:

* Set the path to Chrome for Testing binary

* Add the Requestly Interceptor CRX extension

> [!TIP]
>
> For JavaScript, use our NPM package `@requestly/rq-automation`.\
> [`Learn more →`](https://github.com/requestly/requestly-automation)

> [tab] Selenium
>
> For Javascript ( Node.js )
>
> ```javascript theme={null}
> const { Builder } = require("selenium-webdriver");
> const chrome = require("selenium-webdriver/chrome");
> const path = require("path");
> const extensionPath = path.resolve(__dirname, 'requestly.crx'); // unpacked CRX folder
>
> // IF Using Our NPM Package @requestly/rq-automation
> // const { getExtension } = require("@requestly/rq-automation");
> // const extensionPath = getExtension("crx");
> // -----
>
> const options = new chrome.Options();
> options.setChromeBinaryPath("/Path/to/chrome-for-testing"); 
> options.addExtensions(extensionPath);  
>
> const driver = await new Builder()
>   .forBrowser("chrome")
>   .setChromeOptions(options)
>   .build();
> // Now use driver.get() to navigate as needed...
> ```
>
> For Python
>
> ```python theme={null}
> from selenium import webdriver
> from selenium.webdriver.chrome.options import Options
>
> chrome_options = Options()
> chrome_options.binary_location = "/Path/to/chrome-for-testing"
> chrome_options.add_extension("/path/to/requestly.crx")
>
> driver = webdriver.Chrome(options=chrome_options)
> # driver.get(...) to open pages
> ```
>
> For Java
>
> ```java theme={null}
> ChromeOptions options = new ChromeOptions();
> options.setBinary("/Path/to/chrome-for-testing");
> options.addExtensions(new File("/path/to/requestly.crx"));
> WebDriver driver = new ChromeDriver(options);
> // driver.get(...) to open pages
> ```

> [tab] Playwright
>
> For Javascript ( Node.js )
>
> ```javascript theme={null}
> const { chromium } = require('playwright');
> const extensionPath = require('path').resolve(__dirname, 'requestly'); // unpacked CRX folder
>
> // IF Using Our NPM Package @requestly/rq-automation
> // const { getExtension } = require("@requestly/rq-automation");
> // const extensionPath = getExtension("unpacked");
> // -----
>
> const userDataDir = './user-data';
>
> const context = await chromium.launchPersistentContext(userDataDir, {
>   channel: "chromium", // Enable extensions
>   headless: false, // Set to true only if you handle '--headless=new'
>   args: [
>       `--disable-extensions-except=${extensionPath}`,
>       `--load-extension=${extensionPath}`,
>     ],
>   });
>
> const page = await context.newPage();
> // Use page.goto(...) next
> ```
>
> For Python
>
> ```python theme={null}
> from playwright.sync_api import sync_playwright
>
> path_to_ext = "./requestly"   # path to unpacked CRX folder
> user_data_dir = "/tmp/user-data-dir"
>
> with sync_playwright() as pw:
>     context = pw.chromium.launch_persistent_context(
>         user_data_dir,
>         channel="chromium",
>         headless=False,
>         args=[
>             f"--disable-extensions-except={path_to_ext}",
>             f"--load-extension={path_to_ext}"
>         ]
>     )
>     page = context.new_page()
>     # use page.goto(...)
>     context.close()
> ```

> [tab] Puppeteer
>
> For Javascript ( Node.js )
>
> ```javascript theme={null}
> const puppeteer = require('puppeteer');
> const path = require('path');
> const extensionPath = path.resolve(__dirname, 'requestly'); 
>
> // IF Using Our NPM Package @requestly/rq-automation
> // const { getExtension } = require("@requestly/rq-automation");
> // const extensionPath = getExtension("unpacked");
> // -----
>
> const browser = await puppeteer.launch({
>   executablePath: "/Path/to/chrome-for-testing",
>   headless: false,
>   args: [
>     `--disable-extensions-except=${extensionPath}`,
>     `--load-extension=${extensionPath}`
>   ]
> });
> const page = await browser.newPage();
> // page.goto(...) next
> ```

**5. Close Extension Welcome Page**

When Chrome installs the Requestly Interceptor extension, it may open a "welcome" (post-install) tab that interrupts automation. You can close this tab programmatically:

> [tab] Selenium
>
> ```javascript theme={null}
>   // give Chrome a moment for any stray tabs
>   await driver.sleep(500);
>
>   // close any “welcome” tab if still present
>   const handles = await driver.getAllWindowHandles();
>   const mainHandle = handles[0];
>   for (const handle of handles.slice(1)) {
>     await driver.switchTo().window(handle);
>     await driver.close();
>   }
>   await driver.switchTo().window(mainHandle)
> ```

> [tab] Playwright
>
> ```javascript theme={null}
>   const page = await context.newPage(); // Assume the first one is your primary page
>   await page.waitForTimeout(2000);
>   // Get all open pages in the current context
>   const pages = context.pages();
>   // Iterate through the pages and close any that are not the primary 'page' object
>   for (const openedPage of pages) {
>     if (openedPage !== page) {
>       console.log(`Closing extraneous page: ${openedPage.url()}`);
>       await openedPage.close();
>     }
>    }
>   // page.goto(...) next
> ```

> [tab] Puppeteer
>
> ```javascript theme={null}
>   const pages = await browser.pages();
>   const page = pages[0]; // Assume the first one is your primary page
>
>   await page.waitForTimeout(2000);
>
>   // Close all other pages except the primary one
>   for (const openedPage of pages) {
>     if (openedPage !== page) {
>       console.log(`Closing extraneous page: ${openedPage.url()}`);
>       await openedPage.close();
>     }
>   }
> ```

> [tab] With NPM Package
>
> ```javascript theme={null}
> // FOR SELENIUM ONLY
> const { closeWelcomePage } = require("@requestly/rq-automation");
> await closeWelcomePage(driver);
> ```

**6. Perform Header Modifications Using Automation URLs**

Once the browser is launched with Requestly Interceptor, hit the following URLs to programmatically apply rules:

> [tab] Normal way
>
> #### Add Request Header
>
> > [!TIP]
> >
> > To add multiple headers, simply append them using the `&` symbol like this:\
> > `?header1=value1&header2=value2&header3=value3`
>
> ```bash theme={null}
> https://app.requestly.io/automation/add-request-header?<headerName>=<headerValue>
> ```
>
> #### Add Response Header
>
> ```bash theme={null}
> https://app.requestly.io/automation/add-response-header?<headerName>=<headerValue>
> ```
>
> #### Remove Request Headers
>
> > [!TIP]
> >
> > To remove multiple headers, simply append them using the `&` symbol like this:\
> > `?header1&header2&header3`
>
> ```bash theme={null}
> https://app.requestly.io/automation/remove-request-header?<headerName>
> ```
>
> #### Remove Response Headers
>
> ```bash theme={null}
> https://app.requestly.io/automation/remove-response-header?<headerName>
> ```

> [tab] NPM package
>
> ```javascript theme={null}
> const {
>   addRequestHeaderUrl,
>   addRequestHeadersUrl,
>   removeRequestHeaderUrl,
>   removeRequestHeadersUrl,
>   addResponseHeaderUrl,
>   addResponseHeadersUrl,
>   removeResponseHeaderUrl,
>   removeResponseHeadersUrl,
> } = require("@requestly/rq-automation");
>
>  // Add a single request header
>   await driver.get(addRequestHeaderUrl("X-Custom-Header", "MyValue"));
>
>   // Add multiple request headers
>   await driver.get(
>     addRequestHeadersUrl({
>       Authorization: "Bearer token123",
>       "X-Another-Header": "AnotherValue",
>     })
>   );
>
>   // Remove a request header
>   await driver.get(removeRequestHeaderUrl("X-Another-Header"));
>
>   // Remove multiple request headers
>   await driver.get(
>     removeRequestHeadersUrl(["Authorization", "X-Custom-Header"])
>   );
>
>   // Add a response header
>   await driver.get(addResponseHeaderUrl("Access-Control-Allow-Origin", "*"));
>
>   // Add multiple response headers
>   await driver.get(
>     addResponseHeadersUrl({
>       "X-Response-Header": "ResponseValue",
>       "X-Another-Response-Header": "AnotherResponseValue",
>     })
>   );
>
>   // Remove a response header
>   await driver.get(removeResponseHeaderUrl("X-Another-Response-Header"));
>
>   // Remove multiple response headers
>   await driver.get(
>     removeResponseHeadersUrl(["X-Response-Header", "X-Another-Response-Header"])
>   );
> ```

**7. Test on a Live Site**

To verify if the headers are successfully modified, open [https://testheaders.com](https://testheaders.com) in the automated browser and inspect the headers shown.

*You may need to trigger a button click to reveal headers on some pages.*

### Complete Working Example in Selenium ( Javascript )

Here’s a working example using **Selenium**, but this logic can be adapted easily to **Playwright**, **Puppeteer**, or others.

> [tab] Normal way
>
> ```javascript theme={null}
> const { Builder, By, until } = require("selenium-webdriver");
> const chrome = require("selenium-webdriver/chrome");
> const path = require("path");
>
> (async () => {
>   const options = new chrome.Options();
>
>   options.setChromeBinaryPath("/Path/to/chrome-for-testing");
>   options.addExtensions(path.resolve(__dirname, "requestly.crx"));
>
>   const driver = await new Builder()
>     .forBrowser("chrome")
>     .setChromeOptions(options)
>     .build();
>
>   // give Chrome a moment for any stray tabs
>   await driver.sleep(500);
>
>   // close any “welcome” tab if still present
>   const handles = await driver.getAllWindowHandles();
>   const mainHandle = handles[0];
>   for (const handle of handles.slice(1)) {
>     await driver.switchTo().window(handle);
>     await driver.close();
>   }
>   await driver.switchTo().window(mainHandle)
>
>   try {
>     await driver.get("https://app.requestly.io/automation/add-request-header?x-testing=selenium");
>
>     await driver.wait(
>       until.elementTextContains(
>         driver.findElement(By.tagName("body")),
>         "Success"
>       ),
>       1000
>     );
>
>     await driver.get("https://testheaders.com");
>
>     await driver.findElement(By.css("button")).click();
>
>     await driver.wait(
>       until.elementTextContains(
>         driver.findElement(By.tagName("body")),
>         "x-testing"
>       ),
>       5000
>     );
>
>     console.log("Header added and verified!");
>
>   } catch (err) {
>     console.error("Error during automation:", err);
>   } finally {
>     await driver.quit();
>   }
> })();
> ```

> [tab] NPM package
>
> ```javascript theme={null}
> const {
>   addRequestHeaderUrl,
>   addRequestHeadersUrl,
>   removeRequestHeaderUrl,
>   removeRequestHeadersUrl,
>   addResponseHeaderUrl,
>   addResponseHeadersUrl,
>   removeResponseHeaderUrl,
>   removeResponseHeadersUrl,
>   importRules,
>   closeWelcomePage,
> } = require("@requestly/rq-automation");
> const { Builder } = require("selenium-webdriver");
> const chrome = require("selenium-webdriver/chrome");
> const { getExtension } = require("@requestly/rq-automation");
>
> async function setupDriver() {
>   const options = new chrome.Options();
>
>   // Load Requestly Interceptor extension
>   const extensionPath = getExtension("unpacked");
>   options.addArguments(`--load-extension=${extensionPath}`);
>   options.addArguments(`--disable-extensions-except=${extensionPath}`);
>
>   const driver = await new Builder()
>     .forBrowser("chrome")
>     .setChromeOptions(options)
>     .build();
>
>   return driver;
> }
>
> async function seleniumExample() {
>   const driver = await setupDriver();
>   await closeWelcomePage(driver);
>
>   // Add a single request header
>   await driver.get(addRequestHeaderUrl("X-Custom-Header", "MyValue"));
>
>   // Add multiple request headers
>   await driver.get(
>     addRequestHeadersUrl({
>       Authorization: "Bearer token123",
>       "X-Another-Header": "AnotherValue",
>     })
>   );
>
>   // Remove a request header
>   await driver.get(removeRequestHeaderUrl("X-Another-Header"));
>
>   // Remove multiple request headers
>   await driver.get(
>     removeRequestHeadersUrl(["Authorization", "X-Custom-Header"])
>   );
>
>   // Add a response header
>   await driver.get(addResponseHeaderUrl("Access-Control-Allow-Origin", "*"));
>
>   // Add multiple response headers
>   await driver.get(
>     addResponseHeadersUrl({
>       "X-Response-Header": "ResponseValue",
>       "X-Another-Response-Header": "AnotherResponseValue",
>     })
>   );
>
>   // Remove a response header
>   await driver.get(removeResponseHeaderUrl("X-Another-Response-Header"));
>
>   // Remove multiple response headers
>   await driver.get(
>     removeResponseHeadersUrl(["X-Response-Header", "X-Another-Response-Header"])
>   );
>
>   // Import a shared list of rules
>   await driver.get(importRules("YOUR_API_KEY"));
>
>   // Your test code here
>   await driver.get("https://example.com");
>
>   await driver.quit();
> }
>
> seleniumExample();
> ```


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.