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