How to Use Puppeteer in n8n Workflows
Install the Puppeteer community node, run browser tasks in n8n, configure Docker, troubleshoot Chromium, and compare an API-based shortcut.
Direct answer: Use the community package n8n-nodes-puppeteer. In n8n 0.187 and later, install it from Settings → Community Nodes, make sure the machine running n8n has Chrome or Chromium plus its system dependencies, then add the Puppeteer node to a workflow. Configure the node for a custom script, screenshot, PDF, scraping, or another browser action, and validate browser launch in the same environment where the workflow will run.
n8n-nodes-puppeteer is a community node, not an n8n built-in node. Its installation and available operations can change, so check the current package instructions and your n8n version before deploying.
1. What you need before starting
- An n8n instance running version 0.187 or later for the package’s documented Community Nodes installation route.
- Permission to install community nodes on that instance.
- A browser runtime. Puppeteer must be able to launch Chrome or Chromium and all required system libraries.
- A workflow goal, such as opening a page, clicking a control, extracting content, creating a screenshot, or generating a PDF.
Self-hosted n8n gives you the most control over browser binaries and operating-system packages. The available research does not establish whether the current n8n Cloud service permits this particular package or supplies the browser runtime it requires. Treat Cloud support as an environment-specific question and verify it with the current n8n and package documentation.
2. Install the Puppeteer community node
- Open your n8n instance.
- Go to Settings → Community Nodes.
- Choose Install.
- Enter
n8n-nodes-puppeteer. - Read and accept n8n’s community-node risk notice.
- Install the package, then open the node picker and search for Puppeteer.
These steps come from the package maintainer’s instructions. Confirm the live instructions before following them because n8n’s interface and package compatibility can change.
Review the package before installing
Community nodes execute code in your n8n environment. Review the package source, maintainer, dependencies, update history, and requested permissions. n8n’s security-audit guidance includes community and custom nodes in its node-risk reporting; that reporting is not a certification that a particular package is safe.
3. Make Chromium work in Docker
A container can have the npm package installed and still fail when Puppeteer launches the browser. Chrome or Chromium needs an executable and operating-system libraries for fonts, sandboxing, graphics, and other runtime functions. The package documentation points to a Docker setup with the required dependencies, while related Puppeteer nodes warn that browser installation can fail when system libraries are missing.
For a production image:
- Start with the package’s current Docker instructions rather than an old image snippet.
- Confirm whether the image includes Chrome or Chromium and identify its binary path.
- Install the libraries required by that browser on your base distribution.
- Run a minimal launch workflow in the same container, user account, and execution mode used by production.
- Keep the browser version, Puppeteer version, and community-node version compatible.
Do not assume that a browser installed on your laptop is available inside the n8n container. A common symptom is an error saying that Chrome cannot be found, followed by a fix that either installs the browser in the image or points Puppeteer to the correct executable.
4. Build your first workflow
A useful first workflow has four stages:
- Trigger: Manual Trigger, Schedule Trigger, Webhook, or another event.
- Input: Set the target URL and any values the browser script needs.
- Browser action: The Puppeteer community node navigates and interacts with the page.
- Output: Store extracted JSON, a binary screenshot, a PDF, or a downstream API response.
The exact field names depend on the installed node version. Choose the operation exposed by your node, then map expressions from earlier nodes into its URL, script, selector, or output fields.
Example custom Puppeteer script
Use a script like this when the node provides a custom-script operation. It opens a page, waits for a selector, extracts structured data, and takes a screenshot.
const url = $json.url;
await page.goto(url, {
waitUntil: 'networkidle2',
timeout: 60000,
});
await page.waitForSelector('main', { timeout: 15000 });
const result = await page.evaluate(() => ({
title: document.title,
headings: Array.from(document.querySelectorAll('h1, h2')).map(el => el.textContent.trim()),
text: document.querySelector('main')?.innerText ?? '',
}));
const screenshot = await page.screenshot({
fullPage: true,
type: 'png',
});
return [{
json: result,
binary: {
screenshot: {
data: screenshot.toString('base64'),
mimeType: 'image/png',
fileName: 'page.png',
},
},
}];
If your node exposes a browser and page automatically, use those provided objects. If it expects a complete script or returns a different item shape, follow that version’s node help and adapt the final return value.
Navigation and waiting choices
| Need | Typical approach | Trade-off |
|---|---|---|
| HTML and initial resources | waitUntil: 'domcontentloaded' |
Fast, but late content may be missing. |
| Most network requests settled | waitUntil: 'networkidle2' |
More complete, but analytics or polling can delay completion. |
| One known component | page.waitForSelector() |
Usually more reliable than a fixed sleep. |
| Animation or delayed rendering | A short, bounded delay after the selector appears | Useful for canvas or transitions, but adds latency. |
5. Common browser actions
Click, type, and submit
await page.goto('https://example.com/login', { waitUntil: 'domcontentloaded' });
await page.type('#email', $json.email);
await page.type('#password', $json.password);
await page.click('button[type="submit"]');
await page.waitForNavigation({ waitUntil: 'networkidle2' });
return [{ json: { url: page.url(), title: await page.title() } }];
Capture one element
const card = await page.$('.invoice-card');
if (!card) throw new Error('Expected .invoice-card was not found');
const image = await card.screenshot({ type: 'png' });
return [{
binary: {
data: {
data: image.toString('base64'),
mimeType: 'image/png',
fileName: 'invoice-card.png',
},
},
}];
Create a PDF
const pdf = await page.pdf({
format: 'A4',
printBackground: true,
margin: { top: '16mm', right: '16mm', bottom: '16mm', left: '16mm' },
});
return [{
binary: {
data: {
data: pdf.toString('base64'),
mimeType: 'application/pdf',
fileName: 'page.pdf',
},
},
}];
Set viewport, locale, and user agent
await page.setViewport({ width: 1440, height: 900, deviceScaleFactor: 1 });
await page.setUserAgent('Mozilla/5.0 (compatible; n8n Puppeteer workflow)');
await page.emulateTimezone('UTC');
Only set a user agent or locale when the target site permits it and your use complies with its terms. A different viewport can change responsive layouts, lazy loading, and selectors.
6. Pass data between n8n nodes
Use expressions such as {{$json.url}} for the current item or {{$node["Set"].json["url"]}} for a named earlier node. Keep URLs, selectors, credentials, and timeouts in fields or credentials rather than hard-coding them in a script.
For multiple URLs, use Split in Batches or Loop Over Items and send one item at a time to the browser node. Close pages and browsers according to the community node’s lifecycle rules so a long run does not accumulate processes.
7. Reliability and edge cases
- Cookie banners: A consent dialog can cover the page or intercept clicks. Wait for it, click the appropriate control when permitted, or hide it for your capture logic.
- Lazy content: Scroll gradually before extracting or capturing a full page so images and sections have a chance to load.
- Single-page applications: A successful navigation does not mean the app is ready. Wait for an application-specific selector or state.
- Infinite scroll: Use a bounded loop with a maximum number of scrolls and a stop condition.
- Popups and new tabs: Listen for targets or pages and set a timeout; otherwise a workflow can wait indefinitely.
- CAPTCHAs and bot checks: Do not attempt to bypass access controls. Treat the page as unavailable and record the failure.
- Downloads: Configure a writable download directory in the runtime and pass the resulting path through n8n as binary data.
- Authentication: Store credentials in n8n credentials or environment-managed secrets. Never place passwords in execution logs.
- Untrusted URLs: Validate or allow-list input URLs to reduce SSRF risk and prevent access to internal services.
8. Troubleshooting Puppeteer in n8n
| Error or symptom | Likely cause | Fix |
|---|---|---|
| Executable doesn’t exist | Chrome or Chromium is absent, or the binary path is wrong. | Install a browser in the runtime, identify its path, and configure the node or image accordingly. |
| Browser exits immediately in Docker | Missing system libraries, sandbox restrictions, or incompatible versions. | Use the package’s current Docker setup, install required dependencies, and test launch as the n8n user. |
Timeout exceeded |
The page, selector, or network-idle condition never completed. | Use a realistic timeout, wait for a specific selector, and log the URL and step that timed out. |
| Selector not found | Responsive markup, delayed rendering, shadow DOM, or a changed site. | Inspect the rendered page, wait for the right state, and use a stable selector. |
| Screenshot is blank | Capture occurred before rendering, the page is blocked, or the viewport is wrong. | Wait for a visible element, verify the response content, and test the target URL manually in the same environment. |
| Workflow works locally but not in production | Different browser versions, fonts, permissions, environment variables, or network access. | Compare runtime images and launch settings; reproduce inside the production container. |
| Community node cannot be installed | Unsupported n8n version, disabled community nodes, or restricted permissions. | Check the instance policy, version compatibility, and the live package installation instructions. |
9. Performance, reliability, and cost
Launching a browser is more expensive than an HTTP request. Reuse a browser when the node supports it, keep pages short-lived, block unnecessary resources when your task allows it, and avoid unbounded waits. Process batches with controlled concurrency so CPU and memory remain predictable. Cache stable results in your workflow when freshness does not matter.
Retries should be bounded and should distinguish transient navigation failures from deterministic selector errors. Record the URL, operation, elapsed time, and failure category. A successful n8n execution only proves that the script returned; validate that the screenshot, PDF, or extracted data is present and non-empty.
The community package itself is software. Your costs come from the n8n hosting environment, browser CPU and memory, network traffic, and any external services you call. The research does not provide a benchmark or a package-specific price.
10. Or skip the browser setup
If your workflow only needs a clean screenshot or PDF, ScreenshotNeo removes the browser-runtime work. It provides a GET-based screenshot API and an MCP server for AI agents. Before capture, it accepts cookie and consent banners and removes more than 60 known consent platforms, newsletter popups, and chat widgets. Bot checks, blank pages, timeouts, failed loads, and cache hits are not billed, and each response reports the result with X-Page-Verdict and X-Billed headers.
See the ScreenshotNeo API documentation for the current options.
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)
const q = new URLSearchParams({ access_key: 'YOUR_API_KEY', url: 'https://stripe.com' });
const res = await fetch(`https://api.screenshotneo.com/v1/shot?${q}`);
ScreenshotNeo also supports full-page and element captures, device presets, custom viewports, retina scale, PDF settings, custom CSS and JavaScript, clicks, waits, request blocking, headers, cookies, user agents, timezone and geolocation, transparent backgrounds, resizing, caching, signed links, async jobs, webhooks, bulk capture, usage reporting, and an OpenAPI specification. Its MCP tools are take_screenshot, get_page_info, and capture_pdf.
There is a free plan with 1,000 screenshots per month and no card. Paid plans start at $5 for 3,000 screenshots, and every feature is available on every plan. Create a free ScreenshotNeo account.
11. FAQ
Is Puppeteer built into n8n?
No. n8n-nodes-puppeteer is a community package that adds browser automation nodes.
Does installing the npm package install Chrome?
Not reliably for every deployment. The browser executable and operating-system dependencies must be available in the runtime where n8n executes.
Can I use this on n8n Cloud?
The available sources do not establish current compatibility. Check the current n8n Cloud policy and the package documentation for your account and region.
Which package should I choose?
The research identifies n8n-nodes-puppeteer and an older n8n-nodes-browser package, but does not support a definitive feature or maintenance ranking. Compare current releases, n8n-version support, Docker requirements, and source before choosing.
When should I use an API instead of Puppeteer?
Use an API when you need repeatable captures without maintaining a browser image. Use Puppeteer when the workflow must perform custom interactions or extract application state that an API does not expose.


