How to Run Python in n8n: Using External Libraries Like Playwright
Headless browser rendering, pandas, and more—all available via your own API
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)
Sometimes we receive a table with only a single row:
We need to:
- Extract specific columns (machine type, manufacturer, address, phase, info)
- Filter out irrelevant rows (partial data, billing info)
- 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:
- Trigger: n8n receives the email
- Webhook: n8n sends the email body (with HTML table) to an external Python script
- Script: Python extracts, filters, and renders the table using Playwright
- Return: The script returns a PNG image URL back to n8n
- 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.
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 pngThe 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/webhookWe can test it right from the test panel by pasting sample email HTML:
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 }}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
What Python Libraries Are Available?
This approach isn't just for Playwright. You can use any of the 117+ pre-installed packages, including:
| Library | Use Case |
|---|---|
| Playwright | Headless browser automation, screenshots, PDF generation |
| pandas | Data transformation, CSV/Excel processing |
| pdfplumber | Extract text and tables from PDFs |
| pillow | Image manipulation, resizing, format conversion |
| opencv-python | Computer vision, image processing |
| beautifulsoup4 | HTML/XML parsing |
| openpyxl | Excel 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:
- PDF data extraction - Use pdfplumber to extract invoice details
- Excel transformations - Use pandas to clean/merge/pivot spreadsheet data
- Image processing - Resize, compress, or watermark images with Pillow
- Web scraping - Run Playwright to scrape JavaScript-heavy pages
- Computer vision - Analyze images with OpenCV
- 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