A service for generating PDFs from URLs using Playwright. Supports synchronous generation (direct response) and asynchronous generation via RabbitMQ queue with webhook delivery.
- Node.js >= 18
- RabbitMQ (for asynchronous generation via queue)
- Playwright browsers (installed automatically, or run
npx playwright install chromium)
git clone <repo-url>
cd HTMLforPDF
npm installCreate a .env file in the project root:
PORT=3000
RABBITMQ_URL=amqp://localhost
PDF_QUEUE_NAME=html_for_pdf_job
WORKER_CONCURRENCY=1| Variable | Default | Description |
|---|---|---|
PORT |
3000 |
HTTP server port |
RABBITMQ_URL |
amqp://localhost |
RabbitMQ connection URL |
PDF_QUEUE_NAME |
html_for_pdf_job |
RabbitMQ queue name |
WORKER_CONCURRENCY |
1 |
Number of jobs processed in parallel |
npm run dev # Development server (with hot-reload)
npm run dev:worker # Development worker (with hot-reload)
npm start # Production server
npm run worker # Production worker
npm run lint # Lint
npm run lint:fix # Lint with auto-fix
npm run format # Format code with Prettier
npm test # TestsBase path: /api/pdfs
Generates a PDF synchronously and returns the file in the response.
{
"url": "https://example.com",
"options": {
"format": "A4",
"landscape": true,
"margin": { "top": "2cm", "bottom": "2cm" }
}
}| Field | Type | Required | Description |
|---|---|---|---|
url |
string |
✅ | URL of the page to convert to PDF |
options |
object |
❌ | PDF generation options (see table below) |
| Status | Content-Type | Description |
|---|---|---|
200 |
application/pdf |
Generated PDF file |
422 |
application/json |
Validation error (invalid fields) |
500 |
application/json |
Internal error |
422 error example:
{
"errors": [
{ "field": "url", "message": "The url field must be a valid URL", "rule": "url" }
]
}Queues PDF generation asynchronously. The PDF will be generated by the worker and sent to the provided webhook URL.
{
"url": "https://example.com",
"webhookUrl": "https://my-server.com/webhook/pdf",
"options": {
"format": "A3",
"printBackground": true
}
}| Field | Type | Required | Description |
|---|---|---|---|
url |
string |
✅ | URL of the page to convert to PDF |
webhookUrl |
string |
✅ | URL that will receive the generated PDF via POST |
options |
object |
❌ | PDF generation options (see table below) |
| Status | Description |
|---|---|
202 |
{ "status": "queued" } — Job queued successfully |
422 |
Validation error |
500 |
Internal error |
All fields below are optional. Default values applied: format: "A4" and printBackground: true.
| Field | Type | Description |
|---|---|---|
scale |
number |
Rendering scale (between 0.1 and 2, default: 1) |
displayHeaderFooter |
boolean |
Display header and footer in the PDF |
headerTemplate |
string |
HTML template for the header |
footerTemplate |
string |
HTML template for the footer |
printBackground |
boolean |
Print background graphics (default: true) |
landscape |
boolean |
Landscape orientation |
pageRanges |
string |
Page ranges (e.g., "1-5, 8") |
format |
string |
Paper format (default: "A4") |
width |
string | number |
Custom width (e.g., "8.5in", 100) |
height |
string | number |
Custom height (e.g., "11in", 200) |
margin |
object |
Margins: { top, right, bottom, left } (e.g., "1cm", "10px") |
preferCSSPageSize |
boolean |
Use page size defined via CSS @page |
tagged |
boolean |
Generate PDF with accessibility tags |
outline |
boolean |
Generate outline/bookmarks from headings |
Accepted format values: Letter, Legal, Tabloid, Ledger, A0, A1, A2, A3, A4, A5, A6
Accepted units for width, height, and margin: px, in, cm, mm
Available classes for headerTemplate and footerTemplate:
| Class | Injected value |
|---|---|
date |
Formatted date |
title |
Document title |
url |
Document URL |
pageNumber |
Current page number |
totalPages |
Total number of pages |
When a job is processed by the worker (via POST /api/pdfs/jobs), the generated PDF is sent via POST to the provided webhookUrl.
- Method:
POST - Content-Type:
multipart/form-data - File field:
file - Filename:
file.pdf - MIME type:
application/pdf
curl -X POST https://my-server.com/webhook/pdf \
-F "file=@file.pdf;type=application/pdf"Your server should accept a POST request with multipart/form-data containing a file field with the PDF binary. Example using Express:
import multer from 'multer';
const upload = multer({ dest: 'uploads/' });
app.post('/webhook/pdf', upload.single('file'), (req, res) => {
console.log('PDF received:', req.file);
res.sendStatus(200);
});Note: The worker considers the delivery successful when the webhook returns an HTTP
2xxstatus. Any other status will be logged as an error.
ISC — Edvaldo Lima