Dynamic Rules, Added While You Browse
Dynamic rules are blocking or allow rules an extension adds while it runs, rather than bundling them. They persist across restarts. Scalpel uses one dynamic allowAllRequests rule for each site on your allowlist, which lets that site's requests through.
Why it matters
Static rulesets are bundled inside the extension and can't change. They're fast and private, but they're also rigid. If you want to add or remove a rule while using the blocker (say, to allowlist a site), you need dynamic rules.
Dynamic rules persist in Chrome's local storage and survive a browser restart. When you allowlist a site in Scalpel, the extension creates a new dynamic rule for that domain. When you remove the site from your allowlist, the rule gets deleted. This is how Scalpel turns your allowlist into actual blocking behaviour without re-bundling the extension.
How it works
When you allowlist a site in Scalpel (say, news-site.com), the extension calls Chrome's updateDynamicRules method to add a new rule. That rule looks like this:
{
"id": 101,
"action": {
"type": "allowAllRequests"
},
"condition": {
"urlFilter": "||news-site.com^",
"resourceTypes": ["main_frame"]
}
}
The allowAllRequests action tells Chrome to stop checking this site against any other rules. All its requests are allowed. The condition matches only the site's main frame (the page itself, not subframes or other resources). This keeps the rule specific.
Chrome stores this rule persistently. If you restart the browser, the rule is still there. Every time you visit news-site.com, Chrome sees the rule and skips blocking. No need for the extension to do any work.
When you remove news-site.com from your allowlist, Scalpel deletes the rule. Blocking resumes on your next visit.
What does not matter
Dynamic rules are not faster than static rules. Chrome stores them in local storage and checks them at the same speed it checks static rules. The "dynamic" just means they change at runtime. If you have a thousand sites on your allowlist, you'll have a thousand dynamic rules, and Chrome handles them fine.
There is a limit to dynamic rules (listed in the declarativeNetRequest API docs), but Scalpel's approach (one rule per site) is nowhere near it. For personal use, this is not a constraint.
Code example
Here's how Scalpel creates dynamic rules when you interact with the settings:
{
"id": 101,
"priority": 1000,
"action": {
"type": "allowAllRequests"
},
"condition": {
"urlFilter": "|https://trusted-partner.org^",
"resourceTypes": ["main_frame"]
}
}
This rule gives special treatment to only trusted-partner.org. Its priority is high (1000) so it overrides any lower-priority block rules. The resource type main_frame means it applies only to the top-level page, not to ads loaded in iframes.
If you wanted to block a single URL (not the whole domain), you'd use a dynamic rule like:
{
"id": 102,
"action": {
"type": "block"
},
"condition": {
"urlFilter": "||very-specific-tracker.com/analytics"
}
}
But Scalpel uses them only for allowlisting, not for custom blocking lists.
How Scalpel Ads Blocker shows it
When you open the Scalpel popup and click "Allow on this site," the extension creates a dynamic rule for that domain. The popup label changes to "Block this site" to reflect the new state.
Your allowlist lives in the browser's local storage and is stored as a set of domain names. Scalpel converts that list into dynamic rules and keeps them in sync. If you use Scalpel on multiple browsers, each one has its own allowlist and its own dynamic rules. They don't sync across devices because the rules are local.
Click "Block this site" again and the rule gets deleted. Blocking goes back to normal on your next visit.