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.
9 <pre data-filename=
"manifest.json">
11 "name":
"My extension",
21 <h2 id=
"life_cycle">Life cycle of requests
</h2>
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.
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"/>
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>
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.
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>
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
100 <li>Authorization
</li>
101 <li>Cache-Control
</li>
103 <li>Content-Length
</li>
105 <li>If-Modified-Since
</li>
106 <li>If-None-Match
</li>
108 <li>Partial-Data
</li>
110 <li>Proxy-Authorization
</li>
111 <li>Proxy-Connection
</li>
112 <li>Transfer-Encoding
</li>
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>,
124 <code>file://
</code>, or
125 <code>chrome-extension://
</code>.
126 In addition, even certain requests with URLs using one of the above schemes
128 <code>chrome-extension://other_extension_id
</code> where
129 <code>other_extension_id
</code> is not the ID of the extension to handle
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
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.
142 <h2 id=
"concepts">Concepts
</h2>
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>
148 <h3 id=
"Request IDs">Request IDs
</h3>
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>
156 <h3 id=
"subscription">Registering event listeners
</h3>
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
164 <p>The three arguments to the web request API's
<code>addListener()
</code> have
165 the following definitions:
</p>
167 var callback = function(details) {...};
169 var opt_extraInfoSpec = [...];
172 <p>Here's an example of listening for the
<code>onBeforeRequest
</code>
175 chrome.webRequest.onBeforeRequest.addListener(
176 callback, filter, opt_extraInfoSpec);
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>
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>
196 <p>The $ref:webRequest.RequestFilter
197 <code>filter
</code> allows limiting the requests for which events are
198 triggered in various dimensions:
201 <dd><a href=
"match_patterns.html">URL patterns
</a> such as
202 <code>*://www.google.com/foo*bar
</code>.
</dd>
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>
209 <dd>The identifier for one tab.
</dd>
211 <dd>The identifier for a window.
</dd>
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>
219 <h2 id=
"implementation">Implementation details
</h2>
221 <p>Several implementation details can be important to understand when developing
222 an extension that uses the web request API:
</p>
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>
234 <h3 id=
"caching">Caching
</h3>
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
248 <h3 id=
"timestamps">Timestamps
</h3>
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.
257 <h2 id=
"examples">Examples
</h2>
259 <p>The following example illustrates how to block all requests to
260 <code>www.evil.com
</code>:
</p>
262 chrome.webRequest.onBeforeRequest.addListener(
264 return {cancel: details.url.indexOf(
"://www.evil.com/") != -
1};
266 {urls: [
"<all_urls>"]},
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>
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>
277 chrome.webRequest.onBeforeRequest.addListener(
278 function(details) { return {cancel: true}; },
279 {urls: [
"*://www.evil.com/*"]},
283 <p>The following example illustrates how to delete the User-Agent header from
286 chrome.webRequest.onBeforeSendHeaders.addListener(
288 for (var i =
0; i < details.requestHeaders.length; ++i) {
289 if (details.requestHeaders[i].name === 'User-Agent') {
290 details.requestHeaders.splice(i,
1);
294 return {requestHeaders: details.requestHeaders};
296 {urls: [
"<all_urls>"]},
297 [
"blocking",
"requestHeaders"]);
300 <p> For more example code, see the
<a href=
"samples.html#webrequest">web request