Block Analytics and Third-Party Requests
Stop trackers, chat widgets and ad scripts from loading during tests to speed up pages and remove external flakiness.
Medium Verified against Selenium 4.48.0
Problem
Every page load waits for Google Tag Manager, a chat widget and two ad networks. They add seconds, occasionally hang, and pollute analytics with test traffic.
Solution
Intercept requests to those hosts with BiDi and fail them. Put the block list in the driver factory so every test benefits.
Fail requests to a host block list
Selenium 4 Medium
import org.openqa.selenium.bidi.module.Network;import org.openqa.selenium.bidi.network.*;
static final List<String> BLOCKED = List.of( "*.googletagmanager.com", "*.google-analytics.com", "*.doubleclick.net", "*.hotjar.com", "*.intercom.io", "widget.intercom.io");
public static void blockThirdParties(WebDriver driver) { Network network = new Network(driver); List<UrlPattern> patterns = BLOCKED.stream().map(h -> new UrlPattern().hostname(h)).toList(); network.addIntercept(new AddInterceptParameters(InterceptPhase.BEFORE_REQUEST_SENT).urlPatterns(patterns)); network.onBeforeRequestSent(e -> { if (e.isBlocked()) network.failRequest(e.getRequest().getRequestId()); });}BLOCKED = ["**googletagmanager.com/**", "**google-analytics.com/**", "**doubleclick.net/**", "**hotjar.com/**", "**intercom.io/**"]
def block_third_parties(driver): driver.network.add_request_handler(BLOCKED, lambda request: request.fail())const { Network } = require('selenium-webdriver/bidi/network');const { AddInterceptParameters } = require('selenium-webdriver/bidi/addInterceptParameters');const { InterceptPhase } = require('selenium-webdriver/bidi/interceptPhase');
const BLOCKED = ['googletagmanager.com', 'google-analytics.com', 'doubleclick.net', 'hotjar.com', 'intercom.io'];
async function blockThirdParties(driver) {const network = await Network(driver);await network.addIntercept(new AddInterceptParameters(InterceptPhase.BEFORE_REQUEST_SENT));await network.beforeRequestSent(async (e) => { if (!e.isBlocked) return; const host = new URL(e.request.url).hostname; if (BLOCKED.some((b) => host.endsWith(b))) await network.failRequest(e.request.request); else await network.continueRequest(new ContinueRequestParameters(e.request.request));});}static readonly string[] Blocked = { "googletagmanager.com", "google-analytics.com", "doubleclick.net", "hotjar.com", "intercom.io" };
public static async Task BlockThirdPartiesAsync(IWebDriver driver){ var bidi = await driver.AsBiDiAsync(); await bidi.Network.InterceptRequestAsync(async e => { var host = new Uri(e.Request.Url).Host; if (Blocked.Any(b => host.EndsWith(b))) await e.Request.FailAsync(); else await e.Request.ContinueAsync(); });}Why It Works
Failing the request at beforeRequestSent means the browser never opens a connection; the page sees a network error for that resource and continues. Well-built apps tolerate a missing analytics script; if yours does not, that is a finding.
Gotchas
- When intercepting all requests (JavaScript and C# examples), you must continue the ones you do not block, or the page hangs. The Java and Python examples only intercept matching hosts, so no continuation is needed.
- Some consent-management scripts block the page until they load; add them to the list and dismiss the banner via cookie instead.
- Without BiDi, Chrome’s
--host-resolver-rules="MAP *.doubleclick.net 127.0.0.1"argument achieves a cruder block. - Keep one test unblocked to catch integration breakage with the real third parties.
Learn the theory
- Network Interception with BiDi Observe, block, modify and mock HTTP traffic across browsers: capture requests and responses, fail third-party calls, inject headers, stub API responses, and build a network-idle wait.
- Speeding Up Test Suites Where Selenium suites lose time and how to get it back: measure first, then cut command count, skip UI you are not testing, fix waits, parallelise, block third-party traffic, and shrink the suite itself.