| <h2 id="manifest">Manifest</h2> |
| <p>You must declare the "webRequest" permission in the <a |
| href="manifest">extension manifest</a> to use the web request |
| API, along with the necessary |
| <a href="declare_permissions">host permissions</a>. To intercept a sub-resource |
| request, the extension needs to have access to both the requested URL and its |
| initiator. If you want to use the web request API in a blocking fashion, you |
| need to request the "webRequestBlocking" permission in addition. |
| For example:</p> |
| <pre data-filename="manifest.json"> |
| { |
| "name": "My extension", |
| ... |
| <b>"permissions": [ |
| "webRequest", |
| "*://*.google.com/" |
| ]</b>, |
| ... |
| } |
| </pre> |
| |
| <h2 id="life_cycle">Life cycle of requests</h2> |
| |
| <p> |
| The web request API defines a set of events that follow the life cycle of a web |
| request. You can use these events to observe and analyze traffic. Certain |
| synchronous events will allow you to intercept, block, or modify a request. |
| </p> |
| |
| <p> |
| The event life cycle for successful requests is illustrated here, followed by |
| event definitions:<br/> |
| <img src="{{static}}/images/webrequestapi.png" |
| width="385" height="503" |
| alt="Life cycle of a web request from the perspective of the webrequest API" |
| style="margin-left: auto; margin-right: auto; display: block"/> |
| </p> |
| |
| <p> |
| <dl> |
| <dt><code>onBeforeRequest</code> (optionally synchronous)</dt> |
| <dd>Fires when a request is about to occur. This event is sent before any TCP |
| connection is made and can be used to cancel or redirect requests.</dd> |
| <dt><code>onBeforeSendHeaders</code> (optionally synchronous)</dt> |
| <dd>Fires when a request is about to occur and the initial headers have been |
| prepared. The event is intended to allow extensions to add, modify, and delete |
| request headers <a href="#life_cycle_footnote">(*)</a>. The |
| <code>onBeforeSendHeaders</code> event is passed to all subscribers, so |
| different subscribers may attempt to modify the request; see the <a |
| href="#implementation">Implementation details</a> section for how this is |
| handled. This event can be used to cancel the request.</dd> |
| <dt><code>onSendHeaders</code></dt> |
| <dd>Fires after all extensions have had a chance to modify the request |
| headers, and presents the final <a href="#life_cycle_footnote">(*)</a> |
| version. The event is triggered before the headers are sent to the network. |
| This event is informational and handled asynchronously. It does not allow |
| modifying or cancelling the request.</dd> |
| <dt><code>onHeadersReceived</code> (optionally synchronous)</dt> |
| <dd>Fires each time that an HTTP(S) response header is received. Due to |
| redirects and authentication requests this can happen multiple times per |
| request. This event is intended to allow extensions to add, modify, and delete |
| response headers, such as incoming Content-Type headers. The caching |
| directives are processed before this event is triggered, so modifying headers |
| such as Cache-Control has no influence on the browser's cache. |
| It also allows you to cancel or redirect the request.</dd> |
| <dt><code>onAuthRequired</code> (optionally synchronous)</dt> |
| <dd>Fires when a request requires authentication of the user. This event can |
| be handled synchronously to provide authentication credentials. Note that |
| extensions may provide invalid credentials. Take care not to enter an infinite |
| loop by repeatedly providing invalid credentials. This can also be used to |
| cancel the request.</dd> |
| <dt><code>onBeforeRedirect</code></dt> |
| <dd>Fires when a redirect is about to be executed. A redirection can be |
| triggered by an HTTP response code or by an extension. This event is |
| informational and handled asynchronously. It does not allow you to modify or |
| cancel the request. </dd> |
| <dt><code>onResponseStarted</code></dt> |
| <dd>Fires when the first byte of the response body is received. For HTTP |
| requests, this means that the status line and response headers are |
| available. This event is informational and handled asynchronously. It does not |
| allow modifying or cancelling the request.</dd> |
| <dt><code>onCompleted</code></dt> |
| <dd>Fires when a request has been processed successfully.</dd> |
| <dt><code>onErrorOccurred</code></dt> |
| <dd>Fires when a request could not be processed successfully.</dd> |
| </dl> |
| The web request API guarantees that for each request either |
| <code>onCompleted</code> or <code>onErrorOccurred</code> is fired as the final |
| event with one exception: If a request is redirected to a <code>data://</code> |
| URL, <code>onBeforeRedirect</code> is the last reported event. |
| </p> |
| |
| <p id="life_cycle_footnote">(*) Note that the web request API presents an |
| abstraction of the network stack to the extension. Internally, one URL request |
| can be split into several HTTP requests (for example to fetch individual byte |
| ranges from a large file) or can be handled by the network stack without |
| communicating with the network. For this reason, the API does not provide the |
| final HTTP headers that are sent to the network. For example, all headers that |
| are related to caching are invisible to the extension.</p> |
| |
| <p>The following headers are currently <b>not provided</b> to the |
| <code>onBeforeSendHeaders</code> event. This list is not guaranteed to be |
| complete nor stable. |
| <ul> |
| <li>Authorization</li> |
| <li>Cache-Control</li> |
| <li>Connection</li> |
| <li>Content-Length</li> |
| <li>Host</li> |
| <li>If-Modified-Since</li> |
| <li>If-None-Match</li> |
| <li>If-Range</li> |
| <li>Partial-Data</li> |
| <li>Pragma</li> |
| <li>Proxy-Authorization</li> |
| <li>Proxy-Connection</li> |
| <li>Transfer-Encoding</li> |
| </ul> |
| </p> |
| |
| <p> |
| <span class="availability">Starting from Chrome 79</span>, request header |
| modifications affect Cross-Origin Resource Sharing (CORS) checks. If modified |
| headers for cross-origin requests do not meet the criteria, it will result in |
| sending a CORS preflight to ask the server if such headers can be accepted. |
| If you really need to modify headers in a way to violate the CORS protocol, you |
| need to specify <code>'extraHeaders'</code> in <code>opt_extraInfoSpec</code>. |
| On the other hand, response header modifications do not work to deceive CORS |
| checks. If you need to deceive the CORS protocol, you also need to specify |
| <code>'extraHeaders'</code> for the response modifications. |
| </p> |
| |
| <p> |
| <span class="availability">Starting from Chrome 79</span>, the webRequest API |
| <strong>does not</strong> intercept CORS preflight requests and responses by |
| default. A CORS preflight for a request URL is visible to an extension if there |
| is a listener with <code>'extraHeaders'</code> specified in |
| <code>opt_extraInfoSpec</code> for the request URL. <code>onBeforeRequest</code> |
| can also take <code>'extraHeaders'</code> from Chrome 79. |
| </p> |
| |
| <p> |
| <span class="availability">Starting from Chrome 79</span>, the following request |
| header is <strong>not provided</strong> and cannot be modified or removed |
| without specifying <code>'extraHeaders'</code> in |
| <code>opt_extraInfoSpec</code>: |
| <ul> |
| <li>Origin</li> |
| </ul> |
| </p> |
| |
| <p> |
| <span class="availability">Starting from Chrome 72</span>, the following request |
| headers are <strong>not provided</strong> and cannot be modified or removed |
| without specifying <code>'extraHeaders'</code> in |
| <code>opt_extraInfoSpec</code>: |
| <ul> |
| <li>Accept-Language</li> |
| <li>Accept-Encoding</li> |
| <li>Referer</li> |
| <li>Cookie</li> |
| </ul> |
| </p> |
| |
| <p> |
| <span class="availability">Starting from Chrome 72</span>, the Set-Cookie |
| response header is <strong>not provided</strong> and cannot be modified or |
| removed without specifying <code>'extraHeaders'</code> in |
| <code>opt_extraInfoSpec</code>. |
| </p> |
| |
| <p class="note"> |
| <strong>Note:</strong> Specifying <code>'extraHeaders'</code> in |
| <code>opt_extraInfoSpec</code> may have a negative impact on performance, hence |
| it should only be used when really necessary. |
| <p> |
| |
| <p> |
| The webRequest API only exposes requests that the extension has |
| permission to see, given its |
| <a href="declare_permissions">host permissions</a>. |
| Moreover, only the following schemes are accessible: |
| <code>http://</code>, |
| <code>https://</code>, |
| <code>ftp://</code>, |
| <code>file://</code>, |
| <code>ws://</code> (<span class="availability">since Chrome 58</span>), |
| <code>wss://</code> (<span class="availability">since Chrome 58</span>), or |
| <code>chrome-extension://</code>. |
| In addition, even certain requests with URLs using one of the above schemes |
| are hidden. These include |
| <code>chrome-extension://other_extension_id</code> where |
| <code>other_extension_id</code> is not the ID of the extension to handle |
| the request, |
| <code>https://www.google.com/chrome</code>, |
| and other sensitive requests core to browser functionality. Also synchronous |
| XMLHttpRequests from your extension are hidden from blocking event handlers in |
| order to prevent deadlocks. |
| Note that for some of the supported schemes the set of available events might be |
| limited due to the nature of the corresponding protocol. |
| For example, for the <q>file:</q> scheme, only <code>onBeforeRequest</code>, |
| <code>onResponseStarted</code>, <code>onCompleted</code>, and |
| <code>onErrorOccurred</code> may be dispatched. |
| </p> |
| |
| <p> |
| <span class="availability">Starting from Chrome 58</span>, the webRequest API |
| supports intercepting the WebSocket handshake request. Since the handshake is |
| done by means of an HTTP upgrade request, its flow fits into HTTP-oriented |
| webRequest model. Note that the API does <b>not intercept</b>: |
| <ul> |
| <li>Individual messages sent over an established WebSocket connection.</li> |
| <li>WebSocket closing connection.</li> |
| </ul> |
| Redirects are <b>not supported</b> for WebSocket requests. |
| </p> |
| |
| <p> |
| <span class="availability">Starting from Chrome 72</span>, an extension will be |
| able to intercept a request only if it has host permissions to both the |
| requested URL and the request initiator. |
| </p> |
| |
| <h2 id="concepts">Concepts</h2> |
| |
| <p>As the following sections explain, events in the web request API use request |
| IDs, and you can optionally specify filters and extra information when you |
| register event listeners.</p> |
| |
| <h3 id="Request IDs">Request IDs</h3> |
| |
| <p>Each request is identified by a request ID. This ID is unique within a |
| browser session and the context of an extension. It remains constant during the |
| the life cycle of a request and can be used to match events for the same |
| request. Note that several HTTP requests are mapped to one web request in case |
| of HTTP redirection or HTTP authentication.</p> |
| |
| <h3 id="subscription">Registering event listeners</h3> |
| |
| <p>To register an event listener for a web request, you use a variation on the |
| <a href="events">usual <code>addListener()</code> function</a>. |
| In addition to specifying a callback function, |
| you have to specify a filter argument and you may specify an optional extra info |
| argument.</p> |
| |
| <p>The three arguments to the web request API's <code>addListener()</code> have |
| the following definitions:</p> |
| <pre> |
| var callback = function(details) {...}; |
| var filter = {...}; |
| var opt_extraInfoSpec = [...]; |
| </pre> |
| |
| <p>Here's an example of listening for the <code>onBeforeRequest</code> |
| event:</p> |
| <pre> |
| chrome.webRequest.onBeforeRequest.addListener( |
| callback, filter, opt_extraInfoSpec); |
| </pre> |
| |
| <p>Each <code>addListener()</code> call takes a mandatory callback function as |
| the first parameter. This callback function is passed a dictionary containing |
| information about the current URL request. The information in this dictionary |
| depends on the specific event type as well as the content of |
| <code>opt_extraInfoSpec</code>.</p> |
| |
| <p>If the optional <code>opt_extraInfoSpec</code> array contains the string |
| <code>'blocking'</code> (only allowed for specific events), the callback |
| function is handled synchronously. That means that the request is blocked until |
| the callback function returns. In this case, the callback can return a |
| $(ref:webRequest.BlockingResponse) that determines the further |
| life cycle of the request. Depending on the context, this response allows |
| cancelling or redirecting a request (<code>onBeforeRequest</code>), cancelling a |
| request or modifying headers (<code>onBeforeSendHeaders</code>, |
| <code>onHeadersReceived</code>), and cancelling a request or providing |
| authentication credentials (<code>onAuthRequired</code>).</p> |
| |
| <p>If the optional <code>opt_extraInfoSpec</code> array contains the string |
| <code>'asyncBlocking'</code> instead (only allowed for |
| <code>onAuthRequired</code>), the extension can generate the |
| $(ref:webRequest.BlockingResponse) asynchronously. |
| |
| <p>The $(ref:webRequest.RequestFilter) |
| <code>filter</code> allows limiting the requests for which events are |
| triggered in various dimensions: |
| <dl> |
| <dt>URLs</dt> |
| <dd><a href="match_patterns">URL patterns</a> such as |
| <code>*://www.google.com/foo*bar</code>.</dd> |
| <dt>Types</dt> |
| <dd>Request types such as <code>main_frame</code> (a document that is loaded |
| for a top-level frame), <code>sub_frame</code> (a document that is loaded for |
| an embedded frame), and <code>image</code> (an image on a web site). |
| See $(ref:webRequest.RequestFilter).</dd> |
| <dt>Tab ID</dt> |
| <dd>The identifier for one tab.</dd> |
| <dt>Window ID</dt> |
| <dd>The identifier for a window.</dd> |
| </p> |
| |
| <p>Depending on the event type, you can specify strings in |
| <code>opt_extraInfoSpec</code> to ask for additional information about the |
| request. This is used to provide detailed information on request's data only |
| if explicitly requested.</p> |
| |
| <h2 id="implementation">Implementation details</h2> |
| |
| <p>Several implementation details can be important to understand when developing |
| an extension that uses the web request API:</p> |
| |
| <h3 id="conflict_resolution">Conflict resolution</h3> |
| <p>In the current implementation of the web request API, a request is considered |
| as cancelled if at least one extension instructs to cancel the request. If |
| an extension cancels a request, all extensions are notified by an |
| <code>onErrorOccurred</code> event. Only one extension is allowed to redirect a |
| request or modify a header at a time. If more than one extension attempts to |
| modify the request, the most recently installed extension wins and all others |
| are ignored. An extension is not notified if its instruction to modify or |
| redirect has been ignored.</p> |
| |
| <h3 id="caching">Caching</h3> |
| <p> |
| Chrome employs two caches — an on-disk cache and a very fast in-memory |
| cache. The lifetime of an in-memory cache is attached to the lifetime of a |
| render process, which roughly corresponds to a tab. Requests that are answered |
| from the in-memory cache are invisible to the web request API. If a request |
| handler changes its behavior (for example, the behavior according to which |
| requests are blocked), a simple page refresh might not respect this changed |
| behavior. To make sure the behavior change goes through, call |
| <code>handlerBehaviorChanged()</code> to flush the in-memory cache. But don't do |
| it often; flushing the cache is a very expensive operation. You don't need to |
| call <code>handlerBehaviorChanged()</code> after registering or unregistering an |
| event listener.</p> |
| |
| <h3 id="timestamps">Timestamps</h3> |
| <p> |
| The <code>timestamp</code> property of web request events is only guaranteed to |
| be <i>internally</i> consistent. Comparing one event to another event will give |
| you the correct offset between them, but comparing them to the current time |
| inside the extension (via <code>(new Date()).getTime()</code>, for instance) |
| might give unexpected results. |
| </p> |
| |
| <h3 id="error_handling">Error handling</h3> |
| <p> |
| If you try to register an event with invalid arguments, then a JavaScript error |
| will be thrown, and the event handler will not be registered. |
| |
| If an error is thrown while an event is handled, or if an event handler returns |
| an invalid blocking response, an error message is logged to your extension's |
| console and the handler is ignored for that request. |
| </p> |
| |
| <h2 id="examples">Examples</h2> |
| |
| <p>The following example illustrates how to block all requests to |
| <code>www.evil.com</code>:</p> |
| <pre> |
| chrome.webRequest.onBeforeRequest.addListener( |
| function(details) { |
| return {cancel: details.url.indexOf("://www.evil.com/") != -1}; |
| }, |
| {urls: ["<all_urls>"]}, |
| ["blocking"]); |
| </pre> |
| |
| <p>As this function uses a blocking event handler, it requires the "webRequest" |
| as well as the "webRequestBlocking" permission in the manifest file.</p> |
| |
| <p>The following example achieves the same goal in a more efficient way because |
| requests that are not targeted to <code>www.evil.com</code> do not need to be |
| passed to the extension:</p> |
| <pre> |
| chrome.webRequest.onBeforeRequest.addListener( |
| function(details) { return {cancel: true}; }, |
| {urls: ["*://www.evil.com/*"]}, |
| ["blocking"]); |
| </pre> |
| |
| <p>The following example illustrates how to delete the User-Agent header from |
| all requests:</p> |
| <pre> |
| chrome.webRequest.onBeforeSendHeaders.addListener( |
| function(details) { |
| for (var i = 0; i < details.requestHeaders.length; ++i) { |
| if (details.requestHeaders[i].name === 'User-Agent') { |
| details.requestHeaders.splice(i, 1); |
| break; |
| } |
| } |
| return {requestHeaders: details.requestHeaders}; |
| }, |
| {urls: ["<all_urls>"]}, |
| ["blocking", "requestHeaders"]); |
| </pre> |
| |
| <p> For more example code, see the <a href="samples#search:webrequest">web request |
| samples</a>.</p> |