Create Fillable PDF Forms from HTML

This guide shows how to create fillable PDFs with PDFCrowd's HTML to PDF API. Define the fields and layout in HTML, then enable form conversion to produce a PDF that readers can fill in and save.

Create the HTML form

Use standard HTML form controls. This registration form includes a text field, a dropdown, radio buttons, a checkbox, and a multiline field:

<form>
  <p>
    <label for="full-name">Full name</label>
    <input id="full-name" type="text" name="full_name"
           title="Full name" maxlength="80" required>
  </p>
  <p>
    <label for="attendance">Attendance</label>
    <select id="attendance" name="attendance" title="Attendance">
      <option value="online" selected>Online</option>
      <option value="in-person">In person</option>
    </select>
  </p>
  <fieldset>
    <legend>Session</legend>
    <label><input type="radio" name="session" value="morning" checked> Morning</label>
    <label><input type="radio" name="session" value="afternoon"> Afternoon</label>
  </fieldset>
  <p>
    <label><input type="checkbox" name="updates" value="yes"> Send me workshop updates</label>
  </p>
  <p>
    <label for="notes">Notes</label>
    <textarea id="notes" name="notes" title="Notes"></textarea>
  </p>
  <input type="reset" value="Reset form">
</form>

Give each independent field a distinct name. Radio buttons in one group share a name and have different value attributes.

To set initial values, use value for text inputs, checked for checkboxes and radio buttons, and selected on <option> elements. Place a <textarea>'s initial text between its tags.

The complete registration.html example adds a page title and CSS to this form and is the input for the conversion below.

Generate the fillable PDF

Call setEnablePdfForms(True) before conversion to create interactive PDF fields. Without this setting, the controls render as static page content.

The example uses Python. The same HTML and conversion settings work with any supported client library or the HTTP API.

To run it, install the Python client and set API credentials in the API_USERNAME and API_KEY environment variables. Both can be set to "demo" for testing.

import os

import pdfcrowd

client = pdfcrowd.HtmlToPdfClient(
    os.environ["API_USERNAME"],
    os.environ["API_KEY"],
)
client.setEnablePdfForms(True)
client.setPageSize("A4")
client.setPageMargins("18mm", "18mm", "18mm", "18mm")

client.convertFileToFile("registration.html", "registration.pdf")

For a webpage input, the final conversion call would be:

client.convertUrlToFile("https://your-domain.example/registration/", "registration.pdf")

Try the result

You can try the example PDF without running the code. Enter a name, change the selections, and save a copy using your PDF reader. Reopen that copy to check the saved values; the fields should remain editable.

PDF readers differ in their support for form actions and formatting. Test the PDF in the readers your audience uses, including any reset or submit buttons and number or date formatting.

Choose controls and field behavior

The API converts <input>, <textarea>, and <select> elements and supports multiple forms on a page. These HTML features control the resulting fields:

HTML feature Purpose
Text inputs and <textarea> Single-line and multiline text.
type="checkbox" An independent on/off choice; value identifies the checked value.
type="radio" with a shared name One selection within a group.
<select> and <option> A choice field; selected supplies its initial selection.
<select multiple> Multiple selections in a list.
readonly or disabled A field that cannot be edited.
required Marks a field as required for form submission.
maxlength Limits text length.
min and max on number or range inputs Set numeric limits.
title Supplies a field tooltip.

A required field does not prevent someone from saving an incomplete PDF. Validate submitted data in the application that processes it.

Keep a control static

Add data-pdfcrowd-static to render a control without creating an interactive PDF field:

<input type="text" name="reference" value="REG-2026" data-pdfcrowd-static>

Use this for displayed values that should not be part of the fillable form.

Style the fields

Set field sizes, fonts, colors, and borders in CSS. Leave enough room for the text that people will enter. For gradients or a border on only one side, style a wrapper around a transparent input:

