Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Is it possible to run puppeteer on electron window? #4655

Closed
s0thl opened this issue Jul 2, 2019 · 21 comments
Closed

Is it possible to run puppeteer on electron window? #4655

s0thl opened this issue Jul 2, 2019 · 21 comments

Comments

@s0thl
Copy link

s0thl commented Jul 2, 2019

In nightmare.js, there is a possibility to take advantage of the electron window. That doesn't require us to use external chromium nor google chrome executables, because chromium is already bundled into electron.

So, can I take an advantage of that? Been slightly looking through docs and found out that puppeteer always requires to specify the chromium executable path to be used and there seem to be no way to overcome this and work nicely within electron process.

Regards

@jbures
Copy link

jbures commented Jul 5, 2019

If you want to run puppeteer on an already running chromium environment, there's a workaround somewhere that requires you to download a separate chromium instance and include it in the window... which i don't recommend cuz it's heavy af...
I recommend you setup a nodejs server that only runs puppeteer and you can communicate with using endpoints.

I'm currently running electron with reactjs on the frontend, calling endpoints on nodejs that runs puppeteer... i used the create-react-app to setup like 95% of the stuff automatically

@s0thl
Copy link
Author

s0thl commented Jul 5, 2019

Meanwhile I was digging a bit and actually found a way to attach puppeteer to electron instance however, it doesn't seem like this solution is still working, due to the electron not supporting the DevTools protocols which is mentioned in several issues like electron/electron#17776, #3793 and acknowledged in #4283
Thats why I had to use other solutions available around like nightmare.js.

@AnthoniG
Copy link

AnthoniG commented Jul 15, 2019

I've found a way around this and feel really silly that I did not see if before.
To cut a long story short, YES you can use puppeteer WITH electron.

In your JavaScript file to boot electron up, you use puppeteer inside there.
I am using Electron IPC and that calls into the JavaScript boot file and then I use puppeteer from there.
Works like a charm and no need to go hacking or changing anything

@WilliamChiu
Copy link

@AnthoniG If you have the time, would you be able to include a code snippet? I am having trouble with this same task right now

@AnthoniG
Copy link

AnthoniG commented Jul 16, 2019

@WilliamChiu
I was going to try and put up some snippets but was proving to be more work.
I will create a demo project showing it and then I will upload to github and share the link.

Here is the link. It's not fully fleshed out as it's all I had time for. However the basics are there.

It uses Typescript and I use Yarn rather than npm (hence yarn.lock)
It also presumes that you know how to use Electron's IPCMain and IPCRenderer as that is the only way to get puppeteer working without any hacks

Let me know if you have any problems or questions :)
Just add them as issues on the project itself, this way it keeps this clean 😀

@WilliamChiu
Copy link

Thank you! This was very helpful

@TrevorSundberg
Copy link

TrevorSundberg commented Aug 8, 2019

I wrote a small library to take care of this for my own projects:
https://www.npmjs.com/package/puppeteer-in-electron

It uses the above webSocketDebuggerUrl approach. This does work in the latest version of puppeteer and electron. Disclaimer, the whole library needs a lot of testing.

The other thing I spent a long time trying to solve was how to associate an electron BrowserWindow with a puppeteer Page. I ended up writing a routine that injects JavaScript into the BrowserWindow and searches for that specific Page in puppeteer.

I would note that there are a few limitations in puppeteer, for example you cannot intercept requests due to electron not supporting the network service.

@thenat97
Copy link

thenat97 commented Nov 27, 2019

Hello, im trying to make puppeteer run with the instance of chromium from electron, my code is based from @AnthoniG but i keep getting errors, could you guys help me?
Here is my github repository of this tiny integration

https://github.com/thenat97/electron-puppeteer

@AnthoniG
Copy link

Hello, im trying to make puppeteer run with the instance of chromium from electron, my code is based from @AnthoniG but i keep getting errors, could you guys help me?
Here is my github repository of this tiny integration

https://github.com/thenat97/electron-puppeteer
Hi, from the small tests that I have done:- it's saying that it cannot find puppeteer in puppeterTest
It looks like you are mixing import styles. This is not the place for this and I will open an issue on your repo and we can discuss it there 😄

@JustinELRoberts
Copy link

@TrevorSundberg Would you mind adding a code snippet showing how you were able to render a Puppeteer Page in an ElectronJS BrowserWindow? I'm not able to recreate it.

@TrevorSundberg
Copy link

@JustinELRoberts I'm not sure I understand what you mean by render? Basically once you connect puppeteer to electron, puppeteer can control all the pages (including browser windows). The only problem is that puppeteer identifies everything using target-ids, whereas the BrowserWindow does not expose these target-ids so I had to come up with a way to associate these two together. I did this by looping over all the pages in puppeteer, and setting some Javascript on the BrowserWindow so that I could find the right one:

