puppeteer: Chrome memory leak

Tell us about your environment:

  • Puppeteer version: 2.1.1
  • Platform / OS version: Docker / node:12.16.1-alpine
  • URLs (if applicable): None
  • Node.js version: v12.16.1

What steps will reproduce the problem?

Process: /usr/lib/chromium/chrome --extra-plugin-dir=/usr/lib/nsbrowser/plugins …

The process memory usage above continues to increase.

Also, I’m using dumb-init

image

Sample Javascript Code

async run() {
  const browser = await puppeteer.launch({ args: ['--no-sandbox'] });
  while(true) {      
    const page = await browser.newPage();
    await page.setCacheEnabled(true);
    await page.close();
  }
  await browser.close();
}

About this issue

  • Original URL
  • State: closed
  • Created 4 years ago
  • Reactions: 56
  • Comments: 89 (1 by maintainers)

Most upvoted comments

@sdg9670 how can this be a memory leak? And, I assume doing in firefox will grow multiply. And, if this a chrome memory leak then how is this related to Puppeteer? Open a bug here and please read this

Same problem! I keep one tab open for let say 30 day, and the RAM utilisation keeps on growing from day 1 till my EC2 runs out of memory … This is some serious issue that’s not getting addressed due to sheer ignorance.

@ivictbor wdym? could you please provide any link to a code example? thank you in advance.

I’ve just wrote a detailed blog post about simple example with a fix for puppeteer RAM leak issue:

https://devforth.io/blog/how-to-fix-ram-leaking-libraries-like-pupeeteer-easily-universal-way-to-fix-ram-leaks-once-and-forever/

skill issue tbh

@gvanriper is it possible that using playwrights build of chromium with puppeteer may help with the memory leak?

I know it might be hard to accept that there might be such popular libraries and projects like chromium that leak, but I can share my background, I has been working with libs based on chromium for a long time. First one was CEF (chromium embedded framework). It was 8 years ago when I was working on user imitation project for random websites. I tried almoast all their bindings for python, .net, pure c++, after integration it worked great, but on long run I always faced RAM leaks, we investigated them with contributors in GH issues during weeks, with clear steps to reproduce, and every single one ended with a root cause in chromium, some of them even pointed to original chromium comunity which has tons of unfixed bugs. Developers throughput is smaller then number of issues created by variety of possible pages, tags, js features, and by popularity of project. So yep, from time to time we were able to find very stable version which works for most of pages without leaks, but not 100%: there are so many possibilities, because it runs vendor JS, and web itself has so much legacy-compatibilities and so on. Anyway, most likely you will not want to freeze one chromium version forever, you would loose more fixes and features. I would still recommend to invest time in understanding how to reorganize or unloop your task to be able to run any version of chrome / puppeteer, etc and release memory by yourself, just by exiting process

@CleisonArenhart I have the same issue, and also I thought that with browser.close() I would have solved the issue, but RAM keeps increasing. Not sure how to properly close it and free the RAM.

This is not official solution, but from my expirience puppeteer always was very leaky. I think there are no tests for leaks, also some memory issues might be there from Chromium itself.

So in all serious projects we always wrap it in a small nodejs script with simplest IPC or even CLI/file data pass and start it in new node process using ChildProcess. Then kill it ASAP(as early as task scope allows) and never reuse same instance again. Then it works perfectly and never leaks, and never leaves zombies / extra processes

@CleisonArenhart I have the same issue, and also I thought that with browser.close() I would have solved the issue, but RAM keeps increasing. Not sure how to properly close it and free the RAM.

Same problem 😢

Just an update that this issue was all but gone for me for a while, using 19.8.2 (and, from my package-lock.json:

                "puppeteer": {
                        "version": "19.8.2",
                        "resolved": "https://registry.npmjs.org/puppeteer/-/puppeteer-19.8.2.tgz",
                        "integrity": "sha512-LPdNVYMR6ddp4YS3GK1bqKsasCJj1aZjt9dNOKcnzKezuMoishlHY6bCnFLjTc34iqnGzIrJp07TQ9M+aML2+g==",
                        "requires": {
                                "@puppeteer/browsers": "0.3.1",
                                "cosmiconfig": "8.1.3",
                                "https-proxy-agent": "5.0.1",
                                "progress": "2.0.3",
                                "proxy-from-env": "1.1.0",
                                "puppeteer-core": "19.8.1"
                        }
                }

which is also using chrome/linux-1108766) and then I recently updated (npm update) and it came back with a vengence, no other changes on my end.

Hopefully this helps someone narrow down the problem.

I am not able to reproduce on the latest version

@OrKoN I was; in fact I came to update this thread because it had gone away on an older version and came back using latest. Please don’t close a major issue thread after not being able to reproduce it in a single test case, which, no offense, is impractical - no one is opening/closing the browser in a loop, while that might make sense for testing memory use in some cases, that’s not the issues here nor was that anything anyone suggested as a reproduction.

