1 <h2 id="manifest">Manifest</h2> 2 <p>You must declare the "webRequest" permission in the <a 3 href="manifest">extension manifest</a> to use the web request 4 API, along with <a href="declare_permissions">host permissions</a> 5 for any hosts whose network requests you want to access. If you want to 6 use the web request API in a blocking fashion, you need to request 7 the "webRequestBlocking" permission in addition. 8 For example:</p> 9 <pre data-filename="manifest.json"> 10 { 11 "name": "My extension", 12 ... 13 <b>"permissions": [ 14 "webRequest", 15 "*://*.google.com/" 16 ]</b>, 17 ... 18 } 19 </pre> 20 21 <h2 id="life_cycle">Life cycle of requests</h2> 22 23 <p> 24 The web request API defines a set of events that follow the life cycle of a web 25 request. You can use these events to observe and analyze traffic. Certain 26 synchronous events will allow you to intercept, block, or modify a request. 27 </p> 28 29 <p> 30 The event life cycle for successful requests is illustrated here, followed by 31 event definitions:<br/> 32 <img src="{{static}}/images/webrequestapi.png" 33 width="385" height="503" 34 alt="Life cycle of a web request from the perspective of the webrequest API" 35 style="margin-left: auto; margin-right: auto; display: block"/> 36 </p> 37 38 <p> 39 <dl> 40 <dt><code>onBeforeRequest</code> (optionally synchronous)</dt> 41 <dd>Fires when a request is about to occur. This event is sent before any TCP 42 connection is made and can be used to cancel or redirect requests.</dd> 43 <dt><code>onBeforeSendHeaders</code> (optionally synchronous)</dt> 44 <dd>Fires when a request is about to occur and the initial headers have been 45 prepared. The event is intended to allow extensions to add, modify, and delete 46 request headers <a href="#life_cycle_footnote">(*)</a>. The 47 <code>onBeforeSendHeaders</code> event is passed to all subscribers, so 48 different subscribers may attempt to modify the request; see the <a 49 href="#implementation">Implementation details</a> section for how this is 50 handled. This event can be used to cancel the request.</dd> 51 <dt><code>onSendHeaders</code></dt> 52 <dd>Fires after all extensions have had a chance to modify the request 53 headers, and presents the final <a href="#life_cycle_footnote">(*)</a> 54 version. The event is triggered before the headers are sent to the network. 55 This event is informational and handled asynchronously. It does not allow 56 modifying or cancelling the request.</dd> 57 <dt><code>onHeadersReceived</code> (optionally synchronous)</dt> 58 <dd>Fires each time that an HTTP(S) response header is received. Due 59 to redirects and authentication requests this can happen multiple times per 60 request. This event is intended to allow extensions to add, modify, and delete 61 response headers, such as incoming Set-Cookie headers. The caching directives 62 are processed before this event is triggered, so modifying headers such as 63 Cache-Control has no influence on the browser's cache. 64 It also allows you to redirect the request.</dd> 65 <dt><code>onAuthRequired</code> (optionally synchronous)</dt> 66 <dd>Fires when a request requires authentication of the user. This event can 67 be handled synchronously to provide authentication credentials. Note that 68 extensions may provide invalid credentials. Take care not to enter an infinite 69 loop by repeatedly providing invalid credentials.</dd> 70 <dt><code>onBeforeRedirect</code></dt> 71 <dd>Fires when a redirect is about to be executed. A redirection can be 72 triggered by an HTTP response code or by an extension. This event is 73 informational and handled asynchronously. It does not allow you to modify or 74 cancel the request. </dd> 75 <dt><code>onResponseStarted</code></dt> 76 <dd>Fires when the first byte of the response body is received. For HTTP 77 requests, this means that the status line and response headers are 78 available. This event is informational and handled asynchronously. It does not 79 allow modifying or cancelling the request.</dd> 80 <dt><code>onCompleted</code></dt> 81 <dd>Fires when a request has been processed successfully.</dd> 82 <dt><code>onErrorOccurred</code></dt> 83 <dd>Fires when a request could not be processed successfully.</dd> 84 </dl> 85 The web request API guarantees that for each request either 86 <code>onCompleted</code> or <code>onErrorOccurred</code> is fired as the final 87 event with one exception: If a request is redirected to a <code>data://</code> 88 URL, <code>onBeforeRedirect</code> is the last reported event. 89 </p> 90 91 <p id="life_cycle_footnote">(*) Note that the web request API presents an 92 abstraction of the network stack to the extension. Internally, one URL request 93 can be split into several HTTP requests (for example to fetch individual byte 94 ranges from a large file) or can be handled by the network stack without 95 communicating with the network. For this reason, the API does not provide the 96 final HTTP headers that are sent to the network. For example, all headers that 97 are related to caching are invisible to the extension.</p> 98 99 <p>The following headers are currently <b>not provided</b> to the 100 <code>onBeforeSendHeaders</code> event. This list is not guaranteed to be 101 complete nor stable. 102 <ul> 103 <li>Authorization</li> 104 <li>Cache-Control</li> 105 <li>Connection</li> 106 <li>Content-Length</li> 107 <li>Host</li> 108 <li>If-Modified-Since</li> 109 <li>If-None-Match</li> 110 <li>If-Range</li> 111 <li>Partial-Data</li> 112 <li>Pragma</li> 113 <li>Proxy-Authorization</li> 114 <li>Proxy-Connection</li> 115 <li>Transfer-Encoding</li> 116 </ul> 117 </p> 118 119 <p> 120 The webRequest API only exposes requests that the extension has 121 permission to see, given its 122 <a href="declare_permissions">host permissions</a>. 123 Moreover, only the following schemes are accessible: 124 <code>http://</code>, 125 <code>https://</code>, 126 <code>ftp://</code>, 127 <code>file://</code>, or 128 <code>chrome-extension://</code>. 129 In addition, even certain requests with URLs using one of the above schemes 130 are hidden, e.g., 131 <code>chrome-extension://other_extension_id</code> where 132 <code>other_extension_id</code> is not the ID of the extension to handle 133 the request, 134 <code>https://www.google.com/chrome</code>, 135 and others (this list is not complete). Also synchronous XMLHttpRequests from 136 your extension are hidden from blocking event handlers in order to prevent 137 deadlocks. 138 Note that for some of the supported schemes the set of available events might be 139 limited due to the nature of the corresponding protocol. 140 For example, for the <q>file:</q> scheme, only <code>onBeforeRequest</code>, 141 <code>onResponseStarted</code>, <code>onCompleted</code>, and 142 <code>onErrorOccurred</code> may be dispatched. 143 </p> 144 145 <h2 id="concepts">Concepts</h2> 146 147 <p>As the following sections explain, events in the web request API use request 148 IDs, and you can optionally specify filters and extra information when you 149 register event listeners.</p> 150 151 <h3 id="Request IDs">Request IDs</h3> 152 153 <p>Each request is identified by a request ID. This ID is unique within a 154 browser session and the context of an extension. It remains constant during the 155 the life cycle of a request and can be used to match events for the same 156 request. Note that several HTTP requests are mapped to one web request in case 157 of HTTP redirection or HTTP authentication.</p> 158 159 <h3 id="subscription">Registering event listeners</h3> 160 161 <p>To register an event listener for a web request, you use a variation on the 162 <a href="events">usual <code>addListener()</code> function</a>. 163 In addition to specifying a callback function, 164 you have to specify a filter argument and you may specify an optional extra info 165 argument.</p> 166 167 <p>The three arguments to the web request API's <code>addListener()</code> have 168 the following definitions:</p> 169 <pre> 170 var callback = function(details) {...}; 171 var filter = {...}; 172 var opt_extraInfoSpec = [...]; 173 </pre> 174 175 <p>Here's an example of listening for the <code>onBeforeRequest</code> 176 event:</p> 177 <pre> 178 chrome.webRequest.onBeforeRequest.addListener( 179 callback, filter, opt_extraInfoSpec); 180 </pre> 181 182 <p>Each <code>addListener()</code> call takes a mandatory callback function as 183 the first parameter. This callback function is passed a dictionary containing 184 information about the current URL request. The information in this dictionary 185 depends on the specific event type as well as the content of 186 <code>opt_extraInfoSpec</code>.</p> 187 188 <p>If the optional <code>opt_extraInfoSpec</code> array contains the string 189 <code>'blocking'</code> (only allowed for specific events), the callback 190 function is handled synchronously. That means that the request is blocked until 191 the callback function returns. In this case, the callback can return a 192 $(ref:webRequest.BlockingResponse) that determines the further 193 life cycle of the request. Depending on the context, this response allows 194 cancelling or redirecting a request (<code>onBeforeRequest</code>), cancelling a 195 request or modifying headers (<code>onBeforeSendHeaders</code>, 196 <code>onHeadersReceived</code>), or providing authentication credentials 197 (<code>onAuthRequired</code>).</p> 198 199 <p>The $(ref:webRequest.RequestFilter) 200 <code>filter</code> allows limiting the requests for which events are 201 triggered in various dimensions: 202 <dl> 203 <dt>URLs</dt> 204 <dd><a href="match_patterns">URL patterns</a> such as 205 <code>*://www.google.com/foo*bar</code>.</dd> 206 <dt>Types</dt> 207 <dd>Request types such as <code>main_frame</code> (a document that is loaded 208 for a top-level frame), <code>sub_frame</code> (a document that is loaded for 209 an embedded frame), and <code>image</code> (an image on a web site). 210 See $(ref:webRequest.RequestFilter).</dd> 211 <dt>Tab ID</dt> 212 <dd>The identifier for one tab.</dd> 213 <dt>Window ID</dt> 214 <dd>The identifier for a window.</dd> 215 </p> 216 217 <p>Depending on the event type, you can specify strings in 218 <code>opt_extraInfoSpec</code> to ask for additional information about the 219 request. This is used to provide detailed information on request's data only 220 if explicitly requested.</p> 221 222 <h2 id="implementation">Implementation details</h2> 223 224 <p>Several implementation details can be important to understand when developing 225 an extension that uses the web request API:</p> 226 227 <h3 id="conflict_resolution">Conflict resolution</h3> 228 <p>In the current implementation of the web request API, a request is considered 229 as cancelled if at least one extension instructs to cancel the request. If 230 an extension cancels a request, all extensions are notified by an 231 <code>onErrorOccurred</code> event. Only one extension is allowed to redirect a 232 request or modify a header at a time. If more than one extension attempts to 233 modify the request, the most recently installed extension wins and all others 234 are ignored. An extension is not notified if its instruction to modify or 235 redirect has been ignored.</p> 236 237 <h3 id="caching">Caching</h3> 238 <p> 239 Chrome employs two caches — an on-disk cache and a very fast in-memory 240 cache. The lifetime of an in-memory cache is attached to the lifetime of a 241 render process, which roughly corresponds to a tab. Requests that are answered 242 from the in-memory cache are invisible to the web request API. If a request 243 handler changes its behavior (for example, the behavior according to which 244 requests are blocked), a simple page refresh might not respect this changed 245 behavior. To make sure the behavior change goes through, call 246 <code>handlerBehaviorChanged()</code> to flush the in-memory cache. But don't do 247 it often; flushing the cache is a very expensive operation. You don't need to 248 call <code>handlerBehaviorChanged()</code> after registering or unregistering an 249 event listener.</p> 250 251 <h3 id="timestamps">Timestamps</h3> 252 <p> 253 The <code>timestamp</code> property of web request events is only guaranteed to 254 be <i>internally</i> consistent. Comparing one event to another event will give 255 you the correct offset between them, but comparing them to the current time 256 inside the extension (via <code>(new Date()).getTime()</code>, for instance) 257 might give unexpected results. 258 </p> 259 260 <h3 id="error_handling">Error handling</h3> 261 <p> 262 If you try to register an event with invalid arguments, then a JavaScript error 263 will be thrown, and the event handler will not be registered. 264 265 If an error is thrown while an event is handled, or if an event handler returns 266 an invalid blocking response, an error message is logged to your extension's 267 console and the handler is ignored for that request. 268 </p> 269 270 <h2 id="examples">Examples</h2> 271 272 <p>The following example illustrates how to block all requests to 273 <code>www.evil.com</code>:</p> 274 <pre> 275 chrome.webRequest.onBeforeRequest.addListener( 276 function(details) { 277 return {cancel: details.url.indexOf("://www.evil.com/") != -1}; 278 }, 279 {urls: ["<all_urls>"]}, 280 ["blocking"]); 281 </pre> 282 283 <p>As this function uses a blocking event handler, it requires the "webRequest" 284 as well as the "webRequestBlocking" permission in the manifest file.</p> 285 286 <p>The following example achieves the same goal in a more efficient way because 287 requests that are not targeted to <code>www.evil.com</code> do not need to be 288 passed to the extension:</p> 289 <pre> 290 chrome.webRequest.onBeforeRequest.addListener( 291 function(details) { return {cancel: true}; }, 292 {urls: ["*://www.evil.com/*"]}, 293 ["blocking"]); 294 </pre> 295 296 <p>The following example illustrates how to delete the User-Agent header from 297 all requests:</p> 298 <pre> 299 chrome.webRequest.onBeforeSendHeaders.addListener( 300 function(details) { 301 for (var i = 0; i < details.requestHeaders.length; ++i) { 302 if (details.requestHeaders[i].name === 'User-Agent') { 303 details.requestHeaders.splice(i, 1); 304 break; 305 } 306 } 307 return {requestHeaders: details.requestHeaders}; 308 }, 309 {urls: ["<all_urls>"]}, 310 ["blocking", "requestHeaders"]); 311 </pre> 312 313 <p> For more example code, see the <a href="samples#webrequest">web request 314 samples</a>.</p> 315