webRequest Permission Reference
4 min readwebRequest Permission Reference
What It Does
- Grants access to
chrome.webRequestAPI - Observe HTTP/HTTPS requests at various lifecycle stages
- MV3: webRequest is READ-ONLY — use
declarativeNetRequestfor blocking/modifying
MV3 Critical Change
| Capability | MV2 | MV3 | |———–|—–|—–| | Observe | webRequest | webRequest | | Block | webRequestBlocking | declarativeNetRequest | | Modify headers | webRequestBlocking | declarativeNetRequest | | Redirect | webRequestBlocking | declarativeNetRequest |
Required: Host Permissions
{ "permissions": ["webRequest"], "host_permissions": ["<all_urls>"] }
Using with @theluckystrike/webext-permissions
import { checkPermission, requestPermission } from "@theluckystrike/webext-permissions";
const result = await checkPermission("webRequest");
// { description: "Observe and modify network requests", granted: bool }
import { PERMISSION_DESCRIPTIONS } from "@theluckystrike/webext-permissions";
PERMISSION_DESCRIPTIONS.webRequest; // "Observe and modify network requests"
PERMISSION_DESCRIPTIONS.declarativeNetRequest; // "Block or modify network requests"
PERMISSION_DESCRIPTIONS.declarativeNetRequestFeedback; // "Get feedback on declarative net requests"
Using with @theluckystrike/webext-messaging
Request logger: background monitors, popup displays:
type Messages = {
getRequestLog: { request: { limit: number }; response: Array<{ url: string; method: string; statusCode: number; timestamp: number }> };
getBlockedCount: { request: void; response: { count: number } };
};
// background.ts
import { createMessenger } from "@theluckystrike/webext-messaging";
const msg = createMessenger<Messages>();
const requestLog: Array<{ url: string; method: string; statusCode: number; timestamp: number }> = [];
chrome.webRequest.onCompleted.addListener(
(details) => {
requestLog.push({ url: details.url, method: details.method, statusCode: details.statusCode, timestamp: details.timeStamp });
if (requestLog.length > 500) requestLog.splice(0, requestLog.length - 500);
},
{ urls: ["<all_urls>"] }
);
msg.onMessage({
getRequestLog: ({ limit }) => requestLog.slice(-limit),
getBlockedCount: () => ({ count: requestLog.filter(r => r.statusCode >= 400).length }),
});
Using with @theluckystrike/webext-storage
import { defineSchema, createStorage } from "@theluckystrike/webext-storage";
const schema = defineSchema({
monitoringEnabled: true,
monitoredDomains: [] as string[],
logRetentionDays: 7,
});
const storage = createStorage({ schema });
storage.watch("monitoringEnabled", (enabled) => {
if (enabled) startMonitoring();
else stopMonitoring();
});
Event Lifecycle
onBeforeRequest -> onBeforeSendHeaders -> onSendHeaders ->
onHeadersReceived -> onResponseStarted -> onCompleted
-> onErrorOccurred
Key Events
| Event | When | Use Case |
|——-|——|———-|
| onBeforeRequest | Before request sent | Log URLs, observe bodies |
| onBeforeSendHeaders | Before headers sent | Observe outgoing headers |
| onHeadersReceived | Response headers in | Observe content-type |
| onCompleted | Request finished | Log status, timing |
| onErrorOccurred | Request failed | Track network errors |
Common Patterns
- Network request logger/debugger
- Privacy monitor (third-party tracker counting)
- Performance monitor (request timing)
- API traffic inspector
Gotchas
- MV3: READ-ONLY — cannot block, redirect, or modify
host_permissionsrequired — no events without them- Service worker lifecycle: register listeners synchronously at top level
- High-traffic sites = thousands of events — always filter with URL patterns
requestBodyneeds"extraInfoSpec": ["requestBody"]
declarativeNetRequest for Blocking (MV3)
{
"permissions": ["declarativeNetRequest"],
"declarative_net_request": {
"rule_resources": [{ "id": "ruleset_1", "enabled": true, "path": "rules.json" }]
}
}
Related Permissions
- cookies, tabs, activeTab
- declarativeNetRequest — MV3 replacement for request blocking/modification
API Reference
Frequently Asked Questions
What is webRequest API used for?
The webRequest API allows extensions to intercept, block, or modify network requests before they’re sent.
Is webRequest available in Manifest V3?
In MV3, webRequest is available but blocking is limited. Use declarativeNetRequest for most blocking scenarios instead. —
Part of the Chrome Extension Guide by theluckystrike. Built at zovo.one.