Crashes, No Sound, or Screen Glitches?
Random freezes, missing sound and display glitches usually trace back to one bad driver. Find and replace yours safely.Free scan · under a minuteWindows Errors? Fix Them Before They Spread
Repair common Windows errors and clear accumulated junk for a smoother, more stable PC - no reinstall needed.Free scan · no reinstallHow you generate a PDF in an Express application depends on what the PDF represents. Use PDFKit when your data should become a document that you lay out with drawing and text primitives. Use Puppeteer when an existing HTML page and its CSS are the source of truth. Use pdf-lib when you need to create, load, edit, merge, or save PDF documents in JavaScript.
This guide shows a complete Express route with PDFKit, then covers HTML-to-PDF with Puppeteer, document editing with pdf-lib, response headers, security, errors, deployment checks, and an alternative that avoids browser setup.
Choose the PDF generation model first
| Requirement | Starting point | Why it fits | Trade-offs |
|---|---|---|---|
| Invoices, certificates, reports, or other structured data | PDFKit | PDFDocument is a readable Node.js stream that can pipe directly to an HTTP response. |
You control layout, pagination, fonts, and images yourself. |
| Print an existing HTML/CSS view | Puppeteer | Chromium renders the page and page.pdf() prints it using print media by default. |
You must operate a browser process and test fonts, page breaks, timeouts, and the target host. |
| Create, modify, or assemble PDF files | pdf-lib | Its JavaScript API creates documents, adds pages, draws content, embeds pages, and saves bytes. | Check that its editing APIs cover the structure of the PDFs you receive. |
There is no documented universal speed, memory, page-count, or fidelity winner. Compare the source format, browser-runtime requirements, streaming versus buffering, and the amount of existing PDF content you must preserve.
Prerequisites and version alignment
Use a current supported Node.js runtime and install package versions that you can reproduce with a lockfile. Express displayed version 5.2.1 on its homepage when checked, while the response reference used below is the Express 4.x API reference. The routing and response concepts apply to both, but verify the exact APIs against the Express major version installed in your project. Puppeteer’s guide search result showed 25.12.0; package versions and browser requirements can change.
What’s actually slowing this PC down?
Pick the symptom - the matching free tool is one click away.
#1 Best Overall
- CRISP CLARITY: This 23.8″ Philips V line monitor delivers crisp Full HD 1920x1080 visuals. Enjoy movies, shows and videos with remarkable detail
- INCREDIBLE CONTRAST: The VA panel produces brighter whites and deeper blacks. You get true-to-life images and more gradients with 16.7 million colors
- THE PERFECT VIEW: The 178/178 degree extra wide viewing angle prevents the shifting of colors when viewed from an offset angle, so you always get consistent colors
- WORK SEAMLESSLY: This sleek monitor is virtually bezel-free on three sides, so the screen looks even bigger for the viewer. This minimalistic design also allows for seamless multi-monitor setups that enhance your workflow and boost productivity
- A BETTER READING EXPERIENCE: For busy office workers, EasyRead mode provides a more paper-like experience for when viewing lengthy documents
npm install express pdfkit
Use ES modules if your package.json contains "type": "module". For CommonJS, replace the imports with require() equivalents supported by your installed package versions.
Return a generated PDF from an Express route with PDFKit
Express route methods such as app.get() receive a request and response. A handler must complete that response cycle; a route that neither sends a response nor passes control onward can leave the request hanging. PDFKit documents are readable streams: pipe one to res, write content, and call doc.end() to finalize it.
import express from 'express';
import PDFDocument from 'pdfkit';
const app = express();
const port = process.env.PORT || 3000;
app.get('/report.pdf', (req, res, next) => {
const doc = new PDFDocument({
size: 'A4',
margin: 50,
info: {
Title: 'Example report',
Author: 'Example application'
}
});
res.setHeader('Content-Type', 'application/pdf');
res.setHeader('Content-Disposition', 'inline; filename="report.pdf"');
doc.on('error', (error) => {
if (!res.headersSent) next(error);
else res.destroy(error);
});
res.on('close', () => {
// The client disconnected. Stop producing more output if appropriate.
if (!res.writableEnded) doc.destroy();
});
doc.pipe(res);
doc.fontSize(20).text('Example report', { align: 'center' });
doc.moveDown();
doc.fontSize(12).text(`Generated at ${new Date().toISOString()}`);
doc.moveDown();
doc.text('This paragraph is generated from application data.');
doc.addPage();
doc.fontSize(16).text('Second page');
doc.fontSize(12).text('PDFKit adds a first page automatically; addPage() creates another.');
doc.end();
});
app.use((error, req, res, next) => {
if (res.headersSent) return next(error);
res.status(500).json({ error: 'Unable to generate PDF' });
});
app.listen(port, () => console.log(`Listening on ${port}`));
Run the server and request http://localhost:3000/report.pdf. The browser can display the file because the disposition is inline. Change it to attachment; filename="report.pdf" when you want a download prompt. Keep the filename fixed or sanitize every generated value; never place raw user input into a filesystem path or header.
Rank #2
- CRISP CLARITY: This 22 inch class (21.5″ viewable) Philips V line monitor delivers crisp Full HD 1920x1080 visuals. Enjoy movies, shows and videos with remarkable detail
- 100HZ FAST REFRESH RATE: 100Hz brings your favorite movies and video games to life. Stream, binge, and play effortlessly
- SMOOTH ACTION WITH ADAPTIVE-SYNC: Adaptive-Sync technology ensures fluid action sequences and rapid response time. Every frame will be rendered smoothly with crystal clarity and without stutter
- INCREDIBLE CONTRAST: The VA panel produces brighter whites and deeper blacks. You get true-to-life images and more gradients with 16.7 million colors
- THE PERFECT VIEW: The 178/178 degree extra wide viewing angle prevents the shifting of colors when viewed from an offset angle, so you always get consistent colors
Layout, pages, and assets
- Call
doc.addPage()when you need another page. Plan for long text, table rows, images, and page breaks rather than assuming one page. - Register and use fonts deliberately if recipients need consistent typography. Test embedded images and font files in the same runtime and container used in production.
- PDFKit does not save a file automatically.
pipe()chooses the destination, andend()completes the stream. - If you are writing to disk instead of the response, use a controlled server directory and expose files only through authorization-aware routes.
How to convert HTML to PDF with Puppeteer
Puppeteer is the better starting point when your invoice, report, or page already exists as HTML and CSS. The handler should create or reuse a browser, load the page, wait for the content you need, call page.pdf(), send the returned bytes, and close page/browser resources in a finally path.
Quick wins for a faster PC:
Scan for outdated or missing drivers - takes under a minuteDriver Scan →Repair Windows errors before they cause bigger problemsFix Now →Fix the driver behind crashes, sound loss and screen glitchesFind Drivers →import express from 'express';
import puppeteer from 'puppeteer';
const app = express();
app.get('/invoice.pdf', async (req, res, next) => {
let browser;
try {
browser = await puppeteer.launch();
const page = await browser.newPage();
await page.setContent(`<!doctype html>
<html><head><style>
@page { size: A4; margin: 18mm; }
body { font-family: Arial, sans-serif; }
h1 { color: #123b63; }
@media print { .screen-only { display: none; } }
</style></head>
<body><h1>Invoice</h1><p>Generated from HTML and CSS.</p></body></html>`,
{ waitUntil: 'networkidle0' }
);
await page.evaluate(() => document.fonts.ready);
const pdf = await page.pdf({
format: 'A4',
printBackground: true,
preferCSSPageSize: true
});
res.type('application/pdf');
res.setHeader('Content-Disposition', 'inline; filename="invoice.pdf"');
res.send(Buffer.from(pdf));
} catch (error) {
next(error);
} finally {
if (browser) await browser.close();
}
});
app.listen(3000);
Page.pdf() uses print media by default and returns a Promise<Uint8Array>. If the design intentionally uses screen styles, call await page.emulateMediaType('screen') before generating the PDF. For exact colors, review Chromium’s print-color behavior and the -webkit-print-color-adjust CSS property. Puppeteer’s documented example waits for navigation, creates the PDF, and closes the browser; your route should apply the same cleanup principle.
Browser lifecycle and deployment checks
- Confirm that the Puppeteer package can install or locate its compatible browser in your build environment.
- Set navigation and PDF timeouts appropriate to your application, and decide how a slow third-party asset should fail.
- Limit concurrent browser pages according to measurements from your own document and host. No universal concurrency or memory limit is established by the cited documentation.
- Check sandbox settings, fonts, local-file access, and outbound network policy on the deployment platform rather than assuming local development behavior will match.
- Close pages and browsers on success, errors, and client disconnects. A long-lived browser pool can reduce startup work, but it adds capacity and isolation decisions that you must test.
Create or modify PDFs with pdf-lib
Use pdf-lib when the input or output is a PDF document rather than a web page. You can create a document, add a page, draw text, and save bytes; you can also load an existing PDF and modify or embed pages.
Rank #3
- Clear visuals. Fluid motion: A 144Hz refresh rate and 1ms MPRT deliver smooth, tear‑free motion across work, gaming, and streaming for clearer, more fluid viewing.
- Eye comfort: TÜV Rheinland 3‑star* certification reduces harmful blue light while preserving stunning color quality without compromise. *TÜV Rheinland 3-star eye comfort certification.
- Wide viewing angle: Get consistent views across a wide 178° /178° viewing angle.
- In-Plane Switching (IPS): See excellent color accuracy and consistency across wide viewing angles with In-plane Switching (IPS) technology.
- Ultra-thin bezels: Maximize your viewing experience with thin bezels.
import express from 'express';
import { PDFDocument, StandardFonts, rgb } from 'pdf-lib';
const app = express();
app.get('/certificate.pdf', async (req, res, next) => {
try {
const pdfDoc = await PDFDocument.create();
const page = pdfDoc.addPage([595.28, 841.89]); // A4 points
const font = await pdfDoc.embedFont(StandardFonts.Helvetica);
page.drawText('Certificate', {
x: 72, y: 720, size: 28, font, color: rgb(0.05, 0.2, 0.4)
});
page.drawText('Issued by the example application', {
x: 72, y: 675, size: 14, font
});
const bytes = await pdfDoc.save();
res.type('application/pdf');
res.setHeader('Content-Disposition', 'attachment; filename="certificate.pdf"');
res.send(Buffer.from(bytes));
} catch (error) {
next(error);
}
});
app.listen(3000);
For an existing document, read bytes from a controlled upload or storage location, call PDFDocument.load(bytes), perform the documented edits, then call save(). Validate ownership and authorization before loading any user-selected file.
Express response choices and file safety
res.send(Buffer) is convenient for non-streaming output such as pdf-lib bytes or Puppeteer’s returned bytes. A stream such as PDFKit should be piped to the response. Express also provides res.download() and res.sendFile() for filesystem files, but those APIs access the running filesystem. Constrain paths with the documented root option or resolve them against a fixed directory; do not let a query parameter select arbitrary paths.
Recommended Free Tools
- Set
Content-Type: application/pdf(or useres.type('application/pdf')). - Choose
inlinefor browser viewing andattachmentfor downloading. - Use a safe, deterministic filename and quote it correctly.
- Do not send JSON after PDF bytes have started. Check
res.headersSentbefore passing an error to the error middleware. - Authenticate report data and validate query parameters before generating a document.
Common failures and fixes
The request hangs
In an Express route, ensure every branch sends, streams, or calls next(). For PDFKit, confirm both doc.pipe(res) and doc.end() execute. An exception before either call should reach error middleware.
Rank #4
- CURVED FOR ENHANCED ENGAGEMENT: An immersive viewing experience with a curved monitor that wraps more closely around your field of vision; It creates a wider view, enhancing depth perception and minimizing peripheral distraction
- SMOOTH PERFORMANCE FOR SEAMLESS CONTENT: Stay in the action when playing games, watching videos, or working on creative projects; The 100Hz refresh rate reduces lag and motion blur so you don't miss a thing in fast-paced moments¹
- MORE GAMING POWER: Gain the edge with optimizable game settings; Color and image contrast can be adjusted to see scenes more vividly and spot enemies hiding in the dark; Game Mode adjusts any game to fill the screen so you can view every detail²
- KEEP IT EASY ON THE EYES: Care for your eyes and stay comfortable, even during long sessions; Advanced eye comfort technology certified by TÜV reduces eye strain by minimizing blue light and reducing irritating screen flicker²
- INCREASED VERSATILITY: Connect to more; Plug devices straight into your monitor for increased flexibility, making your computing environment even more convenient
The PDF is empty or corrupt
With PDFKit, do not end the document before writing content. With Puppeteer, await page readiness and send the complete bytes only after page.pdf() resolves. With pdf-lib, await save() and convert the resulting bytes to a Node.js Buffer.
CSS looks wrong
Puppeteer prints with print media by default. Move print-specific rules into @media print, set printBackground: true when backgrounds are required, or explicitly emulate screen media. Check @page size, margins, and page-break rules.
Fonts or images are missing
Wait for network resources and fonts, use reachable URLs or embedded assets, and verify that the production container contains the required files. A local browser cache or developer font can hide deployment problems.
Do these 3 things before closing this tab:
1Fix the driver behind crashes, sound loss and screen glitches2Clear out junk files and repair common Windows errors3Scan for outdated or missing drivers - takes under a minuteBest Value
- 【INTEGRATED SPEAKERS】Whether you're at work or in the midst of an intense gaming session, our built-in speakers provide rich and seamless audio, all while keeping your desk clutter-free.
- 【EASY ON THE EYES】 Protect your eyes and enhance your comfort with Blue-Light Shift technology. This feature reduces harmful blue light emissions from your screen, helping to alleviate eye strain during long hours of use and promoting healthier viewing habits.
- 【WIDEN YOUR PERSPECTIVE】Our sleek minimal bezel design ensures undivided attention. The nearly bezel-free display seamlessly connects in a dual monitor arrangement, delivering an unobstructed view that lets you focus on more at once, completely distraction-free.
Chromium fails to launch
Inspect the installed Puppeteer/browser version, operating-system libraries, sandbox policy, and executable path on the host. These are environment-specific checks; do not assume a configuration that works on one provider works everywhere.
A user can read another file
Never concatenate untrusted input into a path. Map an authenticated document identifier to a server-side record, resolve it under a fixed root, and reject traversal or unexpected extensions before calling file-transfer helpers.
Independent reader supportYour contribution helps us test, update, and keep practical guides available for everyone.Or skip the browser setup
If your source is a URL and you want a rendered capture or PDF without managing Chromium in your Express process, ScreenshotNeo provides a website screenshot API and MCP server. A GET request returns a clean PNG, JPEG, WebP, or PDF; see the API documentation for the current output options.
curl -G "https://api.screenshotneo.com/v1/shot" -d access_key=YOUR_API_KEY --data-urlencode url=https://stripe.com -o shot.webp
import requests
r = requests.get("https://api.screenshotneo.com/v1/shot", params={"access_key": "YOUR_API_KEY", "url": "https://stripe.com"}, timeout=90)
r.raise_for_status()
open("shot.webp", "wb").write(r.content)
const q = new URLSearchParams({ access_key: 'YOUR_API_KEY', url: 'https://stripe.com' });
const res = await fetch(`https://api.screenshotneo.com/v1/shot?${q}`);
if (!res.ok) throw new Error(`Screenshot failed: ${res.status}`);
const bytes = Buffer.from(await res.arrayBuffer());
It accepts cookie and consent banners before capture and removes more than 60 known consent platforms, newsletter popups, and chat widgets; each cleanup step can be disabled. Bot checks, CAPTCHAs, blank pages, timeouts, failed loads, and cache hits are not billed, and response headers identify the page verdict and billing result. Its MCP server exposes take_screenshot, get_page_info, and capture_pdf for Claude, Cursor, and other MCP clients. Every plan includes the features; 1,000 shots per month are free with no card, and paid plans start at $5 for 3,000 shots. Create a free ScreenshotNeo account.
Free tools Windows power users keep installed
One-click scans. No signup required.
Operational and cost considerations
- PDFKit streams output, which can avoid holding the entire document in memory, but layout complexity and asset handling still need measurement.
- Puppeteer adds browser startup, page isolation, rendering time, and host-level resource requirements. Measure your own templates and concurrency.
- pdf-lib and Puppeteer examples buffer bytes before
res.send(); impose sensible document and request limits for untrusted input. - Cache only when the underlying data and authorization permit it. Do not cache a personalized PDF under a shared URL.
- Log generation failures, duration, document identifiers, and response status without logging sensitive document contents.
Frequently Asked Questions
Can I generate a PDF without saving it to disk?
Yes. Pipe a PDFKit document to the Express response, or send the bytes returned by Puppeteer or pdf-lib directly with a PDF content type.
Should I use PDFKit or Puppeteer for an invoice?
Use PDFKit when the invoice is structured data that you are willing to lay out in PDF primitives. Use Puppeteer when an HTML invoice already matches the design you need to print.
Can Express return a PDF from a POST request?
Yes. Validate the posted data, generate the document in the handler, and use the same response headers and stream or buffer technique shown for GET routes.
Quick Recap
Product prices and availability are accurate as of the date/time indicated and are subject to change. Any price and availability information displayed on Amazon at the time of purchase will apply.

