> ## 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.

# Intercept & Modify Network Requests in Web Automation (Selenium, Playwright, etc.)

**Requestly Interceptor** is a powerful browser extension that allows developers and QAs to intercept and modify HTTP requests. It offers features like:

* HTTP header modifications

* URL redirects

* Request and response body overrides

* Injecting custom CSS and JavaScript

In this guide, we’ll show you how to use Requestly Interceptor in an end-to-end (E2E) web testing framework.

### What You Can Do with Requestly Interceptor in Automation For now

There are **2 main ways** to use Requestly Interceptor in an automation environment:

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

1. **Header Modifications**, quick, one-off rules (no API key required)

2. **Import Rules via API Key**, for predefined rules managed from your Requestly Interceptor account

### Header Modifications

If you only need simple header overrides (without API key), like adding or removing request/response headers, refer to this page:\
[Modify HTTP Headers →](https://interceptor-docs.requestly.com/guides/modify-http-headers-in-web-automation-using-requestly.md)

### Import Rules via API Key

**1. Configure Rules in a Team Workspace and Get API Key**

Start by creating the rules you want to use in a new team workspace. Once the rules are set up, request an API key for the workspace by filling out [**this form**](https://app.formbricks.com/s/clryn62s316gjdeho9j03t7oa). The rules in this workspace will be automatically fetched and applied during the end-to-end (E2E) testing in the browser instance.

**2. 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.

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

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

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

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

**4. 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/).

**5. 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
> ```

**6. (Optional) 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}
> const { closeWelcomePage } = require("@requestly/rq-automation");
> await closeWelcomePage(driver);
> ```

**7. Import Rules from Requestly Interceptor**

Visit the following URL in your automated browser to import all active rules from your account:

> [tab] Normal way
>
> ```java theme={null}
> https://app.requestly.io/automation?apiKey=<YOUR_API_KEY>
> ```

> [tab] NPM package
>
> ```javascript theme={null}
> const { importRules } = require("@requestly/rq-automation");
>
> // this will return an URL to import rules 
> importRules("YOUR_API_KEY") 
> // https://app.requestly.io/automation?apiKey=<YOUR_API_KEY>
> ```

![](https://mintcdn.com/interceptor/fhZRboFseopn8ocm/images/intercepting-and-modifying-network-requests-in-web-automation-frameworks-like-selenium-and-playwright/5f80987d-31ef-464c-90d0-212f05503041.png?fit=max\&auto=format\&n=fhZRboFseopn8ocm\&q=85\&s=81c48d819db9e2536564ebba5cfdfe50)


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