W3C Candidate Recommendation Draft
Copyright © 2022 W3C® (MIT, ERCIM, Keio, Beihang). W3C liability, trademark and permissive document license rules apply.
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.
This section describes the status of this document at the time of its publication. A list of current W3C publications and the latest revision of this technical report can be found in the W3C technical reports index at https://www.w3.org/TR/.
This document was published by the Web Performance Working Group as a Candidate Recommendation Draft using the Recommendation track.
Publication as a Candidate Recommendation does not imply endorsement by W3C and its Members. A Candidate Recommendation Draft integrates changes from the previous Candidate Recommendation that the Working Group intends to include in a subsequent Candidate Recommendation Snapshot.
This is a draft document and may be updated, replaced or obsoleted by other documents at any time. It is inappropriate to cite this document as other than work in progress.
This document was produced by a group operating under the W3C Patent Policy. W3C maintains a public list of any patent disclosures made in connection with the deliverables of the group; that page also includes instructions for disclosing a patent. An individual who has actual knowledge of a patent which the individual believes contains Essential Claim(s) must disclose the information in accordance with section 6 of the W3C Patent Policy.
This document is governed by the 2 November 2021 W3C Process Document.
This section is non-normative.
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.visibilityState === '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-2] 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 is in a background state (i.e.
visibilityState
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 restricts 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 set to
true
.
As well as sections marked as non-normative, all authoring guidelines, diagrams, examples, and notes in this specification are non-normative. Everything else in this specification is normative.
The key words MAY, MUST, SHOULD, and SHOULD NOT in this document are to be interpreted as described in BCP 14 [RFC2119] [RFC8174] when, and only when, they appear in all capitals, as shown here.
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.)
WebIDL
The sendBeacon()
method transmits data provided by the
parameter to the URL provided by the data
url
parameter:
visibilityState
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
).
The url
parameter
indicates the URL where the data is to be transmitted.
The
parameter is the data
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.
The user agent imposes limits on the amount of data
that can be sent via this API: this helps ensure that such requests are
delivered successfully and with minimal impact on other user and
browser activity. If the amount of data to be queued exceeds
the user agent limit (as defined in HTTP-network-or-cache
fetch), 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 with url and
optional data, the following steps must be run:
Set base to this's relevant settings object's API base URL.
Set origin to this's relevant settings object's origin.
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
"
" exception and terminate these
steps.TypeError
no-cors
".If data is not null
:
false
and
terminate these steps.
Requests initiated via the Beacon API automatically set the keepalive flag, and developers can similarly set the same flag manually when using the Fetch API. All requests with this flag set share the same in-flight quota restrictions that is enforced within the Fetch API.
cors
".Content-Type
header, set corsMode to "no-cors
".
Content-Type
header with value
contentType to headerList.true
, return the
sendBeacon()
call, and continue to run the following steps in
parallel:
Let req be a new request, initialized as follows:
POST
true
beacon
"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:
Content-Type
is a CORS-safelisted request-header,
then the request mode is no-cors
—similar to an image beacon or
form-post respectively.
Access-Control-Allow-Credentials
,
Access-Control-Allow-Origin
,
Access-Control-Allow-Headers
.
As such, from the security perspective, the Beacon API is subject to 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()
API 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.