DeclarativeNetRequest and webRequest in Firefox
This article explains how Mozilla Firefox uniquely supports both the
declarativeNetRequest (DNR) API and the dynamic
webRequest blocking API within its Manifest V3 (MV3)
implementation. It covers why Firefox maintains both APIs, how the
browser's network pipeline processes them simultaneously, how conflicts
between competing rules are resolved, and how developers can combine
both APIs to build high-performance extensions.
The Dual-API Strategy in Manifest V3
When Manifest V3 was introduced, Google Chrome deprecated the
blocking capabilities of the webRequest API in favor of the
more restrictive, privacy-focused declarativeNetRequest
API. Mozilla took a different path for Firefox.
To ensure cross-browser compatibility, Firefox implemented the DNR
API so developers could easily port MV3 extensions built for Chrome.
However, Firefox also retained full support for the blocking
webRequest API (via the webRequestBlocking
permission). This decision allows advanced privacy and content-blocking
extensions to maintain full access to dynamic, programmatic request
modification while still offering the performance benefits of DNR.
Architectural Integration and Execution
In Firefox, the declarativeNetRequest API does not
operate as a completely separate network engine. Instead, it is built on
top of the same underlying browser network interception architecture
that powers webRequest.
Despite sharing this foundation, the two APIs execute differently in relation to the extension's lifecycle:
- DeclarativeNetRequest: The extension registers structured JSON rulesets with the browser. The browser engine evaluates and enforces these rules natively. Because the browser handles the logic, the extension’s background script (or event page) remains dormant, saving system memory and CPU cycles.
- webRequest: The extension registers JavaScript
event listeners (such as
onBeforeRequestoronBeforeSendHeaders). When a matching network request occurs, Firefox must wake up the extension's background page, pass the request details to the JavaScript environment, and wait for the extension to return a blocking response before the network request can proceed.
Precedence and Conflict Resolution
Because both APIs can be used simultaneously—either by different extensions installed in the same browser or within a single extension—Firefox follows strict precedence rules to resolve conflicts when both APIs attempt to act on the same network request:
- Blocking Always Wins: A block or cancel action is
the highest-priority outcome. If a DNR rule dictates that a request
should be blocked, and a
webRequestlistener attempts to allow or redirect it, the request is blocked. Conversely, if awebRequestlistener returns{ cancel: true }, the request is terminated regardless of any DNR rules. - Isolation of Allow Rules: In the DNR API,
allowandallowAllRequestsrules are used to bypass other DNR blocking rules. However, these DNR allow rules only apply to the DNR engine. A DNRallowrule cannot override a block issued by awebRequestlistener. - Redirects and Upgrades: If neither API blocks the
request, redirect actions are evaluated next. Scheme upgrades (such as
upgrading HTTP to HTTPS via DNR) and URL redirects from both APIs are
processed at the
onBeforeRequeststage. If a conflict occurs between two different extensions, Firefox resolves it based on the extension installation order (more recently installed extensions generally take precedence). - Header Modifications: Both APIs can modify HTTP
request and response headers. DNR
modifyHeadersactions andwebRequestlisteners (onBeforeSendHeadersandonHeadersReceived) are merged. If both APIs attempt to modify the exact same header in conflicting ways, the browser applies conflict resolution based on rule priority and extension load order.
Combining Both APIs in a Single Extension
Firefox allows a single Manifest V3 extension to declare both
declarativeNetRequest and webRequestBlocking
permissions in its manifest.json file. This hybrid approach
allows developers to optimize their extensions for both performance and
capability:
- Baseline Filtering with DNR: Developers can offload tens of thousands of simple, static URL-blocking rules to the DNR API. The browser handles the bulk of standard ad and tracker blocking natively without waking up the extension's background script.
- Advanced Filtering with webRequest: Developers can
scope their
webRequestlisteners narrowly to specific URLs or resource types that require dynamic programmatic logic. This includes dynamically stripping tracking parameters using complex regular expressions, computing cryptographic tokens on the fly, or using Firefox'swebRequest.filterResponseDataAPI to directly inspect and modify the payload of an incoming HTTP response body—a capability that DNR cannot replicate.