declarativeNetRequest, the Manifest V3 Blocking API
declarativeNetRequest is the Chrome API that Manifest V3 blockers use. The extension hands Chrome a set of rules once. Chrome then matches every request against them itself. The extension never sees your traffic, which is why it needs no access to your browsing.
Why it matters
For twenty years, ad blockers worked the same way. The extension watched every network request your browser made, checked it against its rules, and either let it through or stopped it. That meant the blocker had to see all your traffic. Manifest V3, Chrome's new extension platform, changed this.
The old approach needed broad host permissions. The extension read your entire browsing history. But with declarativeNetRequest, you give the extension a list of rules once, and Chrome does the checking itself. The extension never sees your traffic. That's why a declarativeNetRequest blocker can work without asking for access to your browsing.
This is a real privacy win. Your blocker doesn't collect data about what you visit. But it also changes what the blocker can do in real time.
How it works
You supply the blocking rules to Chrome, usually as a static JSON file bundled inside the extension. Each rule has a condition (a URL pattern) and an action (block, allow, or redirect). When your browser makes a request, Chrome checks it against the rules before the request goes out.
If a rule matches, Chrome applies the action. If the action is "block," the request never leaves your computer. Scalpel never sees it. The page never fetches the advert.
Rules are checked in priority order, so allow rules can override block rules. For example, Scalpel could block all requests to adserver.com, then use allow rules to let them through on your allowlisted sites.
Static rulesets are bundled at build time and activated when you install the extension. Chrome loads them into memory and starts matching immediately. Dynamic rules are added while the extension runs. Scalpel uses these for your allowlist.
What does not matter
The extension doesn't run code for each request. It can't inspect the advert's content or preview the advert before deciding. It can't log every blocked request in real time the way Manifest V2 blockers could. This is the privacy cost. But for blocking by URL pattern alone (which covers most adverts), it's not a limitation.
Declarative Net Request also cannot read request bodies or modify responses. It works at the network layer only. It can't change the advert's HTML once it's loaded. That's where cosmetic filtering comes in; that's a different job.
Code example
A simple declarativeNetRequest rule looks like this:
[
{
"id": 1,
"priority": 1,
"action": {
"type": "block"
},
"condition": {
"urlFilter": "||ads.example.com^",
"resourceTypes": ["script", "image"]
}
},
{
"id": 2,
"priority": 10,
"action": {
"type": "allow"
},
"condition": {
"urlFilter": "||ads.example.com^",
"initiatorDomains": ["trusted-site.com"]
}
}
]
Rule 1 blocks all requests to ads.example.com for scripts and images. Rule 2, with higher priority, allows them if they come from trusted-site.com. Chrome applies the highest-priority matching rule. This is how allowlisting works: a high-priority allow rule overrides the general block rule.
How Scalpel Ads Blocker shows it
Scalpel uses two types of declarativeNetRequest rules. Static rulesets contain the main blocking lists (EasyList, EasyPrivacy, and others). These are bundled inside the extension and never change until you update Scalpel.
Dynamic rules are built from your allowlist. Each site you allowlist gets one allowAllRequests rule with high priority. That rule exempts the entire site from blocking. When you remove a site from your allowlist, Scalpel deletes its rule, and blocking resumes.
The advantage is speed and privacy. Scalpel doesn't see your traffic. Chrome does the work. And because the rules are deterministic (the same URL always matches the same rule), blocking is predictable and auditable.