DriversRecommendedOutdated drivers can make a good PC feel brokenScan driver issues before chasing fixes manually.Scan NowOctober DealsAmazon USOctober deal check: compare before you payAmazon US: current deals, useful picks and tech finds.Check DealsPC HealthRecommendedCrashes, freezes, slowdowns? Check your PC nowSpot repairable issues before they interrupt work.Check PC×
Skip to content
cPanel

How to Run a Node.js Puppeteer App on cPanel

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

You can run Puppeteer on cPanel when your host provides a supported Node.js and Passenger setup and the Linux server has the libraries and permissions needed to launch Chrome. Deploy the app as a Passenger-managed Node.js application—not as a terminal process or a separately exposed port—and confirm browser support with your hosting provider before building around it.

What cPanel needs to run Puppeteer

There are two separate compatibility questions: can the account run a Node.js application, and can the server run the browser that Puppeteer launches? Enabling Node.js does not by itself install Chrome’s Linux dependencies or authorize headless browser processes.

  • Node.js and Passenger: Ask the provider whether Node.js applications are enabled for your account, which Node.js versions are available, and whether the account has an application-management route such as Application Manager or the Websites hub. cPanel’s 2026 RHEL-based installation documentation lists package examples for Node.js 16, 18, 20 and 22, plus Passenger and Apache environment support; the applicable packages depend on the operating system. These are examples in cPanel documentation, not a promise that every host offers those versions.
  • Browser and Linux libraries: Puppeteer’s troubleshooting guidance says missing system dependencies are a common reason Chrome will not launch. The Debian dependencies it lists include libnss3, libgbm1, libgtk-3-0, libasound2 and font packages. Ask the host which browser executable is available, whether these libraries (or the distribution’s equivalents) are installed, and whether your account may launch Chromium processes.
  • Permissions and resources: Confirm that you have SSH or another supported way to install app dependencies, and ask about memory, process and execution-time limits. A browser process uses materially different resources from a small ordinary web request.
  • Operating system: Puppeteer’s guidance says Chrome does not support Alpine out of the box. If your plan uses Alpine, expect additional compatibility work and test on that exact host rather than assuming the standard install will work.

The cPanel Websites hub is provider-controlled: its Node.js option appears only when the provider enables it. If Node.js or browser processes are unavailable, no change to your application code can supply those server capabilities.

Choose the cPanel deployment route

Application Manager with Passenger

This is the classic route for a cPanel account where the provider enables Application Manager. You place the source in an application directory, register the domain and app path, and let Passenger manage the web process. cPanel recommends naming the default entry file app.js, because Passenger searches for that name.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.
  1. Create an application directory in your cPanel user’s home directory; do not put source code in a public directory just to make the app reachable.
  2. Add app.js and package.json, then install the dependencies from that directory using the Node.js/npm path required by your host.
  3. In cPanel, open Software → Application Manager. Register the application by selecting its domain, base URL, source path and deployment environment. Add any environment variables the app needs.
  4. Use the app’s domain and base URL to check the deployed service. Application Manager can manage application status and npm dependencies, subject to the host’s configuration.

If you use another startup filename, the server administrator must configure Passenger accordingly. cPanel’s documented custom-startup route uses PassengerStartupFile, PassengerAppType node and PassengerAppRoot, followed by rebuilding the Apache configuration with /usr/local/cpanel/scripts/rebuildhttpdconf and restarting HTTPD with /usr/local/cpanel/scripts/restartsrv_httpd. Those are server-level operations; an ordinary cPanel account may need its provider to perform them.

Websites hub / AI App Hosting

On hosts that expose the Websites hub’s AI App Hosting flow, choose Add Website, select an existing or new domain, choose AI App Hosting, and launch the site. The documented flow accepts a Git repository or ZIP upload. Git supports redeployment and rollback; ZIP is intended for an app that will not change. In Advanced settings, review the Node.js version, package manager, build output directory and environment variables before deploying. The service then installs dependencies, deploys and starts the app.

cPanel’s 2026 documentation for this flow states that each cPanel account can have up to four apps at a time. That limit applies to the described hub flow; check your provider’s current account configuration rather than treating it as a limit for every cPanel deployment method.

Build a small Passenger-compatible Puppeteer app

The example below captures a configured URL and returns a PNG at /screenshot. It deliberately does not accept an arbitrary URL from a public query string: an unrestricted screenshot endpoint can be abused to probe private network addresses. Set a capture token and protect access to the endpoint. The example starts and closes the browser for each capture, which is simple to reason about but adds launch overhead; for sustained workloads, use a controlled job queue and check whether your hosting plan permits the required persistent browser process and concurrency.

Free tools Windows power users keep installed

One-click scans. No signup required.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Create package.json in the app directory:

{
  "name": "cpanel-puppeteer-app",
  "version": "1.0.0",
  "private": true,
  "main": "app.js",
  "scripts": {
    "start": "node app.js"
  },
  "dependencies": {
    "puppeteer": "^24.0.0"
  }
}