In my experience with these issues, as well, to comment on your question, I’ve seen both the Chrome|ium process or both that and the Node thread spawning Puppeteer increase in usage at various times. Most often though, it’s the parent node thread, this is what my code monitors for leaks and started getting notifications within 24h after upgrading as mentioned above (and threshold set at 2GB, so >2GB in <24h). If/when Chrome|ium is also leaking, it’s usually it’s parent process PID that Puppeteer returns that leaks, but I don’t monitor for this because if that happens, the Node thread is also leaking.

There should be little/no difference for the other user running in K8S either in most cases, I’m not running in K8S currently but haven’t observed any differences when doing so, a K8S pod is basically just a Docker container. I’m not sure if that user is fully monitoring all related threads or not when not using K8S as any K8S monitoring would generally show the usage of the entire pod, which would include all spawned processes/threads; that said, most people don’t do any threading in their Node application itself, which I often do, however I’ve only seen it manifest on the main/parent Node thread, which in my case is also the thread spawning/running Puppeteer (and the other threads are inconsequential to this issue) so it likely should’ve shown for them if monitoring the Node processes’ memory usage alone, unless they’re experiencing a different/similar issue.

Admittedly this is a very illusive issue; I can say that the above listed version is not affected by the issue but versions previous to it and newer are definitely affected.

Can we keep this thread open in hopes that it can be narrowed down eventually, especially now that I’ve been able to provide a pointer to a version free of the issue and confirmed it’s regressed since?

@ivictbor , This resolved our long long road of figuring out what the heck was causing our memory leak. Thank you for taking the time to write examples.

If anyone on here is trying to do HTML to PDF and need to return a buffer, I can provide a working example for that as well.

I am having the same issue. My app spawns multiple pages at once and then closes all of them but the memory usage keeps on increasing indefinitely.

Puppeteer: 13.7.0 Platform / OS version: Docker / node:16.15 URLs (if applicable): None Node.js version: v16.15.0

I think the cause of memory leak is chromium. so my solution is I restart docker container every day.

same issue. memory is increasing , still dont konw how to fix it

@Bonauze I think it is related to Chromium… But I don’t know what the exact cause is.

Now memory is increasing little by little, so it can be ignored… But Sometimes restart is necessary.

Maybe it comes from another place, in any case for my part I have no more ram leakage. Maybe there is a mistake in another place. Yes, I never close tabs, just chrome. and I use PM2 for server deployment. I hope you will find the solution to your problem.

Well, thanks for the suggestion regardless. I can’t even confirm whether it might’ve worked or not since it seems to just break things. The same fix on my local ws didn’t seem to cause any issues with my apps usage of it, so not sure why it killed puppeteer but I don’t feel like digging into it. The leak on my end is minor enough now that it’s a reasonably low priority, the biggest change being what I mentioned above about reading response.text() on some requests and passing to my log, once I got rid of that I stopped seeing the huge jumps that I was but it still leaks a little, from gushing to the occasional drip, definite improvement.

Check (even if I think you did) if you have the latest version of puppeteer and chrome. This could alleviate your problem if they have done some corrective work. If not, what exactly do you use Puppeteer for?

I’ve generally kept it pretty up-to-date and haven’t seen much/any change anytime I have, I’ve just updated again though with puppeteer using ws 8.13 now.

My puppeteer basically loads, logs into a site and just navigates between two pages on that site every minute or two non-stop, always in a single tab, occasionally the site forces a log out and it starts the process over, though it never closes the tab/page or anything.

The problem comes from chrome tabs, you close, open close tabs several times. This leaves a trace each time. The solution is to open one or more tabs and reuse the same ones. This will not increase the amount of ram, in any case for my part it solved the problem.

let page = null;
const pages = await browser.pages();
        page = pages.length ? pages[0] : await browser.newPage();

facing the same issue 😦

I’ve found out that puppeteer at some point spawns ghost chromium instances for no reason which don’t seem to be linked to any browser. Because with 2 pages open, I’ll suddenly have 7 chromium instances consuming large amounts of ram. And I believe usingbrowser.close()does not seem to close these ghost chromium instances.

@ForbiddenEra , I switched to playwright using their official Docker images and can confirm that I do not have memory leak issues anymore. I have also tried everything to try and fix this issue and I was not able to fix the memory leak.

I used puppeteer and now playwright because it is a PDF generation microservice internally. We pass html to format these and multiple teams utilize it. It seemed to be the easiest solution for what I was trying to accomplish while giving other teams flexibility to generate what they need.

I switched to Playwright and found they have the same issue unless you use their own build of Chromium. Using their official Docker image and then installing their browsers by running npx playwright install, I now have no issues with memory leaks.

If someone here finds a permanent solution for Puppeteer, I’d love to see it as I’ve wasted a lot of time trying to get it to work.

Hello I experienced the same problem

Same problem.