n8n Integration — Generate Images Without Puppeteer
Replace the n8n Puppeteer node with a single HTTP Request node. Generate images from HTML with RendShot in any n8n workflow.
n8n is a workflow automation platform that connects apps, APIs, and databases with visual flows. If you're currently using the Puppeteer community node to generate images or take screenshots, RendShot is a simpler drop-in alternative: one HTTP Request node, no Docker, no Chromium, works on n8n Cloud and self-hosted alike.
Prerequisites
- A RendShot API key — sign up free at rendshot.ai, then create a key in Dashboard — API Keys. Keys start with
rs_live_. - An n8n instance — either n8n Cloud or a self-hosted installation.
Step 1: Add an HTTP Request Node
In your workflow, add an HTTP Request node and configure it as follows:
Basic settings:
| Field | Value |
|---|---|
| Method | POST |
| URL | https://api.rendshot.ai/v1/image |
| Authentication | Header Auth |
Authentication — Header Auth:
| Field | Value |
|---|---|
| Name | Authorization |
| Value | Bearer rs_live_YOUR_KEY |
Body:
Set Body Content Type to JSON, then use the following body structure:
{
"html": "<div style=\"font-family:sans-serif;padding:40px;background:#1a1816;color:white\"><h1>Hello World</h1></div>",
"width": 1200,
"height": 630,
"format": "png"
}Supported values for format are png, jpeg, and webp. Width and height default to 1200 and 630 if omitted.
The node will return a JSON response with a url field pointing to the hosted image:
{
"id": "img_01abc...",
"url": "https://assets.rendshot.ai/img/01abc....png",
"width": 1200,
"height": 630,
"format": "png",
"created_at": "2026-04-03T10:00:00.000Z"
}Step 2: Use Dynamic Data from Previous Nodes
The real power comes from injecting data from earlier nodes — Airtable rows, RSS items, webhook payloads — directly into your HTML.
Say an Airtable Trigger node fires when a new row is created, with fields title, author, and category. In the HTTP Request node body, reference them with n8n expressions:
{
"html": "<div style=\"font-family:sans-serif;padding:48px;background:#1a1816;color:#fff;width:1200px\"><p style=\"color:#6b8f5e;font-size:14px;text-transform:uppercase;letter-spacing:2px\">{{ $json.category }}</p><h1 style=\"font-size:48px;margin:16px 0\">{{ $json.title }}</h1><p style=\"color:#635c53\">By {{ $json.author }}</p></div>",
"width": 1200,
"height": 630,
"format": "png"
}n8n evaluates the {{ }} expressions before sending the request, so RendShot receives a fully resolved HTML string.
Tips for building HTML in n8n:
- Use the Expression editor (the
=button next to the field) for multi-line HTML — it gives you a larger input area. - Escape double quotes inside JSON strings as
\", or use a Set node to build the HTML string separately before passing it to the HTTP Request node. - If your HTML is complex, use a Code node to build the string with JavaScript template literals, then reference
{{ $json.html }}in the body.
// Code node — build HTML, output as { html: "..." }
const title = $input.first().json.title;
const author = $input.first().json.author;
return [{
json: {
html: `
<div style="font-family:sans-serif;padding:48px;background:#1a1816;color:#fff">
<h1 style="font-size:48px">${title}</h1>
<p style="color:#635c53">By ${author}</p>
</div>
`
}
}];Step 3: Use the Image URL in the Next Node
The HTTP Request node output contains {{ $json.url }}. Wire this to any downstream node.
Slack — post image in a channel:
In a Slack node (Send Message), set the Text field to:
New post image: {{ $json.url }}Or attach it as a block:
{
"type": "image",
"image_url": "{{ $json.url }}",
"alt_text": "Generated image"
}Email (Gmail / SMTP) — embed in message body:
<img src="{{ $json.url }}" width="600" alt="Report" />Airtable / Notion — update a field:
Map {{ $json.url }} to an attachment or URL field in an Airtable or Notion update node.
Example Workflows
Airtable new row → image → Slack
- Airtable Trigger — fires when a new article row is created
- HTTP Request — sends
htmlbuilt fromtitle,author,cover_colorfields to/v1/image - Slack — posts the
urlto#content-teamwith the article link
Use case: automatically generate a social card for every new piece of content without opening a design tool.
RSS feed → OG image → CMS update
- RSS Feed Read — polls a feed every hour
- HTTP Request — renders an OG image from the item's
titleandpubDate - HTTP Request (second) — PATCHes the CMS API with the new
og_imageURL
Use case: keep OG images current for a curated link newsletter without manual work.
Weekly cron → report image → email digest
- Cron — triggers every Monday at 08:00
- HTTP Request — fetches stats from your internal API
- Code node — formats the numbers into an HTML dashboard card
- HTTP Request — renders the card to
/v1/image - Gmail — sends the image as an inline attachment to the team
Use case: a weekly snapshot of key metrics delivered to inboxes, no BI tool required.
URL Screenshots
To capture a screenshot of a live URL instead of rendering HTML, use the /v1/screenshot endpoint:
{
"url": "https://example.com",
"width": 1280,
"height": 800,
"full_page": false
}Everything else — authentication, the response url field, wiring to downstream nodes — works identically to the /v1/image endpoint.
Why Not the Puppeteer Node?
The n8n Puppeteer community node works, but comes with meaningful operational overhead:
| Puppeteer node | RendShot | |
|---|---|---|
| n8n Cloud | Not available (self-hosted only) | Works everywhere |
| Setup | Requires Docker + Chromium (~400 MB) | No setup, just an API key |
| Memory | Leaks on long-running workflows | Stateless HTTP call |
| Fonts | Platform-dependent, often missing | Loaded automatically |
| Maintenance | Manual Chromium updates | Handled by RendShot |
| Timeout handling | Manual page timeout config | Server-side, 30s default |
If you're on n8n Cloud, the Puppeteer node is not available at all — RendShot is the straightforward path. If you're self-hosted, switching to RendShot removes a Docker dependency and the memory management burden from your n8n instance.
Troubleshooting
401 Unauthorized
Your API key is missing or incorrect. Double-check that:
- The Header Auth name is exactly
Authorization(capital A) - The value is
Bearer rs_live_YOUR_ACTUAL_KEYwith no extra spaces - The key hasn't been deleted from the Dashboard
400 Bad Request
The request body is malformed. Common causes:
htmlfield is missing or empty- JSON is invalid — check that double quotes inside the HTML string are escaped as
\" - An unsupported
formatvalue (onlypng,jpeg,webpare accepted)
Enable Include Response Body in the HTTP Request node settings to see the full error message from the API:
{
"error": {
"code": "VALIDATION_ERROR",
"message": "html is required",
"status": 400
}
}Timeout / no response
The default n8n HTTP Request timeout is 300 seconds, which is more than enough. If you see timeouts:
- Check that your HTML doesn't reference large external resources (images, fonts from slow CDNs)
- Simplify the HTML — deeply nested elements or large inline SVGs can increase render time
- Increase the Timeout setting in the HTTP Request node options if needed
See the API Reference for all request parameters, response fields, rate limits, and error codes.