JavaScript Worker postMessage() Method

Beginner
5 min read
Updated: Nov 2026
5 examples
Method

Definition

worker.postMessage(message) sends data from the main thread to a dedicated Worker (MDN). The payload is copied with the structured clone algorithm and arrives as event.data on the worker’s message event.

Pass the required arguments shown below. Check return values and browser support before you rely on the result.

Syntax

Call worker.postMessage. Start with this line.

JavaScript
worker.postMessage(message[, transfer])
CallWhat it does
worker.postMessage(message[, transfer])Primary signature.
worker.postMessage(...)Call with the arguments your case needs.

Built into the browser. Call worker.postMessage(...) on a Worker — no import required.

Library declarations
JavaScript
worker.postMessage(message[, transfer])

Parameters

ParameterDescription
messageRequired. Value delivered as event.data
transferOptional. Move ownership of transferable objects

Return Value

Return ValueDescription
*undefined

JavaScript Examples

Example 1 — Send a String (Echo)

Post a string; the worker echoes it back.

JavaScript
const code = `self.onmessage = (e) => {
  self.postMessage("echo: " + e.data);
};`;
const url = URL.createObjectURL(
  new Blob([code], { type: "application/javascript" })
);
const worker = new Worker(url);

worker.onmessage = (e) => console.log(e.data);
worker.postMessage("hello");
// echo: hello
Try It Yourself

How It Works

  1. Build a blob worker. Tiny script with onmessage.
  2. Listen on the Worker. Ready for the reply.
  3. postMessage("hello"). Cloned into the worker as e.data.
  4. Worker posts back. Main logs echo: hello.

Example 2 — Array Payload (MDN-style)

One message can carry several values in an array.

JavaScript
const code = `self.onmessage = (e) => {
  const [a, b] = e.data;
  self.postMessage(Number(a) + Number(b));
};`;
const url = URL.createObjectURL(
  new Blob([code], { type: "application/javascript" })
);
const worker = new Worker(url);

worker.onmessage = (e) => console.log("sum =", e.data);
worker.postMessage([2, 3]);
// sum = 5
Try It Yourself

How It Works

  1. postMessage sends one value. Here that value is an array.
  2. Worker reads e.data[0] / [1]. Same idea as MDN’s inputs demo.
  3. Returns the sum with self.postMessage.
  4. Main prints sum = 5.

Example 3 — Object Payload

Named fields are often clearer than a bare array.

JavaScript
const code = `self.onmessage = (e) => {
  self.postMessage(e.data.x * e.data.y);
};`;
const url = URL.createObjectURL(
  new Blob([code], { type: "application/javascript" })
);
const worker = new Worker(url);

worker.onmessage = (e) => console.log(e.data);
worker.postMessage({ x: 4, y: 5 });
// 20
Try It Yourself

How It Works

  1. Send a plain object. Structured clone copies it.
  2. Worker reads named fields. e.data.x, e.data.y.
  3. Posts the product back to main.
  4. Prefer objects when field names help readability.

Example 4 — Transfer an ArrayBuffer

MDN transfer: ownership moves; sender sees byteLength === 0.

JavaScript
const code = `self.onmessage = (e) => {
  self.postMessage(e.data.byteLength);
};`;
const url = URL.createObjectURL(
  new Blob([code], { type: "application/javascript" })
);
const worker = new Worker(url);
const buf = new ArrayBuffer(8);

console.log("before", buf.byteLength); // 8
worker.onmessage = (e) => console.log("worker saw", e.data);
worker.postMessage(buf, [buf]);
console.log("after", buf.byteLength);  // 0
Try It Yourself

How It Works

  1. Create an ArrayBuffer. Length 8 on main.
  2. postMessage(buf, [buf]). Second arg lists transferables.
  3. Ownership moves. Main’s buffer is neutered (0).
  4. Worker still sees 8 — it now owns the buffer.

Example 5 — Mandatory Message (null)

MDN: if the data is unimportant, pass null or undefined explicitly.

JavaScript
const code = `self.onmessage = (e) => {
  self.postMessage(String(e.data));
};`;
const url = URL.createObjectURL(
  new Blob([code], { type: "application/javascript" })
);
const worker = new Worker(url);

worker.onmessage = (e) => console.log(e.data);
worker.postMessage(null);
// null
Try It Yourself

How It Works

  1. message is required. Do not call postMessage() with zero args.
  2. Pass null explicitly when you only need a ping / wake-up.
  3. Worker still gets a message event with e.data === null.
  4. Useful for signals where the payload itself does not matter.

Browser Support

Worker.postMessage() is Baseline Widely available (MDN: since July 2015). Available in Web Workers except Service Workers — not in Node.js, Bun, or Deno (use worker_threads there).

✓ Baseline · Widely available

Worker.postMessage()

Send structured-clone data to a dedicated worker. Optional transfer list for ArrayBuffers. Safe everyday Web Worker API.

100% Browser support
Google Chrome Supported · Desktop & Mobile
Full support
Mozilla Firefox Supported · Desktop & Mobile
Full support
Apple Safari Supported · macOS & iOS
Full support
Microsoft Edge Supported · Chromium
Full support
Internet Explorer No native support · Use a polyfill
Polyfill
Opera Supported · Modern versions
Full support
Samsung Internet Supported · Android
Full support
Android WebView Supported · Modern WebView
Full support
postMessage Excellent

Bottom line: Safe for production dedicated workers. See the MDN postMessage reference.

Frequently Asked Questions

It sends a message from the main thread to a dedicated Worker. The data is delivered in the message event’s data field inside the worker (via structured clone).
No. MDN marks Worker.postMessage() as Baseline Widely available (since July 2015). It is not Deprecated, Experimental, or Non-standard. It is available in Web Workers except Service Workers.
Almost any value the structured clone algorithm supports: strings, numbers, booleans, arrays, plain objects, Date, Map, Set, ArrayBuffer, and more—including objects with cyclical references. Functions and DOM nodes cannot be cloned.
postMessage sends one message payload. Put several values in an array or object, for example postMessage([a, b]) or postMessage({ a, b }).
An optional list of transferable objects (like ArrayBuffer) moves ownership to the worker. After transfer, the original buffer is neutered (often byteLength === 0) on the sending side.
No. It is mandatory. If you have nothing useful to send, pass null or undefined explicitly.

Next: terminate()

Learn how to immediately stop a dedicated worker from the main thread.

terminate tutorial →

About the author

Mari Selvan M P
Mari Selvan M P 🔗

Developer, cloud engineer, and technical writer

  • Experience 12 years building web and cloud systems
  • Focus Full Stack Development, AWS, and Developer Education

I write practical tutorials so students and working developers can learn by doing—from databases and APIs to deployment on AWS.

9 people found this page helpful