Request Resource Types
The resource type is the kind of thing a request fetches: a script, image, stylesheet, font, sub-frame and so on. Chrome tags every request with one. Filter rules use the type to be precise, such as blocking a tracker script but allowing images.
Why it matters
A network request isn't just a request. It's a request for something specific. When your browser fetches a stylesheet, it's different from when it fetches a script or an image. An ad blocker can use this difference.
A rule that says "block everything from ads.example.com" is broad. It blocks images, scripts, stylesheets, everything. A rule that says "block scripts from ads.example.com" is narrow. It blocks only the scripts. This precision matters. If a site has an image from an ad network but the image isn't an advert (maybe it's a logo or a sensor pixel), a broad block might be too aggressive. A targeted block is smarter.
Chrome tags every request with its resource type. Ad blockers use these tags to write smarter rules.
How it works
When the browser makes a request, it knows what it's asking for. It's asking for a stylesheet, or a script, or an image, or an iframe, or a font. Chrome tracks this information internally and exposes it to extensions via the ResourceType field in the declarativeNetRequest API.
The available types are:
main_frame: the page itselfsub_frame: an iframe within the pagestylesheet: a CSS filescript: a JavaScript fileimage: an image (PNG, JPG, GIF, SVG, etc.)font: a web fontconnect: a WebSocket or similar connectionmedia: video or audioobject: an embedded object or pluginping: a beacon or tracker pingxmlhttprequest(XHR): an AJAX requestfetch: a Fetch API callwebbundle: a Web Bundle resource
When writing a filter rule, you can specify one or more resource types. The rule applies only to requests of those types.
For example, EasyList might have a rule that says: "Block all requests to ads.example.com, but only if they're images or scripts." In the original filter syntax:
||ads.example.com^$image,script
When Scalpel converts this to Chrome's format, it becomes:
{
"id": 1001,
"priority": 1,
"action": {
"type": "block"
},
"condition": {
"urlFilter": "||ads.example.com^",
"resourceTypes": ["image", "script"]
}
}
This rule blocks only image and script requests from that domain. If the same domain hosts a stylesheet or font, it would go through.
Two resource types are special: main_frame and sub_frame. These are used in allow rules (rules that explicitly permit requests). An allow rule might say: "Allow all requests where the main frame is google.com." This rule would let a site allowlist itself.
What does not matter
You don't need to memorise the resource types. Scalpel handles the conversion from EasyList's filter syntax to Chrome's rules. EasyList volunteers write rules like $image,script. Scalpel's build process converts them to the correct declarativeNetRequest format.
You also don't need to specify a resource type for most blocking rules. If a rule doesn't mention a type, it applies to all types. EasyList's most common rules are broad: "Block this ad network domain, period." They don't scope to specific types because ad networks serve multiple types of content, and blocking all of it is the safest approach.
Code example
Here's how resource-type filtering works in practice. Suppose a site has:
<img src="https://tracker.example.com/pixel.gif" />
<script src="https://tracker.example.com/analytics.js"></script>
<link rel="stylesheet" href="https://tracker.example.com/styles.css" />
Three requests to the same domain, different types.
A broad rule blocks all three:
{
"id": 2000,
"priority": 1,
"action": {
"type": "block"
},
"condition": {
"urlFilter": "||tracker.example.com^"
}
}
A targeted rule blocks only scripts:
{
"id": 2001,
"priority": 1,
"action": {
"type": "block"
},
"condition": {
"urlFilter": "||tracker.example.com^",
"resourceTypes": ["script"]
}
}
With this targeted rule, the image and stylesheet would load. Only the analytics script would be blocked.
An allow rule for a specific site might look like:
{
"id": 5000,
"priority": 100,
"action": {
"type": "allowAllRequests"
},
"condition": {
"urlFilter": "||supportedsite.com^",
"resourceTypes": ["main_frame"]
}
}
This rule allows all requests where the main frame (the page itself) is from supportedsite.com. Requests on that site go through unblocked.
How Scalpel Ads Blocker shows it
Scalpel's bundled rulesets (EasyList and EasyPrivacy) include rules with resource-type filters. When Scalpel's build converts filter lists to declarativeNetRequest rules, it preserves these resource-type constraints.
Most users don't see resource types explicitly. They're under the hood. What you do see is the result: Scalpel blocks trackers and adverts, but rarely breaks a page by blocking something essential like a stylesheet or font.
If you want to audit Scalpel's rules, the compiled rulesets in the extension's rules/ folder show the resource types explicitly. Each rule has a resourceTypes array. You can verify that Scalpel isn't blocking too broadly and that it's using precision where it matters.