Unable to run playwright on n8n runner its giving error ( I tried custom n8n image as well installing deps)

Node execution failed

This can happen for various reasons. Please try executing the node again. If the problem persists, you can try the following:

  1. Reduce the number of items processed at a time, by batching them using a loop node
  2. Increase the memory available to the task runner with ‘N8N_RUNNERS_MAX_OLD_SPACE_SIZE’ environment variable
const { chromium } = require('playwright');

return (async () => {
  const browser = await chromium.launch({ headless: true });
  const page = await browser.newPage();
  await page.goto('https://example.com');

  await page.waitForSelector('.content', { timeout: 10000 });

  const html = await page.content();
  await browser.close();

  return { html };
})();

Hi @karprabha,

Can you please share the steps you took for creating a custom n8n image and how you installed the dependencies?

hi @karprabha !

This usually isn’t a memory or batching issue.
Playwright fails on n8n runners most often because the required system dependencies and browsers are missing, not because of the JS code itself.

Important points to check:

  • Installing playwright via npm is not enough
  • You must install Playwright system dependencies and the browsers inside the image
  • On Alpine-based images (like the default n8n image), Playwright is not officially supported and often fails

The most reliable setup is:

  • Use a Debian/Ubuntu-based image
  • Install Playwright with:
npx playwright install --with-deps
  • Run Playwright inside the runner container, not only on the main instance

If you’re using task runners, the Playwright dependencies must exist on the runner image, not just the main n8n image.

If you can share your Dockerfile, it’ll be easy to spot what’s missing.

Hi @Wouter_Nigrini @tamy.santos Thanks for responding

this was the Dockerfile I was using for runner

# Stage 1: Install Chromium and dependencies in a full Alpine image
FROM alpine:3.22 AS chromium-installer
RUN apk add --no-cache \
    chromium \
    nss \
    freetype \
    freetype-dev \
    harfbuzz \
    ca-certificates \
    ttf-freefont \
    font-noto-emoji \
    wqy-zenhei

# Stage 2: Copy Chromium and dependencies to the n8n runners image
FROM n8nio/runners:latest

USER root

# Copy Chromium binary, libraries, and fonts from the installer stage
COPY --from=chromium-installer /usr/bin/chromium /usr/bin/chromium
COPY --from=chromium-installer /usr/lib/chromium/ /usr/lib/chromium/
COPY --from=chromium-installer /usr/lib/libnss*.so* /usr/lib/
COPY --from=chromium-installer /usr/lib/libfreetype*.so* /usr/lib/
COPY --from=chromium-installer /usr/lib/libharfbuzz*.so* /usr/lib/
COPY --from=chromium-installer /usr/share/fonts/ /usr/share/fonts/
COPY --from=chromium-installer /etc/fonts/ /etc/fonts/

# Install JavaScript packages for utilities and scraping
RUN cd /opt/runners/task-runner-javascript && \
    pnpm add moment uuid lodash dotenv axios got node-fetch puppeteer playwright cheerio jsdom xml2js jsonpath yaml form-data

# Configure Playwright to use system Chromium instead of downloading browsers
# This is necessary because Playwright's bundled browsers don't work well with Alpine's musl libc
ENV PLAYWRIGHT_SKIP_BROWSER_DOWNLOAD=1
ENV PLAYWRIGHT_CHROMIUM_EXECUTABLE_PATH=/usr/bin/chromium

# Install Python packages for utilities and scraping
RUN cd /opt/runners/task-runner-python && \
    uv pip install requests httpx aiohttp beautifulsoup4 lxml lxml[html_clean] selenium scrapy requests-html mechanize pyquery html5lib cssselect parsel pandas numpy jsonpath-ng pyyaml toml python-dotenv environs python-dateutil arrow pytz pendulum validators email-validator phonenumbers iso8601

# Copy the launcher config file
COPY docker/runners/n8n-task-runners.json /etc/n8n-task-runners.json

USER runner

and this is the custom json file

{
  "task-runners": [
    {
      "runner-type": "javascript",
      "workdir": "/home/runner",
      "command": "/usr/local/bin/node",
      "args": [
        "--disallow-code-generation-from-strings",
        "--disable-proto=delete",
        "/opt/runners/task-runner-javascript/dist/start.js"
      ],
      "health-check-server-port": "5681",
      "allowed-env": [
        "PATH",
        "GENERIC_TIMEZONE",
        "NODE_OPTIONS",
        "N8N_RUNNERS_AUTO_SHUTDOWN_TIMEOUT",
        "N8N_RUNNERS_TASK_TIMEOUT",
        "N8N_RUNNERS_MAX_CONCURRENCY",
        "N8N_SENTRY_DSN",
        "N8N_VERSION",
        "ENVIRONMENT",
        "DEPLOYMENT_NAME"
      ],
      "env-overrides": {
        "NODE_FUNCTION_ALLOW_BUILTIN": "*",
        "NODE_FUNCTION_ALLOW_EXTERNAL": "moment,uuid,lodash,dotenv,axios,got,node-fetch,puppeteer,playwright,cheerio,jsdom,xml2js,jsonpath,yaml,form-data",
        "N8N_RUNNERS_HEALTH_CHECK_SERVER_HOST": "0.0.0.0"
      }
    },
    {
      "runner-type": "python",
      "workdir": "/home/runner",
      "command": "/opt/runners/task-runner-python/.venv/bin/python",
      "args": [
        "-m",
        "src.main"
      ],
      "health-check-server-port": "5682",
      "allowed-env": [
        "PATH",
        "N8N_RUNNERS_LAUNCHER_LOG_LEVEL",
        "N8N_RUNNERS_AUTO_SHUTDOWN_TIMEOUT",
        "N8N_RUNNERS_TASK_TIMEOUT",
        "N8N_RUNNERS_MAX_CONCURRENCY",
        "N8N_SENTRY_DSN",
        "N8N_VERSION",
        "ENVIRONMENT",
        "DEPLOYMENT_NAME"
      ],
      "env-overrides": {
        "PYTHONPATH": "/opt/runners/task-runner-python",
        "N8N_RUNNERS_STDLIB_ALLOW": "*",
        "N8N_RUNNERS_EXTERNAL_ALLOW": "requests,httpx,aiohttp,beautifulsoup4,bs4,lxml,selenium,scrapy,requests-html,mechanize,pyquery,html5lib,cssselect,parsel,pandas,numpy,jsonpath-ng,pyyaml,toml,dotenv,environs,python-dateutil,arrow,pytz,pendulum,validators,email-validator,phonenumbers,iso8601"
      }
    }
  ]
}