chrome.declarativeNetRequest
Description: |
The chrome.declarativeNetRequest API is used to block or modify
network requests by specifying declarative rules. This lets extensions
modify network requests without intercepting them and viewing their content,
thus providing more privacy.
|
Availability: |
Since Chrome 84.
|
Permissions: |
host permissions Note that declarativeNetRequestFeedback and host permissions should only be specified when necessary.
|
Manifest
Extensions must declare the "declarativeNetRequest"
permission in
the extension manifest to use this API. The
"declarativeNetRequestFeedback"
permission is required to access
functions and events which return information on declarative rules matched.
Host permissions are required if the extension
wants to redirect requests or modify headers. To specify static
Rulesets, extensions must also declare the
"declarative_net_request"
manifest key, which should be a
dictionary with a single key called "rule_resources"
. It should be
a list containing dictionaries of type Ruleset, as shown below.
{ "name": "My extension", ... "declarative_net_request" : { "rule_resources" : [{ "id": "ruleset_1", "enabled": true, "path": "rules_1.json" }, { "id": "ruleset_2", "enabled": false, "path": "rules_2.json" }] }, "permissions": [ "declarativeNetRequest", "declarativeNetRequestFeedback", "*://example.com/*" ], ... }
Rule Resources
An extension can specify up to MAX_NUMBER_OF_STATIC_RULESETS
rulesets as part of the
"rule_resources"
manifest key. The number of rules
across enabled static rulesets must be less than the
MAX_NUMBER_OF_RULES constant.
Rules
A single declarative Rule consists of four fields: id
,
priority
, condition
and action
.
There are the following kinds of rules:
- Rules that block a network request.
- Rules that prevent a request from getting blocked by negating any matching blocked rules.
- Rules that redirect a network request.
- Rules that modify headers from a network request.
An example rule:
{ "id" : 1, "priority": 1, "action" : { "type" : "block" }, "condition" : { "urlFilter" : "abc", "domains" : ["foo.com"], "resourceTypes" : ["script"] } }
The above rule will block all script requests originating from
"foo.com"
to any URL with "abc"
as a substring.
The urlFilter
field of a rule condition is used to specify the
pattern which is matched against the request URL. Some examples of URL filters:
urlFilter |
Matches | Does not match |
---|---|---|
"abc" |
https://abcd.com https://example.com/abcd |
http://ab.com |
"abc*d" |
https://abcd.com https://example.com/abcxyzd |
http://abc.com |
"||a.example.com" |
https://a.example.com/ https://b.a.example.com/xyz |
http://example.com/ |
"|https*" |
https://example.com |
http://example.com/ http://https.com |
"example*^123|" |
https://example.com/123 http://abc.com/example?123 |
https://example.com/1234 https://abc.com/example0123 |
Dynamic rules
To add or remove rules dynamically, extensions can use the updateDynamicRules API method.
- The number of dynamic rules that an an extension can add is bounded by the MAX_NUMBER_OF_DYNAMIC_RULES constant.
- The dynamic rules for an extension are persisted across both sessions and extension updates.
Updating enabled rulesets
An extension can update the set of enabled static rulesets using the updateEnabledRulesets API method.
- The number of rules across enabled static rulesets must be less than the MAX_NUMBER_OF_RULES constant.
-
The set of enabled static rulesets is persisted across sessions but not
across extension updates. The
rule_resources
manifest key will determine the set of enabled static rulesets on initial extension install and on each subsequent extension update.
Implementation details
Matching algorithm
Before the request is sent, each extension is queried for an action to take. The following actions are considered at this stage:
- Actions which block requests of type
block
- Actions which redirect requests of type
redirect
orupgradeScheme
- Actions which allow requests of type
allow
orallowAllRequests
If more than one extension returns an action, the extension whose action type comes first in the list above gets priority. If more than one extension returns an action with the same priority (position in the list), the most recently installed extension gets priority.
When an extension is queried for how to handle a request, the highest priority matching static or dynamic rule is returned. If more than one matching rule has the highest priority, the tie is broken based on the action type, in the following order of decreasing precedence:
allow
allowAllRequests
block
upgradeScheme
redirect
If the request was not blocked or redirected, the matching
modifyHeaders
rules are evaluated with the most recently installed
extensions getting priority. Within each extension, all
modifyHeaders
rules with a priority lower than matching
allow
or allowAllRequests
rules are ignored.
If multiple modifyHeaders
rules specify the same header, the
resulting modification for the header is determined based on the priority of
each rule and the operations specified.
- If a rule has appended to a header, then lower priority rules can only
append to that header.
set
andremove
operations are not permitted. - If a rule has set a header, then lower priority rules cannot further
modify the header, except for
append
rules from the same extension. - If a rule has removed a header, then lower priority rules cannot further modify the header.
Comparison with the webRequest API
- The declarativeNetRequest API allows for evaluating network requests in the browser itself. This makes it more performant than the webRequest API, where each network request is evaluated in JavaScript in the extension process.
- Because the requests are not intercepted by the extension process, declarativeNetRequest removes the need for extensions to have a background page; resulting in less memory consumption.
- Unlike the webRequest API, blocking requests using the declarativeNetRequest API requires no host permissions.
- The declarativeNetRequest API provides better privacy to users because extensions can't actually read the network requests made on the user's behalf.
- Unlike the webRequest API, any images or iframes blocked using the declarativeNetRequest API are automatically collapsed in the DOM.
- While deciding whether a request is to be blocked or redirected, the declarativeNetRequest API is given priority over the webRequest API because it allows for synchronous interception. Similarly, any headers removed through declarativeNetRequest API are not made visible to web request extensions.
- The webRequest API is more flexible as compared to the declarativeNetRequest API because it allows extensions to evaluate a request programmatically.
Example
manifest.json
{ "name": "declarativeNetRequest extension", "version": "1", "declarative_net_request": { "rule_resources": [{ "id": "ruleset_1", "enabled": true, "path": "rules.json" }] }, "permissions": [ "*://*.google.com/*", "*://*.abcd.com/*", "*://*.example.com/*", "http://*.xyz.com/*", "*://*.headers.com/*", "declarativeNetRequest" ], "manifest_version": 2 }
rules.json
[ { "id": 1, "priority": 1, "action": { "type": "block" }, "condition": {"urlFilter": "google.com", "resourceTypes": ["main_frame"] } }, { "id": 2, "priority": 1, "action": { "type": "allow" }, "condition": { "urlFilter": "google.com/123", "resourceTypes": ["main_frame"] } }, { "id": 3, "priority": 2, "action": { "type": "block" }, "condition": { "urlFilter": "google.com/12345", "resourceTypes": ["main_frame"] } }, { "id": 4, "priority": 1, "action": { "type": "redirect", "redirect": { "url": "https://example.com" } }, "condition": { "urlFilter": "google.com", "resourceTypes": ["main_frame"] } }, { "id": 5, "priority": 1, "action": { "type": "redirect", "redirect": { "extensionPath": "/a.jpg" } }, "condition": { "urlFilter": "abcd.com", "resourceTypes": ["main_frame"] } }, { "id": 6, "priority": 1, "action": { "type": "redirect", "redirect": { "transform": { "scheme": "https", "host": "new.example.com" } } }, "condition": { "urlFilter": "||example.com", "resourceTypes": ["main_frame"] } }, { "id": 7, "priority": 1, "action": { "type": "redirect", "redirect": { "regexSubstitution": "https://\\1.xyz.com/" } }, "condition": { "regexFilter": "^http://www\\.(abc|def)\\.xyz\\.com/", "resourceTypes": [ "main_frame" ] } }, { "id" : 8, "priority": 2, "action" : { "type" : "allowAllRequests" }, "condition" : { "urlFilter" : "||b.com/path", "resourceTypes" : ["sub_frame"] } }, { "id" : 9, "priority": 1, "action" : { "type" : "block" }, "condition" : { "urlFilter" : "script.js", "resourceTypes" : ["script"] } }, { "id": 10, "priority": 2, "action": { "type": "modifyHeaders", "responseHeaders": [ { "header": "h1", "operation": "remove" }, { "header": "h2", "operation": "set", "value": "v2" }, { "header": "h3", "operation": "append", "value": "v3" } ] }, "condition": { "urlFilter": "headers.com/123", "resourceTypes": ["main_frame"] } }, { "id": 11, "priority": 1, "action": { "type": "modifyHeaders", "responseHeaders": [ { "header": "h1", "operation": "set", "value": "v4" }, { "header": "h2", "operation": "append", "value": "v5" }, { "header": "h3", "operation": "append", "value": "v6" } ] }, "condition": { "urlFilter": "headers.com/12345", "resourceTypes": ["main_frame"] } }, ]
-
Consider a navigation to
"http://google.com"
. Rules with id (1) and (4) match. The request will be blocked because blocking rules have higher priority than redirect rules when the"priority"
is the same. -
Consider a navigation to
"http://google.com/1234"
. Rules with id (1), (2), and (4) match. Because the request has a matchingallow
rule and no higher priority rules, the request is not blocked nor redirected and continues to"http://google.com/1234"
. -
Consider a navigation to
"http://google.com/12345"
Rules with id (1), (2), (3), and (4) match. The request will be blocked because rule (3) has the highest priority, overriding all other matching rules. -
Consider a navigation to
"http://abcd.com"
. The rule with id (5) matches. Since rule (5) specifies an extension path, the request is redirected to"chrome-extension://<extension-id>/a.jpg"
. -
Consider a navigation to
"http://example.com/path"
. The rule with id (6) matches. Since rule (6) specifies a url transform, the request is redirected to"https://new.example.com/path"
. -
Consider a navigation to
"http://www.abc.xyz.com/path"
. The rule with id (7) matches. The request will be redirected to"https://abc.xyz.com/path"
. -
Consider the following request hierarchy:
- https://a.com/path (main-frame request)
- https://b.com/path (sub-frame request, matches rule with id (8))
- https://c.com/path (sub-frame request, matches rule with id (8))
- https://c.com/script.js (script request, matches rules with ids (8, 9) but (8) has higher priority)
- https://b.com/script.js (script request, matches rules with ids (8, 9) but (8) has higher priority)
- https://c.com/path (sub-frame request, matches rule with id (8))
- https://d.com/path (sub-frame request)
- https://d.com/script.js (script request, matches rule with ids (9))
- https://b.com/path (sub-frame request, matches rule with id (8))
- https://a.com/path (main-frame request)
-
Consider a navigation to
"http://headers.com/12345"
with response headers{ "h1": "initial_1", "h2": "initial_2" }
. Rules with id (10) and (11) match. The request will have its response headers modified to{ "h2": "v2", "h2": "v5", "h3": "v3", "h3": "v6" }
. Headerh1
was removed by (10),h2
was set by (10) then appended by (11), andh3
was appended by (10) and (11).
Summary
Types | |
---|---|
ResourceType | |
Ruleset | |
URLTransform | |
RuleCondition | |
ModifyHeaderInfo | |
RuleAction | |
Rule | |
MatchedRule | |
MatchedRuleInfo | |
RequestDetails | |
Properties | |
MAX_NUMBER_OF_RULES | |
MAX_NUMBER_OF_DYNAMIC_RULES | |
GETMATCHEDRULES_QUOTA_INTERVAL | |
MAX_GETMATCHEDRULES_CALLS_PER_INTERVAL | |
MAX_NUMBER_OF_REGEX_RULES | |
MAX_NUMBER_OF_STATIC_RULESETS | |
DYNAMIC_RULESET_ID | |
Methods | |
updateDynamicRules −
chrome.declarativeNetRequest.updateDynamicRules(array of integer ruleIdsToRemove, array of Rule rulesToAdd, function callback)
| |
getDynamicRules −
chrome.declarativeNetRequest.getDynamicRules(function callback)
| |
updateEnabledRulesets −
chrome.declarativeNetRequest.updateEnabledRulesets(array of string rulesetIdsToDisable, array of string rulesetIdsToEnable, function callback)
| |
getEnabledRulesets −
chrome.declarativeNetRequest.getEnabledRulesets(function callback)
| |
getMatchedRules −
chrome.declarativeNetRequest.getMatchedRules(object filter, function callback)
| |
setActionCountAsBadgeText −
chrome.declarativeNetRequest.setActionCountAsBadgeText(boolean enable)
| |
Events | |
onRuleMatchedDebug |
Types
ResourceType
Enum |
---|
"main_frame" ,
"sub_frame" ,
"stylesheet" ,
"script" ,
"image" ,
"font" ,
"object" ,
"xmlhttprequest" ,
"ping" ,
"csp_report" ,
"media" ,
"websocket" ,
or "other"
|
Ruleset
properties | ||
---|---|---|
string | id |
A non-empty string uniquely identifying the ruleset. IDs beginning with '_' are reserved for internal use. |
string | path |
The path of the JSON ruleset relative to the extension directory. |
boolean | enabled |
Whether the ruleset is enabled by default. |
URLTransform
properties | ||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
string | (optional) scheme |
The new scheme for the request. Allowed values are "http", "https", "ftp" and "chrome-extension". |
||||||||||||
string | (optional) host |
The new host for the request. |
||||||||||||
string | (optional) port |
The new port for the request. If empty, the existing port is cleared. |
||||||||||||
string | (optional) path |
The new path for the request. If empty, the existing path is cleared. |
||||||||||||
string | (optional) query |
The new query for the request. Should be either empty, in which case the existing query is cleared; or should begin with '?'. |
||||||||||||
object | (optional) queryTransform |
Add, remove or replace query key-value pairs.
|
||||||||||||
string | (optional) fragment |
The new fragment for the request. Should be either empty, in which case the existing fragment is cleared; or should begin with '#'. |
||||||||||||
string | (optional) username |
The new username for the request. |
||||||||||||
string | (optional) password |
The new password for the request. |
RuleCondition
properties | ||
---|---|---|
string | (optional) urlFilter |
The pattern which is matched against the network request url. Supported constructs: '*' : Wildcard: Matches any number of characters. '|' : Left/right anchor: If used at either end of the pattern, specifies the beginning/end of the url respectively. '||' : Domain name anchor: If used at the beginning of the pattern, specifies the start of a (sub-)domain of the URL. '^' : Separator character: This matches anything except a letter, a digit or one of the following: _ - . %. This can also match the end of the URL. Therefore If omitted, all urls are matched. An empty string is not allowed. A pattern beginning with Note: Only one of Note: The |
string | (optional) regexFilter |
Regular expression to match against the network request url. This follows the RE2 syntax. Note: Only one of Note: The |
boolean | (optional) isUrlFilterCaseSensitive |
Whether the |
array of string | (optional) domains |
The rule will only match network requests originating from the list of Note: sub-domains like "a.example.com" are also allowed. The entries must consist of only ascii characters. Use punycode encoding for internationalized domains. |
array of string | (optional) excludedDomains |
The rule will not match network requests originating from the list of Note: sub-domains like "a.example.com" are also allowed. The entries must consist of only ascii characters. Use punycode encoding for internationalized domains. |
array of ResourceType | (optional) resourceTypes |
List of resource types which the rule can match. An empty list is not allowed. Note: this must be specified for |
array of ResourceType | (optional) excludedResourceTypes |
List of resource types which the rule won't match. Only one of |
enum of "firstParty" , or "thirdParty" |
(optional) domainType |
Specifies whether the network request is first-party or third-party to the domain from which it originated. If omitted, all requests are accepted.
|
ModifyHeaderInfo
Not fully implemented. You must build Chromium from source to try this API. Learn more.
properties | ||
---|---|---|
string | header |
The name of the header to be modified. |
enum of "append" , "set" , or "remove" |
operation |
The operation to be performed on a header.
|
string | (optional) value |
The new value for the header. Must be specified for |
RuleAction
properties | ||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
enum of "block" , "redirect" , "allow" , "upgradeScheme" , "modifyHeaders" , or "allowAllRequests" |
type |
The type of action to perform.
|
||||||||||||
object | (optional) redirect |
Describes how the redirect should be performed. Only valid for redirect rules.
|
||||||||||||
array of ModifyHeaderInfo | (optional) requestHeaders |
Not fully implemented. You must build Chromium from source to try this API. Learn more. The request headers to modify for the request. Only valid if RuleActionType is "modifyHeaders". |
||||||||||||
array of ModifyHeaderInfo | (optional) responseHeaders |
Not fully implemented. You must build Chromium from source to try this API. Learn more. The response headers to modify for the request. Only valid if RuleActionType is "modifyHeaders". |
Rule
properties | ||
---|---|---|
integer | id |
An id which uniquely identifies a rule. Mandatory and should be >= 1. |
integer | (optional) priority |
Rule priority. Mandatory and should be >= 1. This is used to break ties between multiple matching rules. |
RuleCondition | condition |
The condition under which this rule is triggered. |
RuleAction | action |
The action to take if this rule is matched. |
MatchedRule
properties | ||
---|---|---|
integer | ruleId |
A matching rule's ID. |
string | rulesetId |
ID of the Ruleset this rule belongs to. For a rule originating from the set of dynamic rules, this will be equal to DYNAMIC_RULESET_ID. |
MatchedRuleInfo
properties | ||
---|---|---|
MatchedRule | rule | |
double | timeStamp |
The time the rule was matched. Timestamps will correspond to the Javascript convention for times, i.e. number of milliseconds since the epoch. |
integer | tabId |
The tabId of the tab from which the request originated if the tab is still active. Else -1. |
RequestDetails
properties | ||
---|---|---|
string | requestId |
The ID of the request. Request IDs are unique within a browser session. |
string | url |
The URL of the request. |
string | (optional) initiator |
The origin where the request was initiated. This does not change through redirects. If this is an opaque origin, the string 'null' will be used. |
string | method |
Standard HTTP method. |
integer | frameId |
The value 0 indicates that the request happens in the main frame; a positive value indicates the ID of a subframe in which the request happens. If the document of a (sub-)frame is loaded ( |
integer | parentFrameId |
ID of frame that wraps the frame which sent the request. Set to -1 if no parent frame exists. |
integer | tabId |
The ID of the tab in which the request takes place. Set to -1 if the request isn't related to a tab. |
ResourceType | type |
The resource type of the request. |
Properties
30,000 |
chrome.declarativeNetRequest.MAX_NUMBER_OF_RULES |
The maximum number of rules that an extension can specify across its enabled static rulesets. Any excess rules will be ignored and an install warning will be raised. |
5,000 |
chrome.declarativeNetRequest.MAX_NUMBER_OF_DYNAMIC_RULES |
The maximum number of dynamic rules that an extension can add. |
10 |
chrome.declarativeNetRequest.GETMATCHEDRULES_QUOTA_INTERVAL |
Time interval within which MAX_GETMATCHEDRULES_CALLS_PER_INTERVAL getMatchedRules calls can be made, specified in minutes. Additional calls will fail immediately and set runtime.lastError. Note: getMatchedRules calls associated with a user gesture are exempt from the quota.
|
20 |
chrome.declarativeNetRequest.MAX_GETMATCHEDRULES_CALLS_PER_INTERVAL |
The number of times getMatchedRules can be called within a period of GETMATCHEDRULES_QUOTA_INTERVAL .
|
1,000 |
chrome.declarativeNetRequest.MAX_NUMBER_OF_REGEX_RULES |
The maximum number of regular expression rules that an extension can add. This limit is evaluated separately for the set of dynamic rules and those specified in the rule resources file. |
10 |
chrome.declarativeNetRequest.MAX_NUMBER_OF_STATIC_RULESETS |
The maximum number of static Rulesets an extension can specify as part of the "rule_resources" manifest key.
|
_dynamic |
chrome.declarativeNetRequest.DYNAMIC_RULESET_ID |
Ruleset ID for the dynamic rules added by the extension. |
Methods
updateDynamicRules
chrome.declarativeNetRequest.updateDynamicRules(array of integer ruleIdsToRemove, array of Rule rulesToAdd, function callback)
Modify the current set of dynamic rules for the extension. The rules with IDs listed in ruleIdsToRemove
are first removed, and then the rules given in rulesToAdd
are added. This update happens as a single atomic operation: either all specified rules are added and removed, or an error is returned. These rules are persisted across browser sessions and across extension updates. Any ids in ruleIdsToRemove
that are not present will be ignored. Note that static rules specified as part of the extension package can not be removed using this function. Note: MAX_NUMBER_OF_DYNAMIC_RULES is the maximum number of dynamic rules an extension can add.
Parameters | ||
---|---|---|
array of integer | ruleIdsToRemove |
The IDs of rules to remove. |
array of Rule | rulesToAdd |
The rules to add. |
function | (optional) callback |
Called once the update is complete or has failed. In case of an error, runtime.lastError will be set and no change will be made to the rule set. This can happen for multiple reasons, such as invalid rule format, duplicate rule ID, rule count limit exceeded, internal errors, and others. If you specify the callback parameter, it should be a function that looks like this: function() {...};
|
getDynamicRules
chrome.declarativeNetRequest.getDynamicRules(function callback)
Returns the current set of dynamic rules for the extension.
Parameters | |||||
---|---|---|---|---|---|
function | callback |
Called with the set of dynamic rules. An error might be raised in case of transient internal errors. The callback parameter should be a function that looks like this: function(array of Rule rules) {...};
|
updateEnabledRulesets
chrome.declarativeNetRequest.updateEnabledRulesets(array of string rulesetIdsToDisable, array of string rulesetIdsToEnable, function callback)
Updates the set of enabled static rulesets for the extension. The rulesets with IDs listed in rulesetIDsToDisable
are first removed, and then the rulesets listed in rulesetIDsToEnable
are added. Note that the set of enabled static rulesets is persisted across sessions but not across extension updates, i.e. the rule_resources
manifest key will determine the set of enabled static rulesets on each extension update.
Parameters | ||
---|---|---|
array of string | rulesetIdsToDisable |
The set of ids corresponding to a static Ruleset that should be disabled. |
array of string | rulesetIdsToEnable |
The set of ids corresponding to a static Ruleset that should be enabled. |
function | callback |
Called once the update is complete. In case of an error, runtime.lastError will be set and no change will be made to set of enabled rulesets. This can happen for multiple reasons, such as invalid ruleset IDs, rule count limit exceeded, or internal errors. The callback parameter should be a function that looks like this: function() {...};
|
getEnabledRulesets
chrome.declarativeNetRequest.getEnabledRulesets(function callback)
Returns the ids for the current set of enabled static rulesets.
Parameters | |||||
---|---|---|---|---|---|
function | callback |
Called with a list of ids, where each id corresponds to an enabled static Ruleset. The callback parameter should be a function that looks like this: function(array of string rulesetIds) {...};
|
getMatchedRules
chrome.declarativeNetRequest.getMatchedRules(object filter, function callback)
Returns all rules matched for the extension. Callers can optionally filter the list of matched rules by specifying a |filter|. This method is only available to extensions with the declarativeNetRequestFeedback
permission or having the activeTab
permission granted for the tabId
specified in filter
. Note: Rules not associated with an active document that were matched more than five minutes ago will not be returned.
Parameters | ||||||||
---|---|---|---|---|---|---|---|---|
object | (optional) filter |
An object to filter the list of matched rules.
|
||||||
function | callback |
Called once the list of matched rules has been fetched. In case of an error, runtime.lastError will be set and no rules will be returned. This can happen for multiple reasons, such as insufficient permissions, or exceeding the quota. The callback parameter should be a function that looks like this: function(object details) {...};
|
setActionCountAsBadgeText
chrome.declarativeNetRequest.setActionCountAsBadgeText(boolean enable)
Sets whether to automatically badge extension's icon to the matched action count for a tab. This preference is persisted across sessions and is false by default.
Parameters | ||
---|---|---|
boolean | enable |
Events
onRuleMatchedDebug
Fired when a rule is matched with a request. Only available for unpacked extensions with the declarativeNetRequestFeedback
permission as this is intended to be used for debugging purposes only.
addListener
chrome.declarativeNetRequest.onRuleMatchedDebug.addListener(function callback)
Parameters | |||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|
function | callback |
The callback parameter should be a function that looks like this: function(object info) {...};
|