Back to Blog
n8nPythonPlaywrightAutomation

How to Run Python in n8n: Using External Libraries Like Playwright

Headless browser rendering, pandas, and more—all available via your own API

TomDecember 26, 20257 min read

If you're using n8n and need to run Python code with libraries that aren't built-in, you've probably hit a wall. While n8n's Code node supports Python, it's limited to the standard library and a handful of pre-installed packages. Need pandas? Playwright? pdfplumber? You're out of luck—unless you want to self-host and manage Docker containers.

In this guide, we'll show you how to run real Python scripts with any library you need, using external webhooks. We'll walk through a real example: rendering HTML email tables as PNG images using a headless browser.


The Problem: n8n Python Libraries Are Limited

n8n's Python Code node is powerful for simple tasks, but it has strict limitations:

  • Only built-in packages (or a small set of pre-installed ones like requests)
  • Can't pip install additional libraries
  • No headless browser support (Playwright, Selenium, Puppeteer)
  • No data processing libraries like pandas or numpy

For self-hosted users, you can add packages by modifying your Docker image—but that means managing infrastructure, rebuilding containers, and dealing with dependency conflicts.

For cloud users on n8n.cloud, you're stuck with what's provided.


The Use Case: HTML Table → PNG Rendering

Here's the problem we needed to solve:

We receive order emails from clients. Each email contains an HTML table with order details—machine type, manufacturer, shipping address, and other info. But the tables aren't consistent:

  • Sometimes we get the full table with 10+ columns (including billing info we don't need)
  • Sometimes we get only the relevant row
  • Sometimes rows are partially filled (and we only want fully completed rows)
The messy full table with all columns including billing info

Sometimes we receive a table with only a single row:

Sometimes we receive only a single row

We need to:

  1. Extract specific columns (machine type, manufacturer, address, phase, info)
  2. Filter out irrelevant rows (partial data, billing info)
  3. Render the clean table as a PNG for downstream processing and human review

Why PNG? We might send it to a vision API later, and humans need to visually verify the data.


Why n8n Can't Do This Alone

You might think: "Can't n8n just extract the HTML and I'll parse it?"

Here's the problem:

  • HTML tables vary wildly - Different formats from different departments
  • Pure HTML extraction is messy - You'd need regex nightmares or complex parsing logic
  • No rendering engine - n8n can't take HTML and render it as an image
  • No Playwright/Puppeteer - Those libraries aren't available in n8n's Python Code node

The solution? Use an external Python webhook with a headless browser.


The Solution: Python Webhook with Playwright

Instead of trying to cram everything into n8n nodes, we:

  1. Trigger: n8n receives the email
  2. Webhook: n8n sends the email body (with HTML table) to an external Python script
  3. Script: Python extracts, filters, and renders the table using Playwright
  4. Return: The script returns a PNG image URL back to n8n
  5. Continue: n8n uploads the image to Dropbox/Google Drive or embeds it in a Trello card

Step-by-Step: Building the Script

Step 1: Use the Prompt Builder

We head to Apyrun's Prompt Builder and answer the setup questions:

  • How will the script be triggered? Via webhook from n8n
  • What data format? JSON (n8n's default webhook format)
  • Does your script receive files? No—we're sending the email body as text
  • Does your script output files? Yes—a PNG image
  • Should the file be returned to n8n or uploaded to storage? Return to n8n (we have downstream processing)
  • Should we use AI processing? No—this is pure code logic. We want deterministic results.
The Prompt Builder with answers visible

In plain language, we describe what the script should do:

Goal: render html table from email body into .png for further processing.
Input: html body of 1 email. Most mails will contain a table. IF no table = script should not error but output a mockup table .png 

Table: 10 columns and 1-x rows
We are only interested in the 1 row that has the most cells filled.
Other rows also gonna have some cells filled but the row with the most cells filled is what we need to focus on. We need to skip all other rows.

from the 1 row that has the most cells filled, we only want to export certain columns. First column on left side = 1
columns we want to export: 1, 2, 3, 7, 8
the remaining columns must be skipped

we also want the header to be exported to the png

The Prompt Builder generates a structured prompt. We copy it into Claude, which generates the Python code.

Step 2: Deploy the Script

We paste the Python code into Apyrun and click Deploy. Within seconds, the script is live and we get a webhook URL:

https://apyrun.io/tom/table-to-png/webhook
Script deployed and running (green status indicator)

We can test it right from the test panel by pasting sample email HTML:

Test panel showing successful response with file_url

Step 3: Connect to n8n

Back in n8n, we add an HTTP Request node:

  • Method: POST
  • URL: https://apyrun.io/tom/table-to-png/webhook
  • Authentication: Custom header Authorization: Bearer <your-token>
  • Body: Form data with the email html
html: {{ $json.html }}
n8n HTTP Request node configuration

The response includes a temporary file URL (file_url), which we can:

  • Pass to a Dropbox upload node
  • Pass to a Google Drive upload node
  • Embed in a Trello card or Notion page
  • Send to a vision API for further processing

The Results

Before, we had:

  • Multiple Code nodes trying to parse HTML
  • Manual Dropbox upload steps
  • Separate template stitching logic
  • Still couldn't render the table visually

After:

  • One webhook call handles extraction, filtering, and rendering
  • Clean PNG output every time
  • No Docker setup, no infrastructure management
  • Works for any HTML table format
Clean output: only 5 relevant columns, no billing data

What Python Libraries Are Available?

This approach isn't just for Playwright. You can use any of the 117+ pre-installed packages, including:

LibraryUse Case
PlaywrightHeadless browser automation, screenshots, PDF generation
pandasData transformation, CSV/Excel processing
pdfplumberExtract text and tables from PDFs
pillowImage manipulation, resizing, format conversion
opencv-pythonComputer vision, image processing
beautifulsoup4HTML/XML parsing
openpyxlExcel file creation and editing

Why This Beats Self-Hosting

You might think: "Can't I just add Playwright to my n8n Docker image?"

You can. But consider:

  • Infrastructure overhead - You're now managing Docker, dependencies, rebuilds
  • Version conflicts - Playwright requires specific browser binaries
  • Memory/CPU - Headless browsers are resource-heavy
  • Maintenance - Every time you need a new library, rebuild the container

With the webhook approach:

  • No infrastructure - Just call a URL
  • No Docker - No containers to manage
  • Instant deploys - Change code, click deploy, done
  • Isolated resources - Heavy processing doesn't slow down your n8n instance

Use Cases Beyond HTML Rendering

This pattern works for any n8n workflow that needs Python libraries:

  1. PDF data extraction - Use pdfplumber to extract invoice details
  2. Excel transformations - Use pandas to clean/merge/pivot spreadsheet data
  3. Image processing - Resize, compress, or watermark images with Pillow
  4. Web scraping - Run Playwright to scrape JavaScript-heavy pages
  5. Computer vision - Analyze images with OpenCV
  6. API rate limiting - Handle complex retry logic that n8n can't do natively

Try It Yourself

If you need to run Python in n8n with libraries that aren't built-in, you can use external webhooks with Apyrun.

What you get:

  • 117+ Python packages pre-installed
  • No timeout limits (unlike n8n's execution time caps)
  • Headless browser support (Playwright, Selenium)
  • Deploy in seconds, no Docker required
  • Works with n8n, Zapier, Make, or any platform that can call a webhook