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>
@VImpe

This comment has been minimized.

Copy link

@VImpe VImpe commented Dec 20, 2017

It's very very helpful to me thank you very much

@druuu

This comment has been minimized.

Copy link

@druuu druuu commented Mar 1, 2018

simple & straight forward.

@terreng

This comment has been minimized.

Copy link

@terreng terreng commented Mar 7, 2018

Thank you! This is very useful.

@rahulkannan

This comment has been minimized.

Copy link

@rahulkannan rahulkannan commented Mar 15, 2018

thanks

@jorge-perez-anfix

This comment has been minimized.

Copy link

@jorge-perez-anfix jorge-perez-anfix commented Apr 13, 2018

Thank you very much for your contribution. It's very useful.

@spardue

This comment has been minimized.

Copy link

@spardue spardue commented May 3, 2018

Awesome man!!

@tuannat

This comment has been minimized.

Copy link

@tuannat tuannat commented May 8, 2018

Awesome, very helpful for me

@SteeveDroz

This comment has been minimized.

Copy link

@SteeveDroz SteeveDroz commented May 9, 2018

I knew it was possible, I didn't know it was that easy. Thanks!

@vipullimbachiya

This comment has been minimized.

Copy link

@vipullimbachiya vipullimbachiya commented May 30, 2018

Thanks for this!

@PATurmel

This comment has been minimized.

Copy link

@PATurmel PATurmel commented Jul 13, 2018

Thanks for this, you can probably leave out 'Make sure you are sending a string, and to stringify JSON' as I just sent an array to an iframe.

@dpaulflavius

This comment has been minimized.

Copy link

@dpaulflavius dpaulflavius commented Aug 17, 2018

Hi @pbojinov,

This is a very well explained and simple example of a communication between an iframe and some other page.

I would like to know if it's possible to send a function as a message in the iframe, so that the iframe can actually invoke that function (inside the iframe) that is sent from the parent.

@webdeveloperpr

This comment has been minimized.

Copy link

@webdeveloperpr webdeveloperpr commented Aug 20, 2018

very nice example!

@nest-aka-swan

This comment has been minimized.

Copy link

@nest-aka-swan nest-aka-swan commented Aug 23, 2018

You can also check event.origin for security as described on MDN
https://developer.mozilla.org/en-US/docs/Web/API/Window/postMessage#Security_concerns

@indie-rok

This comment has been minimized.

Copy link

@indie-rok indie-rok commented Aug 30, 2018

THANK YOU!!!

@Spaceman007

This comment has been minimized.

Copy link

@Spaceman007 Spaceman007 commented Sep 8, 2018

It's very helpful. Thank.

@radius

This comment has been minimized.

Copy link

@radius radius commented Oct 4, 2018

@PATurmel

Thanks for this, you can probably leave out 'Make sure you are sending a string, and to stringify JSON' as I just sent an array to an iframe.

Looks like the example is taking into account older browser versions (on IE and FF) that only supported strings for the message:
https://stackoverflow.com/questions/22205142/iframe-parent-postmessage-returns-string-instead-of-object-in-ie9

@devansvd

This comment has been minimized.

Copy link

@devansvd devansvd commented Oct 8, 2018

Nice. Have one suggestion though. I recommend not to use * instead use the protocol:domain:port you want to transfer.

For More Info: - https://developer.mozilla.org/en-US/docs/Web/API/Window/postMessage

parent to iframe - document.getElementById('iframeId').contentWindow.postMessage(msg, 'protocol:domain:port');
iframe to parent - window.parent.postMessage(msg, 'protocol:domain:port');

@temo-o

This comment has been minimized.

Copy link

@temo-o temo-o commented Oct 12, 2018

I tried many variations for this particular method to work but I always get data like this: 'setImmediate$0.4740642311118859$1'.
I copied this exact code but result is the same. It's a cross-domain Iframe of course.
Can you guys help?

@anasalzuvix

This comment has been minimized.

Copy link

@anasalzuvix anasalzuvix commented Oct 19, 2018

is this working in cross domain iframe?

@askprateek

This comment has been minimized.

Copy link

@askprateek askprateek commented Oct 29, 2018

Yes @AnaZu

@askprateek

This comment has been minimized.

Copy link

@askprateek askprateek commented Oct 29, 2018

@temo-o.
If you sending some specific message, you have handle it in if condition.

if (e.data === 'loginSuccessful') {
// Excute my code.
}
@ronandl

This comment has been minimized.

Copy link

@ronandl ronandl commented Nov 1, 2018

Hello,

Thanks for posting this, it's really helping me out of a bind! I'm using the above to communicate one way from my iFrame to my parent. It's working, however, before any message is sent, my <div = "results"> is displaying [object Object]. Wondering if there's anything I can do change [object Object] to another placeholder, like "OFF"?

