Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?
Two way iframe communication- Check out working example here: http://pbojinov.github.io/iframe-communication/

Two way iframe communication

The main difference between the two pages is the method of sending messages. Recieving messages is the same in both.

Parent

Send messages to iframe using iframeEl.contentWindow.postMessage Recieve messages using window.addEventListener('message')

iframe

Send messages to parent window using window.parent.postMessage Recieve messages using window.addEventListener('message')

Live Example

http://pbojinov.github.io/iframe-communication/

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>iframe Window</title>
<style>
body {
background-color: #D53C2F;
color: white;
}
</style>
</head>
<body>
<h1>Hello there, i'm an iframe</h1>
<p>Send Message: <button id="message_button">Hi parent</button></p>
<p>Got Message:</p>
<div id="results"></div>
<script>
// addEventListener support for IE8
function bindEvent(element, eventName, eventHandler) {
if (element.addEventListener) {
element.addEventListener(eventName, eventHandler, false);
} else if (element.attachEvent) {
element.attachEvent('on' + eventName, eventHandler);
}
}
// Send a message to the parent
var sendMessage = function (msg) {
// Make sure you are sending a string, and to stringify JSON
window.parent.postMessage(msg, '*');
};
var results = document.getElementById('results'),
messageButton = document.getElementById('message_button');
// Listen to messages from parent window
bindEvent(window, 'message', function (e) {
results.innerHTML = e.data;
});
// Send random message data on every button click
bindEvent(messageButton, 'click', function (e) {
var random = Math.random();
sendMessage('' + random);
});
</script>
</body>
</html>
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>Parent Window</title>
</head>
<body>
<h1>Parent Window</h1>
<p>Send Message: <button id="message_button">Hi there iframe</button></p>
<p>Got Message:</p>
<div id="results"></div>
<br/>
<script>
// addEventListener support for IE8
function bindEvent(element, eventName, eventHandler) {
if (element.addEventListener){
element.addEventListener(eventName, eventHandler, false);
} else if (element.attachEvent) {
element.attachEvent('on' + eventName, eventHandler);
}
}
var iframeSource = 'https://gist.github.com/pbojinov/8965299/raw/fadf2c4058b6481646e7244994c1890f2ad81b60/iframe.html';
// Create the iframe
var iframe = document.createElement('iframe');
iframe.setAttribute('src', iframeSource);
iframe.setAttribute('id', 'the_iframe');
iframe.style.width = 450 + 'px';
iframe.style.height = 200 + 'px';
document.body.appendChild(iframe);
// Send a message to the child iframe
var iframeEl = document.getElementById('the_iframe'),
messageButton = document.getElementById('message_button'),
results = document.getElementById('results');
// Send a message to the child iframe
var sendMessage = function(msg) {
// Make sure you are sending a string, and to stringify JSON
iframeEl.contentWindow.postMessage(msg, '*');
};
// Send random messge data on every button click
bindEvent(messageButton, 'click', function (e) {
var random = Math.random();
sendMessage('' + random);
});
// Listen to message from child window
bindEvent(window, 'message', function (e) {
results.innerHTML = e.data;
});
</script>
</body>
</html>
@iinviisiible
Copy link

Thanks for this great live example.
As a security guy, I would add that the message part should be escaped/sanitized (ex: json data should be JSON.parsed) before it's sent to output. also, the origin should be specified by the sender to not disclose any sensitive data to third-party domains and it should be verified by the receiver (event handler) to accept msgs from trusted domains only.

example

@jessemoon0
Copy link

Amazing Gist, thank you!

@laurent-d
Copy link

Thanks a lot for this !!

@jaimecalvo81
Copy link

Awesome example, thanks a lot

@Kanika1994
Copy link

Thanks !
Its very useful ..

@sebas932
Copy link

Great! was very useful for me.

@SokolskyNikita
Copy link

I've created a cross-domain example based on @pbojinov's great demo to show that this also works for cross domain iframes.

