Node.js
Works with fetch (Node 18+), axios, and any HTTP client
01 โ Authentication
Add the API key header
Every request requires an
X-API-Key header.
auth.js
const res = await fetch('https://renderpix.dev/v1/render', {
method: 'POST',
headers: {
'X-API-Key': 'rpx_your_api_key',
'Content-Type': 'application/json',
},
body: JSON.stringify({ html: '<h1>Hello</h1>', width: 1200, height: 630 }),
});
02 โ Basic usage
Render HTML to PNG
POST any HTML string, receive a PNG binary. Works with
fetch (Node 18+) or axios.
render-fetch.js
const fs = require('fs');
async function renderHtml(html, outputFile = 'output.png') {
const res = await fetch('https://renderpix.dev/v1/render', {
method: 'POST',
headers: {
'X-API-Key': 'rpx_your_api_key',
'Content-Type': 'application/json',
},
body: JSON.stringify({ html, width: 1200, height: 630, format: 'png' }),
});
if (!res.ok) {
const err = await res.json().catch(() => ({}));
throw new Error(`RenderPix error ${res.status}: ${err.message || res.statusText}`);
}
const buffer = Buffer.from(await res.arrayBuffer());
fs.writeFileSync(outputFile, buffer);
}
renderHtml('<h1 style="font-family:sans-serif">Hello, RenderPix!</h1>');
render-axios.js
const axios = require('axios');
const fs = require('fs');
const response = await axios.post(
'https://renderpix.dev/v1/render',
{ html: '<h1>Hello</h1>', width: 1200, height: 630, format: 'png' },
{
headers: { 'X-API-Key': 'rpx_your_api_key' },
responseType: 'arraybuffer',
}
);
fs.writeFileSync('output.png', response.data);
03 โ Real-world
OG image generator
Generate a 1200ร630 social card from title, description, and domain.
og-image.js
const fs = require('fs');
async function generateOgImage({ title, description, domain, outputFile = 'og.png' }) {
const html = `<!DOCTYPE html><html><head><meta charset="UTF-8">
<style>
* { margin:0; padding:0; box-sizing:border-box; }
body { width:1200px; height:630px; overflow:hidden; padding:80px;
font-family:-apple-system,sans-serif;
background:linear-gradient(135deg,#0f172a,#1e293b);
display:flex; align-items:center; }
.card { display:flex; flex-direction:column; gap:24px; width:100%; }
.domain { font-size:20px; color:#38bdf8; text-transform:uppercase; letter-spacing:2px; }
h1 { font-size:72px; font-weight:800; color:#f1f5f9; line-height:1.1; }
p { font-size:28px; color:#94a3b8; }
</style></head>
<body><div class="card">
<div class="domain">${domain}</div>
<h1>${title}</h1>
<p>${description}</p>
</div></body></html>`;
const res = await fetch('https://renderpix.dev/v1/render', {
method: 'POST',
headers: { 'X-API-Key': 'rpx_your_api_key', 'Content-Type': 'application/json' },
body: JSON.stringify({ html, width: 1200, height: 630, format: 'png' }),
});
if (!res.ok) throw new Error(`Render failed (${res.status})`);
fs.writeFileSync(outputFile, Buffer.from(await res.arrayBuffer()));
return outputFile;
}
generateOgImage({
title: 'Build Faster with RenderPix',
description: 'HTML to image in one API call. No puppeteer required.',
domain: 'renderpix.dev',
}).then(f => console.log('Saved:', f));
04 โ Error handling
Handle API errors gracefully
error-handling.js
async function renderSafe(html) {
let res;
try {
res = await fetch('https://renderpix.dev/v1/render', {
method: 'POST',
headers: { 'X-API-Key': 'rpx_your_api_key', 'Content-Type': 'application/json' },
body: JSON.stringify({ html, width: 1200, height: 630 }),
});
} catch (networkErr) {
console.error('Network error:', networkErr.message);
return null;
}
if (!res.ok) {
const body = await res.json().catch(() => ({}));
switch (res.status) {
case 401: throw new Error('Invalid API key');
case 429: throw new Error('Rate limit exceeded');
case 422: throw new Error(`Invalid request: ${body.message}`);
default: throw new Error(`Render failed (${res.status}): ${body.message}`);
}
}
return Buffer.from(await res.arrayBuffer());
}
Python
Uses the
requests library โ works with Django, Flask, FastAPI01 โ Authentication
Add the API key header
auth.py
import requests
response = requests.post(
'https://renderpix.dev/v1/render',
headers={'X-API-Key': 'rpx_your_api_key'},
json={'html': '<h1>Hello</h1>', 'width': 1200, 'height': 630},
)
02 โ Basic usage
Render HTML to PNG
render.py
import requests
def render_html(html: str, output_file: str = 'output.png') -> None:
response = requests.post(
'https://renderpix.dev/v1/render',
headers={'X-API-Key': 'rpx_your_api_key'},
json={'html': html, 'width': 1200, 'height': 630, 'format': 'png'},
)
response.raise_for_status()
with open(output_file, 'wb') as f:
f.write(response.content)
render_html('<h1 style="font-family:sans-serif">Hello, RenderPix!</h1>')
03 โ Real-world
OG image generator
og_image.py
import requests
def generate_og_image(title: str, description: str, domain: str, output_file: str = 'og.png') -> str:
html = f"""<!DOCTYPE html><html><head><meta charset="UTF-8">
<style>
* {{ margin:0; padding:0; box-sizing:border-box; }}
body {{ width:1200px; height:630px; padding:80px;
font-family:-apple-system,sans-serif;
background:linear-gradient(135deg,#0f172a,#1e293b);
display:flex; align-items:center; }}
.card {{ display:flex; flex-direction:column; gap:24px; }}
.domain {{ font-size:20px; color:#38bdf8; text-transform:uppercase; }}
h1 {{ font-size:72px; font-weight:800; color:#f1f5f9; line-height:1.1; }}
p {{ font-size:28px; color:#94a3b8; }}
</style></head>
<body><div class="card">
<div class="domain">{domain}</div>
<h1>{title}</h1><p>{description}</p>
</div></body></html>"""
response = requests.post(
'https://renderpix.dev/v1/render',
headers={'X-API-Key': 'rpx_your_api_key'},
json={'html': html, 'width': 1200, 'height': 630, 'format': 'png'},
)
response.raise_for_status()
with open(output_file, 'wb') as f:
f.write(response.content)
return output_file
file = generate_og_image('Build Faster with RenderPix', 'HTML to image in one API call.', 'renderpix.dev')
print(f'OG image saved: {file}')
04 โ Error handling
Handle API errors gracefully
error_handling.py
import requests
from requests.exceptions import ConnectionError, Timeout
def render_safe(html: str) -> bytes | None:
try:
response = requests.post(
'https://renderpix.dev/v1/render',
headers={'X-API-Key': 'rpx_your_api_key'},
json={'html': html, 'width': 1200, 'height': 630},
timeout=30,
)
except (ConnectionError, Timeout) as e:
print(f'Network error: {e}')
return None
if response.status_code == 401:
raise ValueError('Invalid API key')
if response.status_code == 429:
raise RuntimeError('Rate limit exceeded')
if response.status_code == 422:
raise ValueError(f"Invalid request: {response.json().get('message')}")
response.raise_for_status()
return response.content
PHP
Uses the built-in cURL extension โ works with Laravel, Symfony, WordPress
01 โ Authentication
Add the API key header
auth.php
<?php
$ch = curl_init('https://renderpix.dev/v1/render');
curl_setopt($ch, CURLOPT_HTTPHEADER, [
'X-API-Key: rpx_your_api_key',
'Content-Type: application/json',
]);
02 โ Basic usage
Render HTML to PNG
render.php
<?php
function renderHtml(string $html, string $outputFile = 'output.png'): void
{
$payload = json_encode(['html' => $html, 'width' => 1200, 'height' => 630, 'format' => 'png']);
$ch = curl_init('https://renderpix.dev/v1/render');
curl_setopt_array($ch, [
CURLOPT_POST => true,
CURLOPT_POSTFIELDS => $payload,
CURLOPT_RETURNTRANSFER => true,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTPHEADER => [
'X-API-Key: rpx_your_api_key',
'Content-Type: application/json',
],
]);
$body = curl_exec($ch);
$status = curl_getinfo($ch, CURLINFO_HTTP_CODE);
curl_close($ch);
if ($status !== 200) {
$error = json_decode($body, true);
throw new RuntimeException("RenderPix error {$status}: " . ($error['message'] ?? 'unknown'));
}
file_put_contents($outputFile, $body);
}
renderHtml('<h1 style="font-family:sans-serif">Hello, RenderPix!</h1>');
03 โ Real-world
OG image generator
og_image.php
<?php
function generateOgImage(string $title, string $description, string $domain): string
{
$html = "<!DOCTYPE html><html><head><meta charset='UTF-8'>"
. "<style>*{margin:0;padding:0;box-sizing:border-box}"
. "body{width:1200px;height:630px;padding:80px;font-family:-apple-system,sans-serif;"
. "background:linear-gradient(135deg,#0f172a,#1e293b);display:flex;align-items:center}"
. ".card{display:flex;flex-direction:column;gap:24px}"
. ".domain{font-size:20px;color:#38bdf8;text-transform:uppercase}"
. "h1{font-size:72px;font-weight:800;color:#f1f5f9;line-height:1.1}"
. "p{font-size:28px;color:#94a3b8}</style></head>"
. "<body><div class='card'>"
. "<div class='domain'>{$domain}</div>"
. "<h1>{$title}</h1><p>{$description}</p>"
. "</div></body></html>";
$ch = curl_init('https://renderpix.dev/v1/render');
curl_setopt_array($ch, [
CURLOPT_POST => true,
CURLOPT_POSTFIELDS => json_encode(['html' => $html, 'width' => 1200, 'height' => 630]),
CURLOPT_RETURNTRANSFER => true,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTPHEADER => ['X-API-Key: rpx_your_api_key', 'Content-Type: application/json'],
]);
$body = curl_exec($ch);
$status = curl_getinfo($ch, CURLINFO_HTTP_CODE);
curl_close($ch);
if ($status !== 200) throw new RuntimeException("Render failed ({$status})");
file_put_contents('og.png', $body);
return 'og.png';
}
echo generateOgImage('Build Faster with RenderPix', 'HTML to image in one API call.', 'renderpix.dev');
04 โ Error handling
Handle API errors gracefully
error_handling.php
<?php
function renderSafe(string $html): ?string
{
$ch = curl_init('https://renderpix.dev/v1/render');
curl_setopt_array($ch, [
CURLOPT_POST => true,
CURLOPT_POSTFIELDS => json_encode(['html' => $html, 'width' => 1200, 'height' => 630]),
CURLOPT_RETURNTRANSFER => true,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTPHEADER => ['X-API-Key: rpx_your_api_key', 'Content-Type: application/json'],
]);
$body = curl_exec($ch);
$status = curl_getinfo($ch, CURLINFO_HTTP_CODE);
$curlErr = curl_error($ch);
curl_close($ch);
if ($curlErr) { error_log("Network error: {$curlErr}"); return null; }
$error = json_decode($body, true) ?? [];
return match ($status) {
200 => $body,
401 => throw new RuntimeException('Invalid API key'),
429 => throw new RuntimeException('Rate limit exceeded'),
422 => throw new InvalidArgumentException('Invalid request: ' . ($error['message'] ?? '')),
default => throw new RuntimeException("Render failed ({$status})"),
};
}
Ruby
Uses the standard library
net/http โ works with Rails, Sinatra01 โ Authentication
Add the API key header
auth.rb
require 'net/http'
require 'json'
uri = URI('https://renderpix.dev/v1/render')
req = Net::HTTP::Post.new(uri.path)
req['X-API-Key'] = 'rpx_your_api_key'
req['Content-Type'] = 'application/json'
req.body = JSON.generate(html: '<h1>Hello</h1>', width: 1200, height: 630)
02 โ Basic usage
Render HTML to PNG
render.rb
require 'net/http'
require 'json'
def render_html(html, output_file: 'output.png')
uri = URI('https://renderpix.dev/v1/render')
http = Net::HTTP.new(uri.host, uri.port)
http.use_ssl = true
http.read_timeout = 30
req = Net::HTTP::Post.new(uri.path)
req['X-API-Key'] = 'rpx_your_api_key'
req['Content-Type'] = 'application/json'
req.body = JSON.generate(html: html, width: 1200, height: 630, format: 'png')
res = http.request(req)
unless res.code == '200'
error = JSON.parse(res.body) rescue {}
raise "RenderPix error #{res.code}: #{error['message'] || res.message}"
end
File.binwrite(output_file, res.body)
end
render_html('<h1 style="font-family:sans-serif">Hello, RenderPix!</h1>')
03 โ Real-world
OG image generator
og_image.rb
require 'net/http'
require 'json'
def generate_og_image(title:, description:, domain:, output_file: 'og.png')
html = <<~HTML
<!DOCTYPE html><html><head><meta charset="UTF-8">
<style>
* { margin:0; padding:0; box-sizing:border-box; }
body { width:1200px; height:630px; padding:80px;
font-family:-apple-system,sans-serif;
background:linear-gradient(135deg,#0f172a,#1e293b);
display:flex; align-items:center; }
.card { display:flex; flex-direction:column; gap:24px; }
.domain { font-size:20px; color:#38bdf8; text-transform:uppercase; }
h1 { font-size:72px; font-weight:800; color:#f1f5f9; line-height:1.1; }
p { font-size:28px; color:#94a3b8; }
</style></head>
<body><div class="card">
<div class="domain">#{domain}</div>
<h1>#{title}</h1><p>#{description}</p>
</div></body></html>
HTML
uri = URI('https://renderpix.dev/v1/render')
http = Net::HTTP.new(uri.host, uri.port)
http.use_ssl = true
req = Net::HTTP::Post.new(uri.path)
req['X-API-Key'] = 'rpx_your_api_key'
req['Content-Type'] = 'application/json'
req.body = JSON.generate(html: html, width: 1200, height: 630, format: 'png')
res = http.request(req)
raise "Render failed (#{res.code})" unless res.code == '200'
File.binwrite(output_file, res.body)
output_file
end
file = generate_og_image(title: 'Build Faster', description: 'One API call.', domain: 'renderpix.dev')
puts "Saved: #{file}"
04 โ Error handling
Handle API errors gracefully
error_handling.rb
def render_safe(html)
uri = URI('https://renderpix.dev/v1/render')
http = Net::HTTP.new(uri.host, uri.port)
http.use_ssl = true
http.open_timeout = 10
http.read_timeout = 30
req = Net::HTTP::Post.new(uri.path)
req['X-API-Key'] = 'rpx_your_api_key'
req['Content-Type'] = 'application/json'
req.body = JSON.generate(html: html, width: 1200, height: 630)
begin
res = http.request(req)
rescue Net::OpenTimeout, Net::ReadTimeout => e
warn "Timeout: #{e.message}"; return nil
rescue SocketError => e
warn "Network error: #{e.message}"; return nil
end
error = JSON.parse(res.body) rescue {}
case res.code
when '200' then res.body
when '401' then raise 'Invalid API key'
when '429' then raise 'Rate limit exceeded'
when '422' then raise "Invalid request: #{error['message']}"
else raise "Render failed (#{res.code})"
end
end
cURL
Shell scripts, CI/CD pipelines, GitHub Actions
01 โ Authentication
Add the API key header
auth.sh
curl -X POST https://renderpix.dev/v1/render \
-H "X-API-Key: rpx_your_api_key" \
-H "Content-Type: application/json" \
-d '{"html":"<h1>Hello</h1>","width":1200,"height":630}'
02 โ Basic usage
Render HTML to PNG
render.sh
curl -X POST https://renderpix.dev/v1/render \
-H "X-API-Key: rpx_your_api_key" \
-H "Content-Type: application/json" \
-d '{"html":"<h1 style=\"font-family:sans-serif\">Hello, RenderPix!</h1>","width":1200,"height":630,"format":"png"}' \
-o output.png
03 โ Real-world
OG image generator
og-image.sh
#!/bin/bash
API_KEY="rpx_your_api_key"
HTML='<!DOCTYPE html><html><head><meta charset="UTF-8"><style>
* { margin:0; padding:0; box-sizing:border-box; }
body { width:1200px; height:630px; padding:80px; font-family:-apple-system,sans-serif;
background:linear-gradient(135deg,#0f172a,#1e293b);
display:flex; align-items:center; }
.card { display:flex; flex-direction:column; gap:24px; }
.domain { font-size:20px; color:#38bdf8; text-transform:uppercase; }
h1 { font-size:72px; font-weight:800; color:#f1f5f9; line-height:1.1; }
p { font-size:28px; color:#94a3b8; }
</style></head><body>
<div class="card">
<div class="domain">renderpix.dev</div>
<h1>Build Faster with RenderPix</h1>
<p>HTML to image in one API call.</p>
</div></body></html>'
jq -n --arg html "$HTML" '{html:$html,width:1200,height:630,format:"png"}' \
| curl -s -X POST https://renderpix.dev/v1/render \
-H "X-API-Key: $API_KEY" \
-H "Content-Type: application/json" \
-d @- -o og.png
echo "OG image saved: og.png"
04 โ Error handling
Check status codes in shell
error-handling.sh
#!/bin/bash
API_KEY="rpx_your_api_key"
STATUS=$(curl -s -X POST https://renderpix.dev/v1/render \
-H "X-API-Key: $API_KEY" \
-H "Content-Type: application/json" \
-d '{"html":"<h1>Hello</h1>","width":1200,"height":630}' \
-o output.png \
-w "%{http_code}")
case "$STATUS" in
200) echo "Success โ saved to output.png" ;;
401) echo "Error: Invalid API key"; exit 1 ;;
429) echo "Error: Rate limit exceeded"; exit 1 ;;
422) echo "Error: Invalid request โ $(cat output.png)"; exit 1 ;;
*) echo "Error: HTTP $STATUS โ $(cat output.png)"; exit 1 ;;
esac
OG Images
Generate 1200×630 social cards for blog posts, products, and more
Node.js
Dynamic OG image from URL params
Express / Next.js pattern: receive title + domain as query params, render, return image with cache headers.
og-route.js
// Express โ GET /og?title=My+Post&domain=myblog.com
app.get('/og', async (req, res) => {
const { title = 'Untitled', domain = '', description = '' } = req.query;
const html = `<!DOCTYPE html><html><head><meta charset="UTF-8">
<style>
* { margin:0; padding:0; box-sizing:border-box; }
body { width:1200px; height:630px; padding:80px;
font-family:-apple-system,BlinkMacSystemFont,'Segoe UI',sans-serif;
background:linear-gradient(135deg,#0f172a 0%,#1e293b 100%);
display:flex; align-items:center; }
.card { display:flex; flex-direction:column; gap:20px; width:100%; }
.domain { font-size:18px; font-weight:600; color:#38bdf8;
text-transform:uppercase; letter-spacing:3px; }
h1 { font-size:68px; font-weight:800; color:#f1f5f9;
line-height:1.05; letter-spacing:-2px; }
p { font-size:26px; color:#94a3b8; }
</style></head>
<body><div class="card">
<div class="domain">${domain}</div>
<h1>${title}</h1>
${description ? `<p>${description}</p>` : ''}
</div></body></html>`;
const r = await fetch('https://renderpix.dev/v1/render', {
method: 'POST',
headers: { 'X-API-Key': process.env.RENDERPIX_API_KEY, 'Content-Type': 'application/json' },
body: JSON.stringify({ html, width: 1200, height: 630, format: 'png' }),
});
if (!r.ok) return res.status(500).send('Render failed');
res.set('Content-Type', 'image/png');
res.set('Cache-Control', 'public, max-age=86400, stale-while-revalidate=3600');
r.body.pipe(res);
});
Python
Django view โ serve OG image on the fly
views.py
import requests
from django.http import HttpResponse
def og_image(request):
title = request.GET.get('title', 'Untitled')
domain = request.GET.get('domain', '')
html = f"""<!DOCTYPE html><html><head><meta charset="UTF-8">
<style>
* {{ margin:0; padding:0; box-sizing:border-box; }}
body {{ width:1200px; height:630px; padding:80px;
font-family:-apple-system,sans-serif;
background:linear-gradient(135deg,#0f172a,#1e293b);
display:flex; align-items:center; }}
.card {{ display:flex; flex-direction:column; gap:20px; }}
.domain {{ font-size:18px; font-weight:600; color:#38bdf8; text-transform:uppercase; }}
h1 {{ font-size:68px; font-weight:800; color:#f1f5f9; line-height:1.05; }}
</style></head>
<body><div class="card">
<div class="domain">{domain}</div>
<h1>{title}</h1>
</div></body></html>"""
r = requests.post(
'https://renderpix.dev/v1/render',
headers={{'X-API-Key': settings.RENDERPIX_API_KEY}},
json={{'html': html, 'width': 1200, 'height': 630}},
timeout=30,
)
r.raise_for_status()
return HttpResponse(r.content, content_type='image/png',
headers={{'Cache-Control': 'public, max-age=86400'}})
cURL
One-liner for CI/CD
generate-og.sh
#!/bin/bash
# Run in CI after deploy to refresh the OG image
HTML='<html><body style="margin:0;width:1200px;height:630px;overflow:hidden;
background:linear-gradient(135deg,#0f172a,#1e293b);
font-family:-apple-system,sans-serif;display:flex;align-items:center;padding:80px">
<div style="display:flex;flex-direction:column;gap:16px">
<div style="font-size:18px;color:#38bdf8;text-transform:uppercase;letter-spacing:3px">myblog.com</div>
<h1 style="font-size:68px;font-weight:800;color:#f1f5f9;line-height:1.05;letter-spacing:-2px">My Latest Post</h1>
<p style="font-size:26px;color:#94a3b8">A short description goes here.</p>
</div>
</body></html>'
jq -n --arg html "$HTML" '{html:$html,width:1200,height:630,format:"png"}' \
| curl -s -X POST https://renderpix.dev/v1/render \
-H "X-API-Key: $RENDERPIX_API_KEY" \
-H "Content-Type: application/json" \
-d @- -o public/og.png
echo "OG image saved: public/og.png"
Invoices
Generate pixel-perfect invoice images from HTML templates โ ready for PDF conversion or email
Node.js
Invoice image from order data
Pass order data into an HTML template and render it as a PNG. Width 900px works well for A4-ratio invoices.
generate-invoice.js
const fs = require('fs');
async function generateInvoice({ invoiceNo, date, customer, items, total }) {
const rows = items.map(i => `
<tr>
<td>${i.description}</td>
<td style="text-align:right">${i.qty}</td>
<td style="text-align:right">$${i.unit.toFixed(2)}</td>
<td style="text-align:right">$${(i.qty * i.unit).toFixed(2)}</td>
</tr>`).join('');
const html = `<!DOCTYPE html><html><head><meta charset="UTF-8">
<style>
* { margin:0; padding:0; box-sizing:border-box; }
body { width:900px; font-family:-apple-system,'Segoe UI',sans-serif;
background:#fff; padding:60px; color:#1e293b; }
.header { display:flex; justify-content:space-between; align-items:flex-start;
margin-bottom:48px; padding-bottom:24px; border-bottom:2px solid #e2e8f0; }
.brand { font-size:28px; font-weight:800; color:#0f172a; }
.brand span { color:#22d3ee; }
.meta { text-align:right; font-size:13px; color:#64748b; line-height:1.8; }
.meta strong { color:#0f172a; font-size:15px; }
table { width:100%; border-collapse:collapse; font-size:14px; }
th { padding:10px 12px; background:#f8fafc; text-align:left; font-weight:600;
font-size:12px; text-transform:uppercase; letter-spacing:0.5px; color:#64748b; }
th:not(:first-child) { text-align:right; }
td { padding:12px; border-bottom:1px solid #f1f5f9; }
.total-row td { font-size:16px; font-weight:700; border-bottom:none; padding-top:20px; }
</style></head>
<body>
<div class="header">
<div class="brand">My<span>Company</span></div>
<div class="meta">
<strong>Invoice ${invoiceNo}</strong><br>
Date: ${date}<br>Bill to: ${customer}
</div>
</div>
<table>
<thead><tr>
<th>Description</th><th>Qty</th><th>Unit price</th><th>Amount</th>
</tr></thead>
<tbody>${rows}</tbody>
<tfoot><tr class="total-row">
<td colspan="3" style="text-align:right">Total</td>
<td style="text-align:right">$${total.toFixed(2)}</td>
</tr></tfoot>
</table>
</body></html>`;
const res = await fetch('https://renderpix.dev/v1/render', {
method: 'POST',
headers: { 'X-API-Key': process.env.RENDERPIX_API_KEY, 'Content-Type': 'application/json' },
body: JSON.stringify({ html, width: 900, height: 700, format: 'png' }),
});
if (!res.ok) throw new Error(`Render failed (${res.status})`);
const buffer = Buffer.from(await res.arrayBuffer());
fs.writeFileSync(`invoice-${invoiceNo}.png`, buffer);
return `invoice-${invoiceNo}.png`;
}
generateInvoice({
invoiceNo: 'INV-0042',
date: 'April 17, 2026',
customer: 'Acme Corp',
items: [
{ description: 'Pro Plan (April)', qty: 1, unit: 29 },
{ description: 'Extra renders', qty: 2, unit: 9 },
],
total: 47,
}).then(f => console.log('Invoice saved:', f));
Python
Batch invoice generation
batch_invoices.py
import requests
def render_invoice(invoice_no: str, customer: str, amount: float) -> bytes:
html = f"""<!DOCTYPE html><html><head><meta charset="UTF-8">
<style>
* {{ margin:0; padding:0; box-sizing:border-box; }}
body {{ width:900px; font-family:-apple-system,sans-serif;
background:#fff; padding:60px; color:#1e293b; }}
.header {{ display:flex; justify-content:space-between;
margin-bottom:48px; padding-bottom:24px; border-bottom:2px solid #e2e8f0; }}
.brand {{ font-size:28px; font-weight:800; }}
.brand span {{ color:#22d3ee; }}
.info {{ text-align:right; font-size:14px; color:#64748b; line-height:1.8; }}
.amount {{ font-size:48px; font-weight:800; color:#0f172a; margin-top:40px; }}
.label {{ font-size:13px; color:#94a3b8; text-transform:uppercase; letter-spacing:1px; }}
</style></head>
<body>
<div class="header">
<div class="brand">My<span>Company</span></div>
<div class="info">Invoice {invoice_no}<br>Bill to: {customer}</div>
</div>
<div class="label">Amount due</div>
<div class="amount">${amount:,.2f}</div>
</body></html>"""
r = requests.post(
'https://renderpix.dev/v1/render',
headers={'X-API-Key': 'rpx_your_api_key'},
json={'html': html, 'width': 900, 'height': 400, 'format': 'png'},
timeout=30,
)
r.raise_for_status()
return r.content
# Batch render
orders = [
('INV-001', 'Alice Corp', 129.00),
('INV-002', 'Bob Ltd', 47.50),
('INV-003', 'Carol Inc', 299.99),
]
for inv_no, customer, amount in orders:
image = render_invoice(inv_no, customer, amount)
with open(f'{inv_no}.png', 'wb') as f:
f.write(image)
print(f'Saved {inv_no}.png')
Certificates
Generate personalized completion certificates, badges, and awards
Node.js
Course completion certificate
Generate a unique certificate per user โ no image editing tools, no Photoshop templates.
generate-cert.js
const fs = require('fs');
async function generateCertificate({ recipientName, courseName, completionDate, certId }) {
const html = `<!DOCTYPE html><html><head><meta charset="UTF-8">
<link href="https://fonts.googleapis.com/css2?family=Playfair+Display:ital,wght@0,700;1,400&family=Inter:wght@400;600&display=swap" rel="stylesheet">
<style>
* { margin:0; padding:0; box-sizing:border-box; }
body { width:1200px; height:850px; overflow:hidden;
background:linear-gradient(135deg,#0f172a 0%,#1e1b4b 100%);
display:flex; align-items:center; justify-content:center; }
.cert { width:1040px; border:2px solid rgba(167,139,250,0.4);
border-radius:24px; padding:72px 80px; text-align:center;
background:rgba(15,23,42,0.8); }
.badge { display:inline-block; margin-bottom:32px; padding:6px 20px;
border-radius:20px; font-family:'Inter',sans-serif; font-size:11px;
font-weight:600; color:#a78bfa; letter-spacing:2px; text-transform:uppercase;
border:1px solid rgba(167,139,250,0.3); background:rgba(139,92,246,0.1); }
.title { font-family:'Playfair Display',serif; font-size:20px; font-style:italic;
color:#94a3b8; margin-bottom:12px; }
.name { font-family:'Playfair Display',serif; font-size:64px; font-weight:700;
color:#f1f5f9; letter-spacing:-1px; margin-bottom:24px; }
.desc { font-family:'Inter',sans-serif; font-size:16px; color:#64748b; margin-bottom:8px; }
.course { font-family:'Inter',sans-serif; font-size:22px; font-weight:600;
color:#c4b5fd; margin-bottom:48px; }
.footer { display:flex; justify-content:space-between; padding-top:40px;
border-top:1px solid rgba(255,255,255,0.06);
font-family:'Inter',sans-serif; font-size:12px; color:#475569; }
</style></head>
<body><div class="cert">
<div class="badge">✦ Certificate of Completion</div>
<div class="title">This certifies that</div>
<div class="name">${recipientName}</div>
<div class="desc">has successfully completed</div>
<div class="course">${courseName}</div>
<div class="footer">
<span>Course Director</span>
<span>${completionDate}</span>
<span>ID: ${certId}</span>
</div>
</div></body></html>`;
const res = await fetch('https://renderpix.dev/v1/render', {
method: 'POST',
headers: { 'X-API-Key': process.env.RENDERPIX_API_KEY, 'Content-Type': 'application/json' },
body: JSON.stringify({ html, width: 1200, height: 850, format: 'png' }),
});
if (!res.ok) throw new Error(`Render failed (${res.status})`);
const buffer = Buffer.from(await res.arrayBuffer());
fs.writeFileSync(`cert-${certId}.png`, buffer);
return `cert-${certId}.png`;
}
generateCertificate({
recipientName: 'Jane Smith',
courseName: 'Advanced JavaScript & Node.js',
completionDate: 'April 17, 2026',
certId: 'CERT-2026-0142',
}).then(f => console.log('Certificate saved:', f));
Python
Batch certificate generation
batch_certs.py
import requests
def render_certificate(name: str, course: str, date: str, cert_id: str) -> bytes:
html = f"""<!DOCTYPE html><html><head><meta charset="UTF-8">
<style>
* {{ margin:0; padding:0; box-sizing:border-box; }}
body {{ width:1200px; height:850px; overflow:hidden;
font-family:-apple-system,sans-serif;
background:linear-gradient(135deg,#0f172a,#1e1b4b);
display:flex; align-items:center; justify-content:center; }}
.cert {{ width:1040px; border:2px solid rgba(167,139,250,.4);
border-radius:24px; padding:72px 80px; text-align:center;
background:rgba(15,23,42,.8); }}
.badge {{ display:inline-block; margin-bottom:32px; padding:6px 20px;
border-radius:20px; font-size:11px; font-weight:600; color:#a78bfa;
letter-spacing:2px; text-transform:uppercase;
border:1px solid rgba(167,139,250,.3); }}
.label {{ font-size:18px; color:#94a3b8; margin-bottom:12px; }}
.name {{ font-size:60px; font-weight:700; color:#f1f5f9;
letter-spacing:-1px; margin-bottom:24px; }}
.course {{ font-size:22px; font-weight:600; color:#c4b5fd; margin-bottom:48px; }}
.meta {{ font-size:12px; color:#475569; }}
</style></head>
<body><div class="cert">
<div class="badge">Certificate of Completion</div>
<div class="label">This certifies that</div>
<div class="name">{name}</div>
<div class="course">{course}</div>
<div class="meta">{date} · {cert_id}</div>
</div></body></html>"""
r = requests.post(
'https://renderpix.dev/v1/render',
headers={'X-API-Key': 'rpx_your_api_key'},
json={'html': html, 'width': 1200, 'height': 850, 'format': 'png'},
timeout=30,
)
r.raise_for_status()
return r.content
# Batch render for course graduates
graduates = [
('Alice Johnson', 'CERT-001'),
('Bob Williams', 'CERT-002'),
('Carol Martinez', 'CERT-003'),
]
for name, cert_id in graduates:
image = render_certificate(
name=name, course='Advanced Python Development',
date='April 17, 2026', cert_id=cert_id,
)
with open(f'{cert_id}.png', 'wb') as f:
f.write(image)
print(f'Saved {cert_id}.png')