Skip to content
Foxipa

Suggest an edit

Tell us what should be corrected, clarified, or improved. Submission will be connected to Foxipa’s contribution service later.

No information is sent anywhere yet. Your suggestion is only prepared in your browser.

Learning

3.1 Payloads: the BodyInit union and the Content-Type map

Every type sendBeacon's data parameter accepts, the Web IDL stringify truth for odd values, and the fixed Content-Type mapping observed live through Request.

Levels: Beginner ~14 min read

Basic

The second argument of sendBeacon accepts the Fetch standard's BodyInit union — the same type that fetch() and Request accept for bodies. Flattened, the members are: ReadableStream, Blob, BufferSource (an ArrayBuffer or any typed-array view), FormData, URLSearchParams, plain strings — or null. Note that URLSearchParams is a first-class member: tutorials claiming sendBeacon cannot take it contradict the official IDL, and the example below constructs one for real.

The stringify truth

What happens to values that are none of those — a number, a boolean, a plain object? Web IDL union conversion has a string catch-all: after every interface member fails to match, a value falls through to the USVString member and is stringified. sendBeacon(url, 42) ships the two-character body "42". sendBeacon(url, {a: 1}) ships the string "[object Object]" — silently, with true returned, because the call is type-valid. Nothing here throws; the platform's contract is conversion, not validation.

You can watch this happen rather than take it on faith. A Request applies the very same union conversion and body extraction as sendBeacon does, and it lets you read the result back — so the runnable example below hands Request the odd values and prints the exact body and Content-Type the platform derived from each:

Interactive Runnable example
Edit

Ready to run.

The lesson hiding in that output is the single most common real-world bug with this API: a plain object is not JSON. If your collector parses bodies as JSON, sendBeacon(url, obj) delivers the unparseable string "[object Object]" with a 200-level queueing result on your side of the fence. Stringify before you send — the example's last line shows the correct form.

One data type, one Content-Type

You never set a Content-Type on a beacon; the extraction algorithm derives it from the data, and the derived value decides the request's CORS mode — the subject of the next page. The mapping is fixed:

The extraction algorithm's fixed mapping (Fetch standard, body extraction).

Data argument

Derived Content-Type

CORS mode

USVString

text/plain;charset=UTF-8

no-cors

URLSearchParams

application/x-www-form-urlencoded;charset=UTF-8

no-cors

FormData

multipart/form-data; boundary=…

no-cors

Blob

the Blob's own type, or no header if empty

depends on the type

BufferSource

no Content-Type header at all

no-cors

null / omitted

no body, no header

no-cors

ReadableStream

never happens — TypeError (keepalive)

—

The three form-family defaults are the quiet heroes of cross-origin beacons: all three are CORS-safelisted Content-Types, so those requests stay in no-cors mode and need no CORS setup whatsoever on the server. A Blob typed application/json breaks that streak — the next page shows why that single header value restructures the entire request.

Interactive Runnable example
Edit

Ready to run.

Quick check

Your collector expects JSON. Which call actually ships JSON?

navigator.sendBeacon('/api/collect', );

Key takeaways

  • data accepts the full BodyInit union — including URLSearchParams, which some tutorials wrongly deny.
  • Odd values do not throw; Web IDL stringifies them. {a: 1} ships as "[object Object]".
  • Always JSON.stringify() objects before sending — the platform will not do it for you.
  • The Content-Type is derived from the data: string → text/plain;charset=UTF-8, form → form encodings, BufferSource → none.
  • The derived Content-Type decides no-cors versus cors mode — the mechanism the next page dissects.
Was this page helpful?

Mark this learning resource complete to track your learning progress.