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

Some links on this page are affiliate links: if you buy through them we may earn a commission, at no extra cost to you.

Set every form control to the value you want before calling page.pdf(). Puppeteer prints the page as rendered with the print CSS media type, so your print stylesheet must keep the controls visible and make their values legible. The resulting PDF is normally a visual snapshot, not an editable PDF form.

Set values, then print

A reliable sequence is: launch Chromium, open or load the form, populate each control through the same DOM interactions your application uses, wait for dependent UI to settle, and only then generate the PDF.

  1. Launch Puppeteer and create a page.
  2. Navigate with an appropriate readiness condition such as networkidle2, or set the page content for an HTML string.
  3. Fill text fields and textareas, choose option values, and set checkboxes or radios. Trigger application events when the form relies on them.
  4. Wait for validation messages, calculated fields, images, or other asynchronous changes.
  5. Call page.pdf() with the paper and print options required by your output.
  6. Close the browser in a finally block so failures do not leave Chromium processes running.

A complete Node.js example

This script fills common controls and writes a PDF. Replace the URL, selectors, and values with those used by your form.

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.
const puppeteer = require('puppeteer');

async function createPdf() {
  const browser = await puppeteer.launch();
  try {
    const page = await browser.newPage();
    await page.goto('https://example.com/form', { waitUntil: 'networkidle2' });

    await page.locator('input[name="name"]').fill('Ada Lovelace');
    await page.locator('textarea[name="notes"]').fill('Reviewed');
    await page.select('select[name="category"]', 'approved');

    await page.pdf({
      path: 'form.pdf',
      format: 'A4',
      printBackground: true
    });
  } finally {
    await browser.close();
  }
}

createPdf().catch((error) => {
  console.error(error);
  process.exitCode = 1;
});

The locator fill operation and page.select() use the controls’ selectors; the exact selector and interaction depend on the page. If a framework updates another element after input, wait for a selector, a state change, or a short, justified application-level delay before printing.

Text inputs and textareas

Use a stable ID, name, or data attribute rather than a brittle positional selector. Filling through Puppeteer updates the element before printing. For a custom component that is not a native input, interact with the component’s actual UI and verify its displayed value.

Select menus

page.select(selector, value) selects an option by its value attribute. If the page listens for a change event to reveal more fields, wait until that resulting element appears or its content is updated.

Checkboxes and radio buttons

Click the intended control, or set it through the page’s UI, then verify its checked state. A visually styled control may hide the native input; select the clickable label or component element if that is what the application requires.

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

Date, number, and specialized controls

Use the interaction supported by the page and confirm the rendered result. Chromium versions, operating systems, and custom styles can affect how specialized controls appear in print. For production output, generate a PDF with the exact Puppeteer and Chromium versions used in deployment and inspect it.

Why values can disappear in the PDF

Print CSS hides or changes the control

page.pdf() uses print media by default. Rules such as display:none, white text, collapsed containers, or print-only replacements can hide a value that is visible on screen. Add explicit print rules:

@media print {
  input, textarea, select {
    display: block;
    color: #000;
    background: #fff;
    border: 1px solid #777;
  }

  .screen-only { display: none; }
  .page-break-before { break-before: page; }
}

/* Preserve brand colors when required by the design. */
.form, .form * {
  -webkit-print-color-adjust: exact;
  print-color-adjust: exact;
}

Test contrast and wrapping at the actual paper size. A long value may overflow or be clipped even though the control itself is present.

The page was printed before the state changed

Navigation completion does not necessarily mean a client-side calculation or validation request is finished. After filling, wait for a meaningful signal, for example:

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.
await page.locator('[data-status="saved"]').wait();
// or, when the application exposes a dependable condition:
await page.waitForFunction(() => document.querySelector('#total')?.textContent === '$42.00');

Avoid arbitrary long delays when a DOM or network condition can express readiness more precisely.

The value exists only as a property

Form values are DOM properties. If your print layout copies labels into separate elements, that copy must be updated by the application before printing. If you construct a replacement summary yourself, read the current values immediately before generating the PDF.

Choose screen or print styling deliberately

Print media is the default because PDF output is intended for paper-like layout. If the screen design is the required appearance, call:

await page.emulateMediaType('screen');
await page.pdf({ path: 'screen-look.pdf', printBackground: true });

Using screen media does not make a PDF interactive; it only changes which CSS rules are applied. Keep a dedicated print stylesheet when pagination, margins, or simplified controls matter.

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

PDF options that affect form output

Option Use it for Important detail
format Standard paper such as A4 or Letter The current API reference lists Letter as the default; set it explicitly for predictable output.
width, height Custom page dimensions Use CSS units accepted by Puppeteer when a standard format is unsuitable.
margin Keeping controls away from paper edges Account for the printable area when a field spans the page.
preferCSSPageSize Honoring @page dimensions Useful when the document owns its page geometry.
scale Fitting dense forms Scaling can make text too small; adjust layout first where possible.
printBackground Printing background fills and images The documented default is false; enable it when backgrounds carry meaning.
waitForFonts Waiting for web fonts The documented default is true; leave it enabled unless you have a measured reason not to.
tagged Tagged/accessibility-oriented output The current option is experimental and documented with a default of true; verify the result with your PDF tools.

For exact colors, -webkit-print-color-adjust: exact can prevent print color modification, but it can increase ink use and still deserves visual testing.

Rendered snapshot versus fillable PDF