https://github.com/TrevorSundberg/puppeteer-in-electron/blob/d1794c257daa7b585f8f397352c8521f5ebd53c5/index.ts#L62

Does this answer your question? If not feel free to elaborate and I'll try and help

@JustinELRoberts
Copy link

JustinELRoberts commented Jan 4, 2020

@TrevorSundberg Sorry I'm finding it difficult to word exactly what I'm trying to do. From my understanding, your library allows us to use Puppeteer to control Electron BrowserWindows. In my case I would like to use Puppeteer to open a new instance of Chromium, but have it display inside a BrowserWindow rather than inside of a new Chromium window. The reason I want to do this the way I'm mentioning rather than simply use a BrowserView or your library is that if I run this test with a BrowserView, it fails because a it is missing the window.chrome object. However, Chromium passes with flying colors.

I specifically @'ed you because I thought that's what you were saying you did in the second to last paragraph of your this message.

@TrevorSundberg
Copy link

I see, I'm not sure that I know how to achieve that. Provided my understanding of everything is correct*, electron is running it's own compiled version of Chromium, which means you can't just have puppeteer run a full blown instance of real Chromium and have it somehow link into electron; different processes, different binaries, etc. I haven't used electron extensively, but there might be a way to expose window.chrome through some call or to emulate it to make it as close to a real browser as possible. Although I imagine if your BrowserView is getting fingerprinted there's probably a large amount of things you'd need to expose or mimic to pass bot tests :/

The thing I was talking about in that paragraph, and in general with what I wrote, was that since electron was still a build of Chromium, it still happens to include the Chrome Devtools Protocol (a websocket protocol to control Chrome). Puppeteer was built around this, so through some hacky process I was able to expose the protocol in electron apps and connect puppeteer to it. This does not however create a real Chromium instance at all, it merely just controls electron with limitations, since again it's a fork of Chromium with things removed, such as your finding with window.chrome and many other things.

@TrevorSundberg
Copy link

The only other idea I can think of is that you do some sort of remoting where you run a full non-headless version of chromium but you either hide it and broadcast the screen, or do something very hacky where you place or parent the window to the electron window.

@JustinELRoberts
Copy link

Sorry to keep bothering you but could you please elaborate a bit more on how I could hack this together? My current solution is already running a non-headless version of Chromium through puppeteer so that bit isn't much of an issue. I just wanted to make these Chromium instances child windows of my BrowserWindow.

@blohamen
Copy link

blohamen commented Feb 27, 2020

I wrote a small library to take care of this for my own projects:
https://www.npmjs.com/package/puppeteer-in-electron

It uses the above webSocketDebuggerUrl approach. This does work in the latest version of puppeteer and electron. Disclaimer, the whole library needs a lot of testing.

The other thing I spent a long time trying to solve was how to associate an electron BrowserWindow with a puppeteer Page. I ended up writing a routine that injects JavaScript into the BrowserWindow and searches for that specific Page in puppeteer.

I would note that there are a few limitations in puppeteer, for example you cannot intercept requests due to electron not supporting the network service.

About intercepting requests. Any workarounds on how we can deal with it? The problem is when you try to respond on intercepted request puppeteer thinks that request finished but in chrome dev tools I can see that something strange happened with the request: status finished and I can see the response but I can't set up headers and status to 200. And also response not appeared in javascript code.

await chartPage.on('request', (req) => {
    if (req.url().includes('TracsProxy')) {
      console.log(req);
      req.respond({
        status: 200,
        contentType: 'application/json',
        body: JSON.stringify(tracsProxyMock),
      });
    } else {
      req.continue();
    }
  });

@TrevorSundberg
Copy link

@blohamen
I have to look into it more, but I saw this issue over on electron: electron/electron#15791

It's marked as closed so I'll have to investigate, not sure if there's another good workaround but let me know if you find one.

@stale
Copy link

stale bot commented Jun 26, 2022

We're marking this issue as unconfirmed because it has not had recent activity and we weren't able to confirm it yet. It will be closed if no further activity occurs within the next 30 days.

@stale stale bot added the unconfirmed label Jun 26, 2022
@stale
Copy link

stale bot commented Jul 26, 2022

We are closing this issue. If the issue still persists in the latest version of Puppeteer, please reopen the issue and update the description. We will try our best to accomodate it!

@stale stale bot closed this as completed Jul 26, 2022
@hayzedDev
Copy link

Hello, im trying to make puppeteer run with the instance of chromium from electron, my code is based from @AnthoniG but i keep getting errors, could you guys help me?
Here is my github repository of this tiny integration
https://github.com/thenat97/electron-puppeteer
Hi, from the small tests that I have done:- it's saying that it cannot find puppeteer in puppeterTest
It looks like you are mixing import styles. This is not the place for this and I will open an issue on your repo and we can discuss it there 😄

Has anyone tried this and it worked?

@AnthoniG
Copy link

@hayzedDev What's not working for you?

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

No branches or pull requests

9 participants