Palancar
Browser Extensions, Privacy Tools, and Open Web Resources
Browser Extensions

declarativeNetRequest vs webRequest: Why the Same Ad Blocker Behaves Differently in Chrome and Firefox

uBlock Origin and uBlock Origin Lite differ because of one API choice. Here is how declarativeNetRequest and blocking webRequest work and where the limits bite.

By Palancar · 5 min · 3 November 2026

Photorealistic highway toll gantry with lanes of traffic, one lane inspected by a checkpoint, suggesting request filtering

declarativeNetRequest vs webRequest: Why the Same Ad Blocker Behaves Differently in Chrome and Firefox

Install uBlock Origin in Firefox and you get one product. Install uBlock Origin Lite in Chrome and you get a visibly different one: fewer controls, a rules-based model, occasional misses on sites that fight ad blockers. The gap is not about developer effort or taste. It follows from which network API the browser lets an extension use to block requests, and the difference is precise enough to be worth stating carefully.

Two Models of Blocking

Blocking webRequest is imperative. An extension registers a listener, the browser pauses each matching request, and the extension’s own code decides what to do: cancel it, redirect it, or modify headers. The extension sees the request and runs arbitrary logic on it.

declarativeNetRequest (DNR) is declarative. The extension hands the browser a set of rules, each describing conditions and an action, and the browser evaluates them itself. Chrome’s migration guide describes it as specifying actions to perform when conditions are met instead of intercepting requests at runtime. The extension’s code never sits on the request path and never reads request contents to block them.

Chrome’s documentation states the reason directly: blocking listeners in Manifest V2 could degrade extension and page performance, and the permissions they needed were invasive. Critics counter that the declarative model caps what a filter engine can express. Both statements can be true, and they explain the two camps in the debate.

What Chrome’s Manifest V3 Changed

In Chrome’s Manifest V3, blocking webRequest listeners are replaced by declarative rules. The Chrome guide says the two APIs are significantly different, so migration means rewriting around use cases, not swapping function calls. One exception remains: extensions installed by enterprise policy can still use webRequestBlocking.

DNR also carries quantitative limits. From Chrome’s API reference:

  • Static rules guaranteed per extension: at least 30,000, with more available from a shared global pool depending on what other installed extensions enable.
  • Static rulesets: up to 100 specified, with 50 enabled at a time.
  • Dynamic rules: 30,000 “safe” rules, but only 5,000 “unsafe” ones.
  • Regular-expression rules: capped at 1,000, evaluated separately for static and dynamic rules.
  • Session rules: up to 5,000.

Those numbers shape ad blocking directly. Large community filter lists run to tens of thousands of entries, and any filter that depends on logic rather than a pattern has to be expressed as one of a limited set of rule types.

What Firefox Does Differently

Mozilla took a different position. In a February 2025 post, Mozilla said Firefox continues to support both blocking webRequest and declarativeNetRequest in Manifest V3, and kept Manifest V2 alongside it. The practical result is that a Firefox extension can use the imperative model for logic that DNR cannot express, and use DNR where declarative rules are enough.

Firefox’s DNR implementation also has its own quotas, which MDN documents per ruleset. We would not carry Chrome’s figures over to Firefox. Check the current MDN compatibility tables before sizing a ruleset for it, because limits have changed between Firefox versions.

Why the Two uBlock Products Differ

This is where the abstract difference becomes visible. The uBlock Origin project describes full uBlock Origin as working best in Firefox, with Chromium browsers needing Manifest V2, which current Chrome cannot run. uBlock Origin Lite is the Manifest V3 build and runs on Chrome, Edge, Firefox, and Safari.

The project’s own comparison is candid about the tradeoffs. Lite offers filtering modes (No filtering, Basic, Optimal, Complete) and “does not include full uBO’s dynamic filtering controls.” On custom filters, it notes that browser API limits apply and not every uBO filter can be used. Some filters cannot be translated into Manifest V3 rules at all, which the project says can make Lite less effective on sites that use anti-ad-blocking techniques. Lite’s Basic mode can work without reading or modifying page content, while Optimal and Complete modes require that permission.

That permission point is the privacy counterweight. Declarative blocking requires less trust in extension code, since the code is not inspecting every request. Procedural blocking can do more but sees more. Neither is free.

Where Developers Feel the Difference

For an extension author, the split shows up in three places. First, anything that needs to inspect a request body or make a per-request decision from runtime state has no declarative equivalent, so it must be redesigned or dropped on Chrome. Second, rule updates are heavier: static rulesets ship with the extension, while dynamic rules are the part an extension can change at runtime, and both are bounded by the quotas above. Third, testing changes shape. Debugging a listener means stepping through code; debugging DNR means asking which rule matched and why, using the browser’s rule-match tooling and a small set of test URLs.

How to Choose and What to Test

  • Chrome user wanting less breakage: a DNR-based blocker is what the platform supports. Expect to adjust the filtering mode on sites that break or fight back.
  • Firefox user wanting maximum control: the full-capability blocker is available because the imperative API remains. See our Firefox privacy comparison for how that fits the wider browser picture.
  • Extension developer: do not assume one API choice ports cleanly. Our Manifest V3 migration guide covers the structural changes, and the service worker migration article covers the lifecycle side.

The Takeaway

The difference between the two blockers is a difference in what the browser permits an extension to do on the request path. When a filter works in one browser and not the other, check whether it needs procedural logic. If it does, the cause is the API, not a bug.