Puppeteer’s page printing workflow renders HTML into PDF content. A visible input and its value therefore do not automatically become an editable AcroForm field. If recipients must type into the saved PDF, add a PDF form-authoring or post-processing step that creates interactive fields, then test those fields in the PDF readers your audience uses. Treat “values visible in the PDF” and “fields editable in a PDF reader” as separate acceptance criteria.

Validation checklist before shipping

  • Confirm every required control has the intended value immediately before page.pdf().
  • Check unchecked, checked, selected, disabled, and read-only states that your workflow can produce.
  • Inspect the PDF at its target paper size, including long text, wrapped labels, and page breaks.
  • Verify fonts, background colors, contrast, and print-only visibility.
  • Run the same Puppeteer/Chromium versions used in production.
  • Decide explicitly whether a rendered snapshot is sufficient or interactive PDF fields are required.
  • Use a temporary output path and clean it up if generation fails.

Troubleshooting common failures

The PDF shows an empty input

Check that the fill call completed and that the selector identifies the live element, not a hidden template. Then inspect print CSS for hiding or color rules. If a framework replaces the node after filling, perform the interaction after the replacement or wait for the replacement first.

A select value is not reflected

Ensure the value passed to page.select() exactly matches an option’s value. If the application requires a user event, select through the visible component and wait for its dependent update.

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

Calculated fields contain old data

Wait for the calculation’s completion signal rather than relying solely on navigation readiness. A selector, status text, or deterministic page function is preferable to a blanket timeout.

Backgrounds or colors are missing

Set printBackground: true and review -webkit-print-color-adjust. Also check whether print CSS intentionally overrides the screen palette.

Content is cut off or breaks badly

Set an explicit format or dimensions, margins, and (where appropriate) preferCSSPageSize. Add CSS break rules, allow long labels to wrap, and avoid solving every overflow problem by shrinking the global scale.

The PDF is not fillable

That is expected from ordinary page printing. Add a separate PDF form-generation step and verify field names, tab order, validation, and appearance in representative readers.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.
Independent reader supportYour contribution helps us test, update, and keep practical guides available for everyone.Support on Ko-Fi

Performance, reliability, and security notes

Reuse a browser process for a batch of documents while creating an isolated page per job; close pages and the browser on shutdown. Set navigation and application-level timeouts appropriate to your environment, and capture console and page-error messages for diagnosis. Keep credentials out of URLs and logs, and do not print sensitive values unintentionally. For deterministic PDFs, pin the deployed Chromium/Puppeteer versions, fonts, locale, timezone, and CSS assets. Generate and inspect representative PDFs after browser upgrades because rendering details can change.

Or skip the browser setup

When you need a PDF or screenshot of a public form page rather than a custom Puppeteer workflow, ScreenshotNeo provides a single request. Its cleanup step accepts cookie/consent banners and removes more than 60 known consent platforms, newsletter popups, and chat widgets before capture; you can turn each step off. Bot checks, blank pages, failed loads, timeouts, and cache hits are not billed, and response headers identify the page verdict and billing status. It also offers an MCP server for AI agents, including Claude and Cursor, with take_screenshot, get_page_info, and capture_pdf tools.

curl -G "https://api.screenshotneo.com/v1/shot" -d access_key=YOUR_API_KEY --data-urlencode url=https://example.com/form -o form.pdf

See the ScreenshotNeo documentation for PDF parameters and authentication. The same endpoint can return PNG, JPEG, WebP, or PDF according to your request.

import requests
r = requests.get("https://api.screenshotneo.com/v1/shot", params={"access_key": "YOUR_API_KEY", "url": "https://example.com/form"}, timeout=90)
r.raise_for_status()
open("form.pdf", "wb").write(r.content)
const q = new URLSearchParams({ access_key: 'YOUR_API_KEY', url: 'https://example.com/form' });
const res = await fetch(`https://api.screenshotneo.com/v1/shot?${q}`);
if (!res.ok) throw new Error(`ScreenshotNeo: ${res.status}`);
const data = Buffer.from(await res.arrayBuffer());
require('fs').writeFileSync('form.pdf', data);

The Free plan includes 1,000 screenshots per month with no card. Paid plans start at $5 for 3,000 shots, and every feature is available on every plan. If that fits your workflow, sign up for the free plan.

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

FAQ

Can Puppeteer preserve a user’s unsaved browser edits?

Only if those edits exist in the page you control and you capture that page state. A fresh navigation starts from the server response, so populate the controls again or load the corresponding state before printing.

Should I use a screenshot instead of a PDF for a form?

Use PDF when selectable text, pagination, or document distribution matters. Use an image when a fixed visual asset is the actual requirement; neither approach alone creates editable PDF fields.

How do I test output after a Chromium upgrade?

Keep a fixture form containing each control type and important print states, generate PDFs with the new versions, and compare them visually and for text accessibility before deployment.

Frequently Asked Questions

Can Puppeteer preserve a user’s unsaved browser edits?

Only if those edits exist in the page you control and you capture that page state. A fresh navigation starts from the server response, so populate the controls again or load the corresponding state before printing.

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

Should I use a screenshot instead of a PDF for a form?

Use PDF when selectable text, pagination, or document distribution matters. Use an image when a fixed visual asset is the actual requirement; neither approach alone creates editable PDF fields.

How do I test output after a Chromium upgrade?

Keep a fixture form containing each control type and important print states, generate PDFs with the new versions, and compare them visually and for text accessibility before deployment.

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.