@kanachrisi
Copy link

Thanks a lot my friend!!

@dorelljames
Copy link

Thanks, man. Huge help with what I'm doing right now. Daamn works! 😊

@plann9
Copy link

plann9 commented Aug 24, 2019

Works great with a div or textarea as the receiving element but it won't pass the data to a text input box. Can you help?
ex: <input type="text" id="results"> does NOT work
ex: <div id="results"> does work

@lucas1
Copy link

lucas1 commented Sep 7, 2019

Thanks :)

@codebyarbaz
Copy link

Thanks man..!

@gjrmacedo
Copy link

Thank you!

@camjcorley
Copy link

Just dog-piling on top of all these thankful people to say this was very helpful for me as well. Thank you for sharing!

@justenh
Copy link

justenh commented Dec 5, 2019

Gonna leave a quick note of appreciate here as well. Thanks!

@Christopher-Hayes
Copy link

Helped me figure out why my code wasn't working, thanks!

@ChandanaRDeshmukh96
Copy link

I am trying this in angular. I am unable to get the iframe elem. Can anyone help?

@Christopher-Hayes
Copy link

Christopher-Hayes commented Mar 6, 2020

@ChandranaRDeshmukh96 Angular separates components in a way that makes it a difficult for them to access each other. Something like document.querySelector('#iframe-id') should still work though. Otherwise, you may have to make a service to give yourself access to that iframe element.

@leotengfei
Copy link

Thank you,very useful!

@justlester
Copy link

Thank you this helps me a lot! Just asking if is it possible to emit an event in all frames in a nested iframe?

@mrvisser
Copy link

@justlester you'll probably need to have the iframe at nesting level 1, propagate it to iframe at nesting level 2, and so on.

FWIW, I've created a library protoframe that adds a type wrapper around your iframe messaging protocol and has some helper functions to bind the listeners to the right window and establish "connection": https://github.com/mrvisser/protoframe

@greybax
Copy link

greybax commented Sep 8, 2020

great example! it helps me a lot while I've worked on VSC extension. I've described my process in my blog post here https://alfilatov.com/posts/how-to-pass-data-between-iframe-and-parent-window/

@iKlsR
Copy link

iKlsR commented Jan 25, 2021

Thanks! I can use this cleanly in vue embedded via iframe.

@Ranjinisudha
Copy link

how to check parent location path in iframe using postmessage

@FossPrime
Copy link

FossPrime commented Jun 24, 2021

This does not work when the iFrame domain is not the same as the parent.

The general behavior across browsers for cross origin (root domain) iFrames seems to be:

  • iFrame to TopWindow messages ALWAYS work under all circumstances, but the iFrame may have no easy way of knowing the message was received.
  • Messages will work from First Party TopWindow to Third Party domain iFrame
  • Service workers on third party domain iFrames are restricted on Chrome Incognito
    • Don't use service workers for Critical work, use Web Workers directly
  • Third Party domains cannot use ANY local storage API... no exceptions.
    • The only work reasonable work-around is to use a messaging gateway server that Top and Third Party can agree on ahead of time
    • The other option is to exploit Shared Workers and iFrames. third.com/iframe2?payload=[base64] would be loaded on iFrame 2 whenever iFrame 1 needs to receive a response or a message from TopWindow. iFrame2 would then broadcast a window message to all shared worker clients with the payload.

One way to demo this with free services is to use a mix of code sandbox, runkit and glitch... the latter two don't require accounts to use real containers

@ilyalazarev31
Copy link

Many thanks to me this decision saved the nervous system!

@Natanhel
Copy link

Natanhel commented Oct 4, 2021

Does this work on multiple iframes?

@xyal-343448187
Copy link

it's very helpful, thanks.

@Eric-yyy
Copy link

helpful, thanks!

@Reydson
Copy link

Reydson commented Apr 20, 2022

Thank you!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment