What’s actually slowing this PC down?

Pick the symptom - the matching free tool is one click away.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

There are two reliable ways to do this in Node.js: fill an existing interactive PDF (an AcroForm) with pdf-lib, or design a new document with PDFKit. Once you have the PDF bytes or a stream, Nodemailer can send it as an attachment. The example below uses an existing form, then shows a from-scratch report, attachment strategies, validation, and failure recovery.

Choose the right PDF workflow

Requirement Recommended approach Why
You received a PDF template with named fields pdf-lib Loads the AcroForm, finds fields by name, sets values, updates appearances, and saves a completed PDF.
You need a custom report, confirmation, or application summary PDFKit You control page layout, typography, tables, and pagination while writing a new document stream.
The file is modest in size Save to bytes and attach a Buffer Simple and easy to validate before sending.
The file or workload is large Use a file path or readable stream Nodemailer can transfer content incrementally instead of retaining the whole attachment in memory.

These are different jobs. A PDF that merely looks like a form is not necessarily an interactive AcroForm, and a generated report will not automatically contain fields that recipients can edit.

Prepare the Node.js project

  1. Create a project and enable ESM if you want import syntax: npm init -y, then add "type":"module" to package.json.
  2. Install the libraries: npm install pdf-lib pdfkit nodemailer.
  3. Keep the template at a known path, such as template.pdf. Store SMTP host, port, username, password, sender, and recipient in environment variables rather than source code.
  4. Use a mail transport approved by your organization. The libraries do not choose a provider, enforce a quota, or guarantee delivery.

Fill an existing PDF form with pdf-lib

Field names in the code must exactly match names embedded in your template. They are not necessarily the visible labels. A mismatch causes lookup errors, so inspect the source form before deploying.

import fs from 'node:fs/promises';
import { PDFDocument } from 'pdf-lib';
import nodemailer from 'nodemailer';

const templateBytes = await fs.readFile('template.pdf');
const pdfDoc = await PDFDocument.load(templateBytes);
const form = pdfDoc.getForm();

// These names are examples. Replace them with names from your template.
form.getTextField('full_name').setText('Avery Example');
form.getTextField('email').setText('[email protected]');
form.getTextField('summary').setText('Application received on 2026-09-29');
form.getCheckBox('consent').check();
form.getDropdown('country').select('United States');

// Regenerate visible appearances before saving.
form.updateFieldAppearances();
const pdfBytes = await pdfDoc.save();

const transporter = nodemailer.createTransport({
  host: process.env.SMTP_HOST,
  port: Number(process.env.SMTP_PORT || 587),
  secure: process.env.SMTP_SECURE === 'true',
  auth: { user: process.env.SMTP_USER, pass: process.env.SMTP_PASS }
});

await transporter.sendMail({
  from: process.env.MAIL_FROM,
  to: process.env.MAIL_TO,
  subject: 'Completed form',
  text: 'The completed PDF is attached.',
  attachments: [{
    filename: 'completed-form.pdf',
    content: Buffer.from(pdfBytes),
    contentType: 'application/pdf'
  }]
});

console.log('PDF generated and email submitted');

pdf-lib exposes accessors for text fields, checkboxes, dropdowns, option lists, radio groups, and buttons. Use the accessor that matches the actual field type; do not assume every control is text. If a field is optional, decide whether an empty value, an unchecked box, or an omitted field is correct for your business process.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.
#1 Best Overall
PDF Max - Read, Annotate & Edit PDF documents plus Fill out PDF Forms!
  • Desktop class PDF reader and editor for Android
  • Read PDF documents with Mobile-Optimized Text Reflow mode & Text To Speech
  • Annotate like a Pro with unmatched annotating tools
  • Fill out, Stamp & Sign PDF Forms
  • Powerful File Manager features Automatic, Desktop-like syncing with all major cloud services

Find the real field names and types

Before mapping user input, enumerate the form and log only non-sensitive metadata in a development environment:

const fields = form.getFields();
for (const field of fields) {
  console.log(field.constructor.name, field.getName());
}

Do not log applicants’ answers, access tokens, or entire PDF buffers. Confirm that the template is an AcroForm; a scanned image or an XFA-only document may not expose fields through this API.

Appearance and character coverage

A field value and its visual appearance are separate concerns. Call updateFieldAppearances() and open the result in the PDF readers your recipients use. The default form font may not contain every non-Latin character; if your data requires other scripts, embed a suitable font and regenerate appearances according to the current pdf-lib font guidance. Treat this as a template-and-font decision, not an email problem.

Create a new PDF with PDFKit

Use PDFKit when there is no existing template. In Node, a PDFDocument is a readable stream, so you can pipe it to a file or another writable destination and call end() when all content is written.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.
Rank #2
Fill and Sign PDF Forms
  • Fill out and sign PDF forms on your mobile
  • Share completed forms via e-mail, etc.
  • Custom business solution support
import PDFDocument from 'pdfkit';
import fs from 'node:fs';
import nodemailer from 'nodemailer';

const outputPath = 'application-summary.pdf';
const doc = new PDFDocument({ margin: 50 });
const file = fs.createWriteStream(outputPath);
doc.pipe(file);

doc.fontSize(20).text('Application summary');
doc.moveDown();
doc.fontSize(12).text('Name: Avery Example');
doc.text('Email: [email protected]');
doc.text('Answers:');
doc.moveDown(0.5);
doc.text('I confirm that the information supplied is accurate.');
doc.end();

await new Promise((resolve, reject) => {
  file.once('finish', resolve);
  file.once('error', reject);
});

const transporter = nodemailer.createTransport({
  host: process.env.SMTP_HOST,
  port: Number(process.env.SMTP_PORT || 587),
  secure: process.env.SMTP_SECURE === 'true',
  auth: { user: process.env.SMTP_USER, pass: process.env.SMTP_PASS }
});
await transporter.sendMail({
  from: process.env.MAIL_FROM,
  to: process.env.MAIL_TO,
  subject: 'Application summary',
  text: 'The generated summary is attached.',
  attachments: [{ filename: 'application-summary.pdf', path: outputPath }]
});

PDFKit also documents form annotations. If you need a newly authored interactive form, initialize the form and add annotations deliberately, then test the result in target viewers. Creating annotations is not the same as filling a supplied AcroForm.

Choose Buffer, path, or stream for the attachment

Buffer for small, short-lived documents

The first example saves a Uint8Array and wraps it with Buffer.from(pdfBytes). This is convenient when you must validate or hash the complete PDF before sending. It uses memory proportional to the document size.

Path for a file already on disk

Nodemailer accepts an attachment path. This keeps your application code simple and lets Nodemailer read the file as it sends. Remove temporary files after the message has been accepted, while retaining them only as long as your retry policy requires.

Readable stream for incremental transfer

Pass a Node stream.Readable as content when the producer can stream directly. A browser-style WHATWG ReadableStream, such as a fetch response body, is not accepted directly as attachment content; convert it with Readable.fromWeb() from node:stream. For a remote resource, prefer HTTPS and keep certificate validation enabled. If an internal service uses a private certificate authority, configure that CA explicitly rather than disabling certificate checks.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.
Rank #3
PDF Director 3 PLUS - Edit, Convert, Redact, Protect PDFs, Fill Forms for Win 11, 10, 8.1, 7
  • Full-featured PDF Editor: Edit text in the document
  • Fully convert PDF to Word and Excel and continue editing
  • NEW: Further development of existing functions
  • NEW: Even faster and more user-friendly
  • NEW: Over 75 small improvements in all areas

Validate before you send

  • Validate and normalize form answers before writing them into the PDF; enforce length limits so a long response does not overflow a fixed field or page.
  • Reject unexpected field names and unsupported values instead of silently dropping them.
  • After saving, verify that the byte buffer is non-empty and begins with a valid PDF signature in your own validation layer.
  • Open representative outputs in the PDF readers used by recipients. Check accented and non-Latin text, checkbox state, dropdown display, page breaks, and print output.
  • Use a stable, descriptive filename and set contentType: 'application/pdf' when attaching bytes.
  • Handle generation and mail errors separately so a failed SMTP submission does not cause duplicate PDF creation without an idempotency decision.

Security and privacy considerations

Application answers can contain personal or confidential information. Follow your organization’s retention, access, and approved-email rules. Do not put answers or credentials in logs, URLs, exception messages, or analytics payloads. Protect template files and temporary PDFs, restrict filesystem permissions, and delete temporary files after the retry window. Use authenticated SMTP with transport security and confirm the recipient address before sending.

Troubleshooting common failures

“Field not found” or an accessor error

The name is wrong, the field type differs from the accessor, or the file is not an AcroForm. Enumerate field names in development, inspect the template in a PDF form editor, and switch to the matching accessor.

The value exists but is invisible

Regenerate appearances with form.updateFieldAppearances(), embed a font that contains the required characters, and retest in the actual recipient viewers. Viewer support for appearance flags is not uniform.

The attachment is empty or corrupt

Wait for pdfDoc.save() to resolve, or wait for the PDFKit output stream’s finish event before attaching a path. Do not read a file while it is still being written.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Mail sends but the message never arrives

Separate SMTP acceptance from final delivery. Check the provider’s response, authentication, recipient address, spam controls, and message-size policy. The Node libraries cannot guarantee inbox placement.

Remote stream fails with a certificate error

Keep certificate verification enabled. Install or configure the correct private CA for an internal endpoint; do not turn validation off merely to make the request succeed.

Memory usage grows under load

Replace in-memory buffers with a file path or readable stream for larger PDFs, cap concurrent jobs, and remove temporary files after successful submission or an intentional retry delay.

Independent reader supportYour contribution helps us test, update, and keep practical guides available for everyone.Support on Ko-Fi

Or skip the browser setup

If your workflow also needs a clean screenshot or PDF of a web form, ScreenshotNeo provides a single HTTP call instead of maintaining browser automation. It accepts consent banners like a visitor and removes more than 60 known consent platforms, newsletter popups, and chat widgets before capture; each cleanup step can be disabled. Bot checks, blank pages, timeouts, failed loads, and cache hits are not billed, and response headers report the page verdict and billing status. Its MCP server exposes take_screenshot, get_page_info, and capture_pdf to Claude, Cursor, and other MCP clients.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.
curl -G "https://api.screenshotneo.com/v1/shot" -d access_key=YOUR_API_KEY --data-urlencode url=https://stripe.com -o shot.webp

See the ScreenshotNeo API documentation for PDF output and the other capture options. The free plan includes 1,000 screenshots per month with no card; paid plans start at $5 for 3,000 screenshots. Create a free ScreenshotNeo account.

Best Value
pdf fill form
  • PDF fill form is a powerful app for filling pdf forms,
  • Very light and intuitive interface. With a couple of clicks your pdf is done!

FAQ

Can I fill a PDF generated from an HTML form?

Only if the PDF contains compatible interactive fields. An HTML form submission by itself does not create an AcroForm; generate a new PDF layout or use a template that was authored with fields.

Should I send the PDF as an attachment or a link?

Use an attachment when the recipient must receive the exact generated document immediately. Use a controlled link when files are large or need revocation and audit, subject to your organization’s storage and access rules.

Can one message contain several generated PDFs?

Yes. Provide multiple attachment objects, each with its own filename and content, path, or stream, while checking the receiving provider’s total message-size limits.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Frequently Asked Questions

Does pdf-lib send email itself?

No. pdf-lib creates or edits the PDF; Nodemailer and your configured SMTP transport handle message submission.

Is PDFKit a replacement for pdf-lib?

Not generally. PDFKit is primarily for authoring new documents, while pdf-lib is suited to loading an existing interactive PDF and setting its fields.

Why do viewers show different form results?

PDF field values and their appearance streams are separate, and some viewers do not honor appearance-related flags identically. Regenerate appearances and test the target readers.

Quick Recap

Bestseller No. 1
PDF Max - Read, Annotate & Edit PDF documents plus Fill out PDF Forms!
PDF Max - Read, Annotate & Edit PDF documents plus Fill out PDF Forms!
Desktop class PDF reader and editor for Android; Read PDF documents with Mobile-Optimized Text Reflow mode & Text To Speech
Bestseller No. 2
Fill and Sign PDF Forms
Fill and Sign PDF Forms
Fill out and sign PDF forms on your mobile; Share completed forms via e-mail, etc.; Custom business solution support
Bestseller No. 3
PDF Director 3 PLUS - Edit, Convert, Redact, Protect PDFs, Fill Forms for Win 11, 10, 8.1, 7
PDF Director 3 PLUS - Edit, Convert, Redact, Protect PDFs, Fill Forms for Win 11, 10, 8.1, 7
Full-featured PDF Editor: Edit text in the document; Fully convert PDF to Word and Excel and continue editing
$29.99
Bestseller No. 5
pdf fill form
pdf fill form
PDF fill form is a powerful app for filling pdf forms,; Very light and intuitive interface. With a couple of clicks your pdf is done!

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.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.