![]() |
When developing modern web applications, it often happens that you need to make windows, iframes or web workers communicate with each other.
In these cases, the postMessage
method proves to be a fundamental tool. In this article we will see what postMessage
is, what it is used for and how to use it, with practical examples.
What is postMessage
?
postMessage
is a method provided by the window
and worker
objects in JavaScript, which allows cross-origin communication, such as:
- between a main window and an iframe;
- between two open windows or tabs;
- between a web page and a Web Worker.
What is it for?
It is used to send data from one context to another securely, even if they come from different sources. It is useful when:
- you embed widgets from other sites (e.g. a YouTube iframe);
- you use Web Workers to perform heavy operations in the background;
- you open popup windows or communicate different tabs of the same application.
How to use it: the syntax
window.postMessage(message, targetOrigin, [transfer]);
Parameters:
- message: the data to send (can be a string, object, array, etc.).
- targetOrigin: the origin of the recipient (eg:
'https://example.com'
or'*'
). - transfer (optional): transferable objects (like ArrayBuffer).
Beware of targetOrigin
: it is mandatory
The second parameter of postMessage
, called targetOrigin, is mandatory according to the HTML specification. It is used to indicate the origin (protocol + domain + port) of the recipient who should receive the message.
Why is it important?
- Security: prevents data from being intercepted by unauthorized sources.
- Control: ensures that the message arrives only in the right window.
Examples:
// Correct
iframe.contentWindow.postMessage({ type: 'ping' }, 'https://example.com');
// Not recommended in production
iframe.contentWindow.postMessage({ type: 'ping' }, '*');
Note: Although in some JavaScript environments the parameter may seem optional, the HTML specification explicitly requires that you always provide targetOrigin
.
How to receive messages: window.addEventListener('message', ...)
To receive a message sent with postMessage, the receiver subscribes to the message event which provides the event
object:
window.addEventListener('message', function(event) {
console.log('Data:', event.data);
console.log('Origin:', event.origin);
console.log('Source:', event.source);
});
Explanation of fields:
event.data
: the received message.event.origin
: the origin of the sending window (e.g. https://example.com).event.source
: a reference to the window that sent the message.
(Simple) Examples of use
Communication between main window and iframe
<iframe id="myFrame" src="https://otheruser.com/frame.html"></iframe>
// Main window
const iframe = document.getElementById('myFrame');
iframe.contentWindow.postMessage({ type: 'GREETING', text: 'Hello iframe!' }, 'https://otheruser.com');
// In the iframe (frame.html)
window.addEventListener('message', function(event) {
if (event.origin !== 'https://yoursite.com') return;
console.log('Message received:', event.data);
});
Window Communication
// Open new window
const popup = window.open('https://example.com/popup.html');
// Send message after 1 second
setTimeout(() => {
popup.postMessage('Hello from the main window!', 'https://example.com');
}, 1000);
// Get response
window.addEventListener('message', (event) => {
console.log('Response from popup:', event.data);
});
๐ When postMessage
can save you in development
postMessage
can really save you from hours of frustration (or going crazy) in many scenarios of modern web development. It is one of the most underrated APIs, but extremely useful when you are dealing with multiple contexts or sandboxing. postMessage
becomes a lifeline:๐งฉ 1. Communication between iframe and main page
Problem: You have a widget (chat, login, payment, etc.) embedded in an <iframe>
, but you can't access its content directly (because it's on a different domain).
Solution with postMessage
:
-
The host page sends messages to the iframe to tell it what to do (ex: change theme).
-
The iframe sends messages to the page to notify it of events (ex: "user logged in").
✅ Avoid hacks like polling or illegal cross-origin login attempts.
๐ 2. Integration between microfrontends (different domains or teams)
Problem: You are working in a microfrontend architecture, where each section of the app is served by a different SPA (and maybe different teams).
Solution with postMessage
:
-
Micro-apps communicate events between each other (e.g. “user selected”, “global logout”).
-
Avoid tight coupling between modules.
✅ Isolation + coordination = fewer bugs and more autonomous teams.
๐ 3. Authentication via popup (OAuth, external login)
Problem: You use a popup authentication flow (e.g. Google Sign-In, Facebook Login) and want to receive the token on the main page.
Solution with postMessage
:
-
The popup, once authenticated, sends the token via
postMessage
to the main window.
✅ Avoided: bad redirects, use of tokenized URLs, shared localStorage.
๐ฆ 4. Embedded data editors or third-party tools
Problem: You want to integrate an interactive tool (e.g. text editor, graphics, configurators) into your site, but it is hosted on an external domain.
Solution with postMessage
:
-
The tool sends events such as "content updated", "error", "save successful".
-
You can respond with commands, settings or content.
✅ Fluid interaction even with external services.
๐งต 5. Synchronization between windows or tabs
Problem: You have your app open in multiple tabs or windows, and you want to keep them synchronized (logout, notifications, real-time changes).
Solution with postMessage
:
-
Windows send events to each other (via
window.opener
,window.parent
, orBroadcastChannel
as a modern alternative).
✅ Consistent, centralized user experience.
⚙️ 6. Web Worker and performance
Problem: You have to do heavy operations (calculations, JSON parsing, transformations) but you don't want to block the main thread.
Solution with postMessage
:
-
Send data to Web Worker → process → return result with
postMessage
.
✅ Fluid UI even with complex operations.
๐ฎ Advanced validation of the received message
When receiving messages from other windows, iframes or Web Workers via postMessage
, you should never blindly trust the received content.
Even if a message comes from a seemingly valid source, it could have been manipulated or sent by mistake.
For reasons of security, maintainability and code robustness, it is important to implement thorough validation. Here are some basic tips:
๐ 1. Check the origin (origin)
Check that the message comes from an expected domain. Never use '*' in production environments.
const trustedOrigin = 'https://example.com';
if (event.origin !== trustedOrigin) return; // Discard unauthorized messages
๐งฑ 2. Check the message structure
The message can be any type. Always check that it is a valid object and has the expected properties.
const msg = event.data;
if (typeof msg === 'object' && msg !== null && 'type' in msg) {
// Structurally valid message
}
✅ 3. Validation of expected values
Check that the field values are in the correct format:
if (msg.type === 'GREETING' && typeof msg.testo === 'string') {
console.log('Greeting received:', msg.testo);
}
๐งช 4. Advanced validation with libraries (optional)
For more complex messages, you can use validation libraries like zod
, joi
or ajv
. Example with zod:
import { z } from 'zod';
const MessageSchema = z.object({
type: z.literal('GREETING'),
text: z.string(),
});
const parsed = MessageSchema.safeParse(event.data);
if (parsed.success) {
console.log('Valid greeting:', parsed.data.text);
}
๐ซ 5. What to avoid
- Don't trust
event.data
a priori. - Don't ignore
event.origin
, not even during testing. - Don't take the message structure for granted.
- Don't expose sensitive data to unverified senders.
⚡Browser Compatibility
As for compatibility with the different browsers on the market today, fortunately postMessage
is widely supported:
- All major browsers (Chrome, Firefox, Safari, Edge, Opera) have supported it for a long time.
- It also works on mobile.
- For up-to-date details: caniuse.com/postMessage
⚙️ Use with Web Worker
postMessage
is the basis of how Web Workers work. Below is a simple example to pique your curiosity that can be satisfied by reading the article Web Worker in JavaScript: what they are, how to use them and why they are needed (and differences with Service Worker):
// In the main thread
const worker = new Worker('worker.js');
worker.postMessage('Perform a calculation');
// In the worker (worker.js)
onmessage = function(event) {
// Receive message
postMessage('Result ready');
};
✖️ Common mistakes to avoid
- Using
'*'
astargetOrigin
in production. - Not checking
event.origin
when receiving a message. - Forgetting that
postMessage
is asynchronous. - Expecting communication to work between
file://
files (need a local server to test).
⚽ Conclusion
postMessage
is a powerful tool for creating modular and communicating web applications. Its correct implementation allows you to keep execution contexts separate and improve code security and scalability.
postMessage
is a powerful ally when:
-
you have isolated but cooperating contexts (iframes, popups, microfrontends),
-
you work with different origins (cross-origin),
-
you want to maintain performance or security,
-
you want decoupling between components (communication without direct dependency).
Follow me #techelopment
Official site: www.techelopment.it
facebook: Techelopment
instagram: @techelopment
/>telegram: @techelopment_channel
whatsapp: Techelopment
youtube: @techelopment