The version range above is an example dependency declaration, not a statement about the newest version available or compatibility with every host. Select and test a Puppeteer version that matches your chosen Node.js version and provider’s environment. If the host provides Chrome but not Puppeteer’s downloaded browser, set CHROME_EXECUTABLE_PATH to the exact executable path supplied by the administrator.

Create app.js:

const http = require('node:http');
const puppeteer = require('puppeteer');

const target = process.env.TARGET_URL;
const token = process.env.CAPTURE_TOKEN;
const executablePath = process.env.CHROME_EXECUTABLE_PATH;
const timeoutMs = Number(process.env.CAPTURE_TIMEOUT_MS || 30000);

const server = http.createServer(async (req, res) => {
  if (req.url === '/health' && req.method === 'GET') {
    res.writeHead(200, { 'content-type': 'text/plain; charset=utf-8' });
    return res.end('ok');
  }

  if (req.url !== '/screenshot' || req.method !== 'GET') {
    res.writeHead(404, { 'content-type': 'text/plain; charset=utf-8' });
    return res.end('not found');
  }

  if (!token || req.headers.authorization !== `Bearer ${token}`) {
    res.writeHead(401, { 'content-type': 'text/plain; charset=utf-8' });
    return res.end('unauthorized');
  }

  if (!target) {
    res.writeHead(503, { 'content-type': 'text/plain; charset=utf-8' });
    return res.end('TARGET_URL is not configured');
  }

  let browser;
  try {
    const launchOptions = { headless: true };
    if (executablePath) launchOptions.executablePath = executablePath;

    browser = await puppeteer.launch(launchOptions);
    const page = await browser.newPage();
    page.setDefaultNavigationTimeout(timeoutMs);
    await page.goto(target, { waitUntil: 'networkidle2', timeout: timeoutMs });
    const image = await page.screenshot({ type: 'png', fullPage: true });
    res.writeHead(200, {
      'content-type': 'image/png',
      'cache-control': 'no-store'
    });
    res.end(image);
  } catch (error) {
    console.error('Puppeteer capture failed:', error);
    if (!res.headersSent) {
      res.writeHead(502, { 'content-type': 'text/plain; charset=utf-8' });
      res.end('capture failed');
    }
  } finally {
    if (browser) await browser.close().catch((error) => {
      console.error('Browser close failed:', error);
    });
  }
});

server.listen(process.env.PORT || 3000, '0.0.0.0');

Install the dependency from the application directory with the Node/npm executable required by your host. If your plan provides SSH and the host’s example Node installation path is applicable, cPanel documents a pattern such as /opt/cpanel/ea-nodejs**/bin/node app.js; the asterisks stand for a versioned directory, so use the actual path installed on your server, not the text literally. Configure TARGET_URL and CAPTURE_TOKEN in the app’s environment settings. Set CHROME_EXECUTABLE_PATH only when the provider gives you a valid path; otherwise Puppeteer may use its downloaded browser if the install and host support it.

Passenger manages the externally routed port using reverse port binding. Do not open a random public port or assume that port 3000 is your public endpoint. cPanel’s 2026 application-installation guidance says Passenger controls the port on which the Node.js application listens for HTTP requests. The PORT fallback above is useful for local testing; the production behavior must match the Passenger integration configured by your host.

Test locally on the account, then through the domain

  1. From SSH, change to the app directory and use the host’s Node binary to start the app as the cPanel user. Do not test only as root: file ownership, permissions and browser cache paths can differ.
  2. In another shell, check the local health route with curl http://127.0.0.1:3000/health if the process is listening on that local port. Expect ok. cPanel’s example similarly checks a local endpoint at http://127.0.0.1:3000; this is a local diagnostic, not a public port to expose.
  3. Test the protected capture route locally with curl -H 'Authorization: Bearer YOUR_TOKEN' http://127.0.0.1:3000/screenshot --output shot.png. Verify that the response is an image and opens correctly.
  4. Stop the manual test process, register or deploy the app through the supported cPanel interface, then request /health and /screenshot through the configured domain and base URL.

Do not leave a manually launched process competing with Passenger after deployment. Passenger, rather than a shell session, is responsible for the application exposed through the configured website route.

What’s actually slowing this PC down?

Pick the symptom - the matching free tool is one click away.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Restart the app after code changes

For the classic Passenger route, create or update tmp/restart.txt under the application root after changes that should take effect. cPanel documents that this directs mod_passenger to restart the app; touch the file again for each restart request. Ensure the tmp directory exists and is writable by the cPanel user. For a Websites hub deployment, use that interface’s redeploy or restart controls when available.

For runtime errors, inspect the application’s logs, which cPanel’s example places under a path such as /home/user/nodejsapp/logs. Replace user and nodejsapp with the account and app directory in your environment.

