This specification defines an interface that web developers can use to schedule asynchronous and non-blocking delivery of data that minimizes resource contention with other time-critical operations, while ensuring that such requests are still processed and delivered to destination.
Web applications often need to issue requests that report events, state updates, and analytics to one or more servers. Such requests typically do not require response processing on the client (e.g. result in 204, or 200 HTTP response codes with an empty response body), and should not compete for network and compute resources with other high priority operations such as fetching critical resources, reacting to input, running animations, and so on. However, such one-way requests (beacons), are also responsible for delivering critical application and measurement data, forcing developers to use costly methods to ensure their delivery:
The mismatch between above delivery and processing requirements leaves most developers with a tough choice and widespread adoption of blocking techniques that hurt the user experience. This specification defines an interface that web developers can use to schedule asynchronous and non-blocking delivery of data that minimizes resource contention with other time-critical operations, while ensuring that such requests are still processed and delivered to destination:
The following example shows use of the sendBeacon
method to
deliver event, click, and analytics data:
<html> <script> // emit non-blocking beacon to record client-side event function reportEvent(event) { var data = JSON.stringify({ event: event, time: performance.now() }); navigator.sendBeacon('/collector', data); } // emit non-blocking beacon with session analytics as the page // transitions to background state (Page Visibility API) document.addEventListener('visibilitychange', function() { if (document.visiblityState === 'hidden') { var sessionData = buildSessionReport(); navigator.sendBeacon('/collector', sessionData); } }); </script> <body> <a href='http://www.w3.org/' onclick='reportEvent(this)'> <button onclick="reportEvent('some event')">Click me</button> </body> </html>
Above example uses visibilitychange
event
defined in [[PAGE-VISIBILITY]] to trigger delivery of session data. This
event is the only event that is guaranteed to fire on mobile devices when
the page transitions to background state (e.g. when user switches to a
different application, goes to homescreen, etc), or is being unloaded.
Developers should avoid relying on unload
event because it
will not fire whenever a page in background state (i.e.
visiblityState
equal to hidden
) and the process
is terminated by the mobile OS.
The requests initiated via the sendBeacon
method do not
block or compete with time-critical work, may be prioritized by the user
agent to improve network efficiency, and eliminate the need to use blocking
operations to ensure delivery of beacon data.
What sendBeacon
does not do and is not intended to
solve:
sendBeacon
method does not provide special handling
for offline storage or delivery. A beacon request is like any other
request and may be combined with [[SERVICE-WORKERS]] to provide offline
functionality where necessary.sendBeacon
method is not intended to provide
background synchronization or transfer capabilities. The user agent is
allowed to restrict the maximum accepted payload size to ensure that
beacon requests are able to complete quickly and in a timely manner.sendBeacon
method does not provide ability to customize the request method, provide custom request headers, or change other processing properties of the request and response. Applications that require non-default settings for such requests should use the [[FETCH]] API with keepalive flag set to true
.All diagrams, examples, and notes in this specification are non-normative, as are all sections explicitly marked non-normative. Everything else in this specification is normative.
The key words "MUST", "MUST NOT", "REQUIRED", "SHOULD", "SHOULD NOT", "RECOMMENDED", "MAY", and "OPTIONAL" in the normative parts of this document are to be interpreted as described in [[!RFC2119]]. For readability, these words do not appear in all uppercase letters in this specification.
Requirements phrased in the imperative as part of algorithms (such as "strip any leading space characters" or "return false and abort these steps") are to be interpreted with the meaning of the key word ("must", "should", "may", etc) used in introducing the algorithm.
Some conformance requirements are phrased as requirements on attributes, methods or objects. Such requirements are to be interpreted as requirements on the user agent.
Conformance requirements phrased as algorithms or specific steps may be implemented in any manner, so long as the end result is equivalent. (In particular, the algorithms defined in this specification are intended to be easy to follow, and not intended to be performant.)
The following terms are defined in the DOM specification: [[!DOM]]
The following terms are defined in the HTML specification: [[!HTML5]]
The following terms are defined in the HTML specification: [[!FETCH]]
Origin
header flagThe following terms are defined in the File API specification: [[!FILEAPI]]
The following terms are defined in the Typed Array specification: [[!TYPEDARRAY]]
ArrayBufferView
interfaceArrayBuffer
interfaceThe following terms are defined in the URL specification: [[!URL]]
The IDL fragments in this specification must be interpreted as required for conforming IDL fragments, as described in the Web IDL specification [[!WebIDL]].
The following terms are defined in the Web IDL specification:
The following term is defined in the XMLHttpRequest specification: [[!XMLHttpRequest]]
FormData
interfacesendBeacon
Methodpartial interface Navigator { boolean sendBeacon(USVString url, optional BodyInit? data = null); };
The sendBeacon
method transmits data provided by the data
parameter to the URL provided by
the url
parameter:
data
size
to ensure that beacon requests are able to complete quickly and in a
timely manner.visiblityState
([[!PAGE-VISIBILITY]]) transitions to hidden
, and must
allow all such requests to run to completion without blocking other
time-critical and high-priority work.204 No Content
).url
The url
parameter indicates the URL where the data is
to be transmitted.
data
The data
parameter is the BodyInit data that is
to be transmitted.
The sendBeacon
method returns true if the user agent is able to successfully queue the
data for transfer. Otherwise it returns false.
If the user agent limits the amount of data that can be queued to be sent using this API and the size of data causes that limit to be exceeded, this method returns false. A return value of true implies the browser has queued the data for transfer. However, since the actual data transfer happens asynchronously, this method does not provide any information whether the data transfer has succeeded or not.
On calling the sendBeacon
method, the
following steps must be run:
Set base to the entry settings object's API base URL.
Set origin to the entry settings object's origin.
Set referrer to the entry settings object's' API referrer source's URL if entry settings object's API referrer source is a document, and entry settings object's API referrer source otherwise
Set parsedUrl to the result of the URL parser
steps with url
and base. If the algorithm
returns an error, or if parsedUrl's scheme is not
"http" or "https", throw a
"TypeError
" exception and terminate these
steps.
If data is not null and if the user agent limits the amount of data that can be queued to be sent using this API and the size of data causes that limit to be exceeded, terminate these steps and set the return value to false.
cors
".Content-Type
header,
set corsMode to "no-cors
".
Content-Type
header with value
mimeType to headerList.sendBeacon()
call, but continue to runs the following
steps. These steps may be run even after the document has
unloaded.Let req be a new request, initialized as follows:
POST
true
The sendBeacon
interface provides an asynchronous and non-blocking mechanism for delivery of data. This API can be used to:
The delivered data might contain potentially sensitive information, for example, data about a user's activity on a web page, to a server. While this can have privacy implications for the user, existing methods, such as scripted form-submit, image beacons, and XHR/fetch requests provide similar capabilities, but come with various and costly performance tradeoffs: the requests can be aborted by the user agent unless the developer blocks the user agent from processing other events (e.g. by invoking a synchronous request, or spinning in an empty loop), and the user agent is unable to prioritize and coalesce such requests to optimize use of system resources.
A request initiated by sendBeacon is subject to following properties:
application/x-www-form-urlencoded
, multipart/form-data
, or text/plain
, then the request is a simple request that does not require an additional CORS-preflight; same as scripted form-post or XHR/fetch.Blob
and the resulting Content-Type
is not a simple header, then a CORS preflight is made and the server needs to first allow such requests by returning the appropriate set of CORS headers (Access-Control-Allow-Credentials
, Access-Control-Allow-Origin
, Access-Control-Allow-Headers
); same as XHR/fetch.As such, from the security perspective, the Beacon API is subject to all the same security policies as the current methods in use by developers. Similarly, from the privacy perspective, the resulting requests are initiated immediately when the API is called, or upon a page visibility change, which restricts the exposed information (e.g. user's IP address) to existing lifecycle events accessible to the developers. However, user agents might consider alternative methods to surface such requests to provide transparency to users.
Compared to the alternatives, the sendBeacon does apply two restrictions: there is no callback method, and the payload size can be restricted by the user agent. Otherwise, the sendBeacon API is not subject to any additional restrictions. The user agent ought not skip or throttle processing of sendBeacon calls, as they can contain critical application state, events, and analytics data. Similarly, the user agent ought not disable sendBeacon when in "private browsing" or equivalent mode, both to avoid breaking the application and to avoid leaking that the user is in such mode.
Thanks to Alois Reitbauer, Arvind Jain, Anne van Kesteren, Boris Zbarsky, Chase Douglas, Daniel Austin, Jatinder Mann, James Simonsen, Jason Weber, Jonas Sicking, Nick Doty, Philippe Le Hegaret, Todd Reifsteck, Tony Gentilcore, William Chan, and Yoav Weiss for their contributions to this work.