<style>
  .name-field {
    width: 75mm;
    height: 10mm;
    border-bottom: 2px solid #2563eb;
    background: linear-gradient(90deg, #e0f2fe, #f0fdfa);
  }
  .name-field input {
    width: 100%;
    height: 100%;
    box-sizing: border-box;
    border: 0;
    background: transparent;
    font: 12pt sans-serif;
  }
</style>

<label for="name">Name</label>
<div class="name-field">
  <input id="name" type="text" name="name">
</div>

Field fonts and check symbols

By default, the input font is embedded in the PDF. data-pdfcrowd-font selects a standard PDF font for the field instead, which can reduce the file size:

<input type="text" name="reference" data-pdfcrowd-font="Courier">
Family Accepted font names
Courier Courier, Courier Oblique, Courier Bold, Courier Bold-Oblique
Helvetica Helvetica, Helvetica Oblique, Helvetica Bold, Helvetica Bold-Oblique
Times Times Roman, Times Italic, Times Bold, Times Bold-Italic

data-pdfcrowd-check-style changes the checkbox or radio symbol. The codes are 4 (check), l (lowercase L, circle), H (star), u (diamond), n (rectangle), and 8 (cross):

<input type="checkbox" name="confirmed" value="yes" data-pdfcrowd-check-style="l">

Format numbers, dates, and times

These attributes control how field values are formatted in the PDF. They do not change how the HTML controls appear in a browser.

Numbers

<input type="number" name="amount" value="1250" step="0.01"
       data-pdfcrowd-decimal-places="2"
       data-pdfcrowd-separate-thousands
       data-pdfcrowd-symbol="$"
       data-pdfcrowd-prepend-symbol>
Attribute Effect
data-pdfcrowd-decimal-places="2" Sets the number of decimal places.
data-pdfcrowd-separate-thousands Enables thousands separators.
data-pdfcrowd-symbol="$" Adds the specified currency symbol.
data-pdfcrowd-prepend-symbol Places that symbol before the number.
data-pdfcrowd-negative-red Displays negative values in red.
data-pdfcrowd-parens Encloses negative values in parentheses.

Dates and times

Use data-pdfcrowd-datetime-format for date fields and data-pdfcrowd-time-format for time fields:

<input type="date" name="event_date" data-pdfcrowd-datetime-format="yyyy-mm-dd">
<input type="time" name="start_time" data-pdfcrowd-time-format="HH:MM">
Tokens Meaning
m, mm Month without/with a leading zero.
mmm, mmmm Abbreviated/full month name.
d, dd Day of the month without/with a leading zero.
ddd, dddd Abbreviated/full weekday name.
yy, yyyy Two-digit/four-digit year.
h, hh 12-hour time without/with a leading zero.
H, HH 24-hour time without/with a leading zero.
MM Minutes.
s, ss Seconds without/with a leading zero.
t, tt a/p or am/pm.

The tokens are case-sensitive: mm is the month, while MM is minutes.

Add reset and submit buttons

A reset button restores the form's initial values. A submit button sends data to the endpoint specified by the HTML form's action, using its method:

<form action="https://your-domain.example/registrations/" method="post">
  <label>Name <input type="text" name="full_name" required></label>
  <input type="reset" value="Reset form">
  <input type="submit" value="Send registration">
</form>

The form's action must point to an endpoint that accepts submissions. Conversion creates the button and its action; data is sent when someone uses the button in a compatible PDF reader. Reset and submit support depends on the PDF reader and its security settings.

The default submission format is HTML. Use data-pdfcrowd-submit-format on the submit input to select FDF, XFDF, or PDF instead; PDF sends the complete document. The endpoint must accept the chosen format.

<input type="submit" value="Send XFDF"
       data-pdfcrowd-submit-format="XFDF"
       data-pdfcrowd-submit-canonical-dates>

data-pdfcrowd-submit-canonical-dates requests a standard representation for submitted date values. Check the actual payload with your endpoint and intended reader before relying on it.

Place fields over an existing PDF

A static or scanned PDF can serve as the page background. Add HTML controls and position them with CSS to match the areas to fill in on the background page.

For an A4 background, this overlay.html places a field 25 mm from the left and 50 mm from the top of the page:

<!doctype html>
<html>
<head>
  <meta charset="utf-8">
  <style>
    html, body { margin: 0; background: transparent; }
    .page { position: relative; width: 210mm; height: 297mm; }
    .page:not(:last-child) { break-after: page; }
    .name {
      position: absolute;
      left: 25mm;
      top: 50mm;
      width: 85mm;
      height: 10mm;
      box-sizing: border-box;
      border: 1px solid #94a3b8;
      background: transparent;
      font: 12pt sans-serif;
    }
  </style>
</head>
<body>
  <div class="page">
    <input class="name" type="text" name="full_name" title="Full name">
  </div>
</body>
</html>

To combine overlay.html with background.pdf, initialize the client as in the conversion example, then apply these settings:

client.setEnablePdfForms(True)
client.setPageSize("A4")
client.setNoMargins(True)
client.setContentFitMode("no-scaling")
client.setMultipageBackground("background.pdf")

client.convertFileToFile("overlay.html", "fillable.pdf")

Match the output page dimensions to the background PDF. Removing margins makes the HTML coordinates start at the page edge; disabling content scaling preserves the dimensions set in CSS. Adjust each field's position and size to fit the background.

For multiple pages, add one .page container per output page, each containing its own fields. setMultipageBackground() uses the corresponding background page; if the background has fewer pages, its last page repeats. Use distinct names for independent fields on different pages.

Troubleshooting

  • Fields look correct but cannot be edited: check that form conversion is enabled, the controls are not readonly, disabled, or marked data-pdfcrowd-static, and the PDF reader supports interactive forms.
  • Formatting or buttons behave differently between readers: test those features separately from basic text entry and saving. A reader may support editable fields but only partly support form actions.
  • Overlay fields do not line up: check the background's page dimensions, output margins, and CSS coordinates, and use setContentFitMode("no-scaling") to preserve field positions.
  • Conversion fails when PDF/A is enabled: the API's PDF/A conformance setting cannot be combined with fillable PDF forms.