I'm a bit of a noob when it comes to this, so any help is greatly appreciated.

Many thanks!

@Snesi

This comment has been minimized.

Copy link

@Snesi Snesi commented Nov 6, 2018

Excellent! Thank you!

@jdiegosierra

This comment has been minimized.

Copy link

@jdiegosierra jdiegosierra commented Jan 25, 2019

Thank you!

@Darshnik

This comment has been minimized.

Copy link

@Darshnik Darshnik commented Feb 14, 2019

This is really helpful!

@NhanNgo2306

This comment has been minimized.

Copy link

@NhanNgo2306 NhanNgo2306 commented Mar 5, 2019

Thank you, It's very helpful

@Andrewpravin

This comment has been minimized.

Copy link

@Andrewpravin Andrewpravin commented Mar 12, 2019

Hi,
i tried to run the same from my local server . while loading parent.html 'iframe.html' is not loading it is showing below error
"Refused to display 'https://gist.githubusercontent.com/pbojinov/8965299/raw/fadf2c4058b6481646e7244994c1890f2ad81b60/iframe.html' in a frame because it set 'X-Frame-Options' to 'deny'" can you please help me to sort out of this error

@pBread

This comment has been minimized.

Copy link

@pBread pBread commented Mar 15, 2019

Great solution

@mattharley

This comment has been minimized.

Copy link

@mattharley mattharley commented Mar 20, 2019

awesome cheers

@iinviisiible

This comment has been minimized.

Copy link

@iinviisiible iinviisiible commented Jun 8, 2019

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

This comment has been minimized.

Copy link

@jessemoon0 jessemoon0 commented Jun 25, 2019

Amazing Gist, thank you!

@laurent-d

This comment has been minimized.

Copy link

@laurent-d laurent-d commented Jul 1, 2019

Thanks a lot for this !!

@jaimecalvo81

This comment has been minimized.

Copy link

@jaimecalvo81 jaimecalvo81 commented Jul 26, 2019

Awesome example, thanks a lot

@Kanika1994

This comment has been minimized.

Copy link

@Kanika1994 Kanika1994 commented Aug 7, 2019

Thanks !
Its very useful ..

@sebas932

This comment has been minimized.

Copy link

@sebas932 sebas932 commented Aug 14, 2019

Great! was very useful for me.

@SokolskyNikita

This comment has been minimized.

Copy link

@SokolskyNikita SokolskyNikita commented Aug 15, 2019

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

@kanachrisi

This comment has been minimized.

Copy link

@kanachrisi kanachrisi commented Aug 20, 2019

Thanks a lot my friend!!

@dorelljames

This comment has been minimized.

Copy link

@dorelljames dorelljames commented Aug 22, 2019

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

@plann9

This comment has been minimized.

Copy link

@plann9 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

This comment has been minimized.

Copy link

@lucas1 lucas1 commented Sep 7, 2019

Thanks :)

@codebyarbaz

This comment has been minimized.

Copy link

@codebyarbaz codebyarbaz commented Sep 9, 2019

Thanks man..!

@gjrmacedo

This comment has been minimized.

Copy link

@gjrmacedo gjrmacedo commented Sep 16, 2019

Thank you!

@camjcorley

This comment has been minimized.

Copy link

@camjcorley camjcorley commented Oct 10, 2019

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

This comment has been minimized.

Copy link

@justenh justenh commented Dec 5, 2019

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

@Christopher-Hayes

This comment has been minimized.

Copy link

@Christopher-Hayes Christopher-Hayes commented Jan 7, 2020

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

@ChandanaRDeshmukh96

This comment has been minimized.

Copy link

@ChandanaRDeshmukh96 ChandanaRDeshmukh96 commented Mar 6, 2020

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

@Christopher-Hayes

This comment has been minimized.

Copy link

@Christopher-Hayes 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

This comment has been minimized.

Copy link

@leotengfei leotengfei commented Apr 15, 2020

Thank you,very useful!

@justlester

This comment has been minimized.

Copy link

@justlester justlester commented Jun 19, 2020

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

This comment has been minimized.

Copy link

@mrvisser mrvisser commented Jun 23, 2020

@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

This comment has been minimized.

Copy link

@greybax 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

This comment has been minimized.

Copy link

@iKlsR iKlsR commented Jan 25, 2021

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

@Ranjinisudha

This comment has been minimized.

Copy link

@Ranjinisudha Ranjinisudha commented Jun 24, 2021

how to check parent location path in iframe using postmessage

@rayfoss

This comment has been minimized.

Copy link

@rayfoss rayfoss 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

This comment has been minimized.

Copy link

@ilyalazarev31 ilyalazarev31 commented Jul 16, 2021

Many thanks to me this decision saved the nervous system!

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