Chrome Extension Fetch Interceptor — Best Practices

5 min read

Fetch/XHR Interception Patterns

This document covers patterns for intercepting and modifying network requests in Chrome extensions using MV3.

Overview

Chrome extensions can intercept, modify, block, or redirect network requests through several mechanisms:

declarativeNetRequest (MV3)

The declarativeNetRequest API is the MV3 approach for modifying network requests without requiring host permissions.

Static Rules

Static rules are defined in the manifest and loaded at extension startup:

{
  "declarative_net_request": {
    "rule_resources": [{
      "id": "ruleset_1",
      "enabled": true,
      "path": "rules/block-ads.json"
    }]
  }
}

Dynamic Rules

Dynamic rules can be added at runtime:

chrome.declarativeNetRequest.updateDynamicRules({
  addRules: [{
    id: 1,
    priority: 1,
    action: { type: "block" },
    condition: { urlFilter: "*.ads.example.com", resourceTypes: ["script"] }
  }]
});

Blocking Patterns

Block specific requests using URL filters:

{
  "id": 1,
  "priority": 1,
  "action": { type: "block" },
  "condition": {
    "urlFilter": "tracking-pixel",
    "resourceTypes": ["image", "script"]
  }
}

Redirect Patterns

Redirect requests to alternative URLs:

{
  "id": 2,
  "priority": 1,
  "action": {
    "type": "redirect",
    "redirect": { "url": "https://cdn.example.com/image.png" }
  },
  "condition": {
    "urlFilter": "old-cdn.example.com",
    "resourceTypes": ["image"]
  }
}

CDN Switching

Rewrite URLs to use different CDNs:

{
  "id": 3,
  "priority": 1,
  "action": {
    "type": "redirect",
    "redirect": { "transform": { "host": "fast-cdn.com" } }
  },
  "condition": {
    "urlFilter": "slow-cdn.com",
    "resourceTypes": ["script"]
  }
}

Modifying Headers

Use modifyHeaders to add, remove, or set request/response headers:

{
  "id": 4,
  "priority": 1,
  "action": {
    "type": "modifyHeaders",
    "requestHeaders": [
      { "header": "User-Agent", "operation": "set", "value": "MyExtension/1.0" }
    ]
  },
  "condition": {
    "urlFilter": "api.example.com",
    "resourceTypes": ["xmlhttprequest"]
  }
}

Programmatic Interception (Content Scripts)

For intercepting requests within page context, monkey-patch fetch and XMLHttpRequest:

// Inject via content script with world: "MAIN"
const script = document.createElement('script');
script.textContent = `
  const originalFetch = window.fetch;
  window.fetch = async function(...args) {
    const [resource, options = {}] = args;
    
    // Add custom headers
    options.headers = {
      ...options.headers,
      'X-Custom-Header': 'value'
    };
    
    // Log request
    console.log('Intercepted fetch:', resource);
    
    return originalFetch(resource, options);
  };
`;
chrome.scripting.executeScript({
  target: { tabId: tab.id },
  world: "MAIN",
  func: () => document.documentElement.appendChild(script)
});

Observing Requests (webRequest)

Use chrome.webRequest for read-only observation (non-blocking):

chrome.webRequest.onCompleted.addListener(
  (details) => {
    console.log('Request completed:', details.url, details.statusCode);
  },
  { urls: ["<all_urls>"] }
);

chrome.webRequest.onBeforeRequest.addListener(
  (details) => {
    console.log('Request started:', details.url);
  },
  { urls: ["<all_urls>"] }
);

Note: In MV3, blocking via webRequest (webRequestBlocking) is no longer available for most extensions. Only policy-installed extensions retain access. Use declarativeNetRequest instead for request blocking and modification.

Security Considerations

Reading Response Data

The declarativeNetRequest API cannot read response bodies. For content inspection:

  1. Use content script injection with monkey-patching
  2. Intercept fetch or XMLHttpRequest to access response data
  3. Consider using chrome.debugger for deeper inspection (requires user consent)

Cross-References

Part of the Chrome Extension Guide by theluckystrike. Built at zovo.one.