Troubleshoot common failures

  • Node.js or Application Manager is missing: The provider controls whether the Websites hub exposes Node.js. Ask whether Node.js, Passenger and the relevant app-management route are enabled for the account. If not, choose a plan that supports them or move the workload to a managed VPS or server where the required components can be installed.
  • Passenger cannot find the app: Confirm that the source path points to the application root and that the default entry file is named app.js. If using a custom filename, the Passenger startup configuration must be set by someone with server-level access.
  • The app works in a shell but not through the domain: Check the selected domain and base URL in Application Manager, confirm the deployment environment variables, and inspect the app logs. Do not try to fix routing by exposing a new public port; investigate Passenger’s reverse port binding and ask the host to check its configuration.
  • puppeteer.launch() reports missing libraries: Check the browser’s shared-library dependencies with ldd /path/to/chrome | grep not, replacing the path with the actual browser binary. Provide missing-library output to the host administrator and ask whether the server has the required packages. Puppeteer’s Linux guidance specifically recommends checking for unresolved dependencies.
  • Chrome cannot execute or locate its browser: Verify that the executable exists and is executable by the cPanel user, and check the Puppeteer browser cache and installation. If using a system browser, confirm the exact path with the provider and configure CHROME_EXECUTABLE_PATH. A path that works for an administrator may not be readable by the app user.
  • Chrome exits with a sandbox or permission error: Ask the provider whether Chromium is permitted under the account’s process and security policy. Do not add --no-sandbox as a routine fix; use it only if the host administrator explicitly requires it and accepts the isolation trade-off.
  • Capture hangs or returns a timeout: Check whether the target page actually finishes loading, whether the host can reach it, and whether the configured timeout is adequate. The sample waits for networkidle2, which can be unsuitable for pages that maintain ongoing network activity. Test another appropriate readiness condition for the target rather than increasing timeouts without limit.
  • Captures fail under load or the app restarts: Each simultaneous request can create another browser process in this example. Reduce concurrency, queue capture jobs, and ask the provider about memory and process limits. Shared hosting can be a poor fit if browser launches exhaust those limits.
Independent reader supportYour contribution helps us test, update, and keep practical guides available for everyone.Support on Ko-Fi

When shared cPanel is not enough

Compare providers on the capabilities Puppeteer actually needs, not just whether a plan advertises Node.js. Check Node.js and Passenger availability, Linux distribution and Chrome libraries, SSH/package permissions, process and memory limits, app restart and log access, and whether headless browser automation is allowed. A managed VPS or dedicated server becomes more attractive when shared hosting cannot install browser dependencies or imposes process limits that prevent reliable captures. Confirm the OS image and browser packages with the provider before moving; a VPS label alone does not guarantee a compatible Chrome environment.

Or skip the browser setup

If your goal is to return a website screenshot rather than host your own browser, ScreenshotNeo provides a screenshot API and MCP server. Its API accepts a URL in one GET request and can return PNG, JPEG, WebP or PDF output. For Node.js, the following example saves the response bytes as a WebP file; see the ScreenshotNeo API documentation for parameters and response details.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.
const q = new URLSearchParams({ access_key: 'YOUR_API_KEY', url: 'https://stripe.com' });
const res = await fetch(`https://api.screenshotneo.com/v1/shot?${q}`);
if (!res.ok) throw new Error(`Screenshot request failed: ${res.status}`);
const fs = await import('node:fs/promises');
await fs.writeFile('shot.webp', Buffer.from(await res.arrayBuffer()));

Equivalent one-request examples:

curl -G "https://api.screenshotneo.com/v1/shot" -d access_key=YOUR_API_KEY --data-urlencode url=https://stripe.com -o shot.webp
import requests
r = requests.get("https://api.screenshotneo.com/v1/shot", params={"access_key": "YOUR_API_KEY", "url": "https://stripe.com"}, timeout=90)
open("shot.webp", "wb").write(r.content)
  • Cookie/consent banners are accepted like a visitor, and more than 60 known consent platforms, newsletter popups and chat widgets can be removed before capture; each step can be turned off.
  • Bot checks/CAPTCHAs, blank pages, timeouts, failed loads and cache hits cost nothing. Response headers state the page verdict and whether the request was billed.
  • An MCP server provides take_screenshot, get_page_info and capture_pdf tools for Claude, Cursor and other MCP clients.
  • The free plan includes 1,000 shots per month without a card; paid plans start at $5 for 3,000 shots. Yearly billing gives two months free, and every feature is on every plan.

Sign up for ScreenshotNeo’s free plan: 1,000 screenshots a month, no card required.

Frequently Asked Questions

Can I leave a terminal session running instead of configuring Passenger?

That is not the deployment model for a cPanel website application. Use the host-supported Passenger or Websites hub workflow so the app is managed and routed through the configured domain.

Will Puppeteer always download a browser during installation?

Not necessarily. The install and host environment determine whether its browser is available; when it is not, the app may need the provider’s system-browser path and compatible libraries.

Product prices and availability are accurate as of the date/time indicated and are subject to change. Any price and availability information displayed on Amazon at the time of purchase will apply.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Leave a Reply

Your email address will not be published. Required fields are marked *

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Read next

Recommended PC Tool
Recommended PC Tool
PC Slower Than It Used to Be?Free scan - under a minute
Crashes, No Sound, or Screen Glitches?Free driver scan

Two free Windows tools

One Free Minute Could Fix That PC

Before you go - each of these free tools takes about a minute and tackles what quietly slows a Windows PC down.

Special offer. View Outbyte info, uninstall instructions, EULA, and Privacy Policy.