§HOW-TO GUIDE · C# · .NET 8 & 10

Fill PDF form fields in C#

Load the PDF with PdfFormManager, look up each field by name in Fields, set its value and save. The sample first makes the fillable form itself, by converting an HTML form with CreateFormFields turned on.

Compiled and run: Linux ARM64 · Linux x64 · macOS ARM64 · Windows x64

Video walkthrough · 3:43 · Watch on YouTube · Short · 0:59
§STEP BY STEP

Build it step by step.

  1. 1Install the NuGet packages

    SelectPdf.Universal is the library. The native package carries the Chromium engine for one platform: add the one for the platform you run on.

    terminal
    dotnet add package SelectPdf.Universal
    dotnet add package SelectPdf.Universal.Native.win-x64
    terminal
    dotnet add package SelectPdf.Universal
    dotnet add package SelectPdf.Universal.Native.linux-x64
    terminal
    dotnet add package SelectPdf.Universal
    dotnet add package SelectPdf.Universal.Native.linux-arm64
    terminal
    dotnet add package SelectPdf.Universal
    dotnet add package SelectPdf.Universal.Native.osx-arm64
  2. 2Create a console app

    Any .NET 8 or .NET 10 project works. To follow along, create a console app, run the install commands above inside its folder, then replace Program.cs with the code below.

    terminal
    dotnet new console -n PdfSample
    cd PdfSample
  3. 3Write the HTML form

    Program.cs · lines 3–21
    // an HTML form: every control has a name
    string html = """
        <style>body { font-family: Arial, sans-serif; }</style>
        <h1>Conference registration</h1>
        <form>
          <p><label>Full name <input type="text" name="fullName"></label></p>
          <p><label>Email <input type="email" name="email"></label></p>
          <p><label>Ticket
            <select name="ticket">
              <option value="standard">Standard</option>
              <option value="workshop">Workshop</option>
              <option value="vip">VIP</option>
            </select></label></p>
          <p>Meal:
            <label><input type="radio" name="meal" value="regular"> Regular</label>
            <label><input type="radio" name="meal" value="vegetarian"> Vegetarian</label></p>
          <p><label><input type="checkbox" name="newsletter"> Send me the newsletter</label></p>
        </form>
        """;

    Give every control a name: it becomes the name of the PDF field. In your application the form is usually a page or a template you already have, or you start from an existing fillable PDF and skip the conversion.

  4. 4Convert it into a fillable PDF form

    Program.cs · lines 23–28
    // convert it into a fillable PDF form
    HtmlToPdf converter = new HtmlToPdf();
    converter.Options.CreateFormFields = true;
    PdfDocument doc = converter.ConvertHtmlString(html);
    doc.Save("registration-form.pdf");
    doc.Close();

    Options.CreateFormFields = true turns the controls into PDF form fields instead of printing them as they look on the page. The text boxes, the select, the radio buttons and the check box keep the page's own look.

  5. 5Load the form and fill the fields by name

    Program.cs · lines 30–38
    // load the form and fill the fields by name
    PdfFormManager form = new PdfFormManager();
    form.Load("registration-form.pdf");
    
    ((PdfFormFieldTextBox)form.Fields["fullName"]).Text = "Jane Doe";
    ((PdfFormFieldTextBox)form.Fields["email"]).Text = "jane.doe@example.com";
    ((PdfFormFieldComboBox)form.Fields["ticket"]).SelectedValue = "workshop";
    ((PdfFormFieldRadioButtonList)form.Fields["meal"]).SelectedValue = "vegetarian";
    ((PdfFormFieldCheckBox)form.Fields["newsletter"]).Checked = true;

    PdfFormManager.Load opens the PDF, and Fields["name"] returns the field with that name. Cast it to its type to set the value: Text for a text box, SelectedValue for a combo box or a radio button list, Checked for a check box.

  6. 6Save the filled form

    Program.cs · lines 40–42
    // save the filled form
    form.Save("registration-filled.pdf");
    form.Close();

    Save writes registration-filled.pdf with the values in the fields, which stay editable in a PDF viewer. Close releases the document.

  7. 7Run it

    terminal
    dotnet run

    The program writes registration-filled.pdf to the working folder. Without a license key, every page carries a trial watermark; set GlobalProperties.LicenseKey before the first conversion to remove it.

§COMPLETE PROGRAM

The complete Program.cs.

This is the exact file our samples pipeline compiled and ran on Linux ARM64 and Linux x64 and macOS ARM64 and Windows x64 to produce the output on this page.

Program.cs
using SelectPdf.Universal;

// an HTML form: every control has a name
string html = """
    <style>body { font-family: Arial, sans-serif; }</style>
    <h1>Conference registration</h1>
    <form>
      <p><label>Full name <input type="text" name="fullName"></label></p>
      <p><label>Email <input type="email" name="email"></label></p>
      <p><label>Ticket
        <select name="ticket">
          <option value="standard">Standard</option>
          <option value="workshop">Workshop</option>
          <option value="vip">VIP</option>
        </select></label></p>
      <p>Meal:
        <label><input type="radio" name="meal" value="regular"> Regular</label>
        <label><input type="radio" name="meal" value="vegetarian"> Vegetarian</label></p>
      <p><label><input type="checkbox" name="newsletter"> Send me the newsletter</label></p>
    </form>
    """;

// convert it into a fillable PDF form
HtmlToPdf converter = new HtmlToPdf();
converter.Options.CreateFormFields = true;
PdfDocument doc = converter.ConvertHtmlString(html);
doc.Save("registration-form.pdf");
doc.Close();

// load the form and fill the fields by name
PdfFormManager form = new PdfFormManager();
form.Load("registration-form.pdf");

((PdfFormFieldTextBox)form.Fields["fullName"]).Text = "Jane Doe";
((PdfFormFieldTextBox)form.Fields["email"]).Text = "jane.doe@example.com";
((PdfFormFieldComboBox)form.Fields["ticket"]).SelectedValue = "workshop";
((PdfFormFieldRadioButtonList)form.Fields["meal"]).SelectedValue = "vegetarian";
((PdfFormFieldCheckBox)form.Fields["newsletter"]).Checked = true;

// save the filled form
form.Save("registration-filled.pdf");
form.Close();

Open the project on GitHub → this program and the variations below, ready to dotnet run

§OUTPUT

The PDF it produces.

First page of registration-filled.pdf, the PDF this sample produces
registration-filled.pdf, page 1

Download registration-filled.pdf ↓ the file this sample produced, unedited

§VARIATIONS

Variations you will need next.

Each variation is a separate file in the same project, compiled and run with the program above.

List the fields of a form with their types and values

Before filling a form you did not create, find out what it contains. Enumerating Fields gives every field; its class (PdfFormFieldTextBox, PdfFormFieldCheckBox, PdfFormFieldRadioButtonList, PdfFormFieldComboBox or PdfFormFieldListBox) tells you which property holds its value. Load also accepts a PdfDocument, so a converted document is read without saving it first.

ListFormFields.cs
using SelectPdf.Universal;

static class ListFormFields
{
    public static void Run()
    {
        // a form that already holds values (made here so the sample runs on its own)
        HtmlToPdf converter = new HtmlToPdf();
        converter.Options.CreateFormFields = true;
        PdfDocument doc = converter.ConvertHtmlString("""
            <form>
              <input type="text" name="company" value="Contoso Ltd">
              <textarea name="notes">Deliver to the side entrance.</textarea>
              <input type="checkbox" name="express" checked>
              <input type="radio" name="payment" value="card">
              <input type="radio" name="payment" value="invoice" checked>
              <select name="country"><option>France</option><option selected>Germany</option></select>
              <select name="extras" multiple>
                <option selected>Gift wrap</option><option>Insurance</option><option selected>Tracking</option>
              </select>
            </form>
            """);

        // list every field: name, type and current value
        PdfFormManager form = new PdfFormManager();
        form.Load(doc);
        List<string> lines = new List<string>();
        foreach (PdfFormField field in form.Fields)
        {
            string value = field switch
            {
                PdfFormFieldTextBox text => text.Text,
                PdfFormFieldCheckBox check => check.Checked.ToString(),
                PdfFormFieldRadioButtonList radio => radio.SelectedValue,
                PdfFormFieldComboBox combo => combo.SelectedValue,
                PdfFormFieldListBox list => string.Join(", ", list.SelectedValues),
                _ => ""
            };
            lines.Add($"{field.Name} ({field.GetType().Name}, page {field.DisplayPage}): {value}");
        }
        form.Close();
        doc.Close();

        File.WriteAllLines("form-fields.txt", lines);
        lines.ForEach(Console.WriteLine);
    }
}

Fill a form in memory and make it read-only

Load takes a byte array (or a stream), so a form from a database or an upload never touches the disk. Setting ReadOnly on the PdfFormManager marks every field read-only; set ReadOnly on a single field to lock only that one. To turn the fields into ordinary page content instead, see the guide on flattening a PDF form.

FillAndLock.cs
using SelectPdf.Universal;

static class FillAndLock
{
    public static void Run()
    {
        // a blank form (made here so the sample runs on its own)
        HtmlToPdf converter = new HtmlToPdf();
        converter.Options.CreateFormFields = true;
        PdfDocument doc = converter.ConvertHtmlString("""
            <h1>Leave request</h1>
            <p><label>Employee <input type="text" name="employee"></label></p>
            <p><label>From <input type="text" name="from"></label>
               <label>To <input type="text" name="to"></label></p>
            <p><label><input type="checkbox" name="approved"> Approved</label></p>
            """);
        byte[] blank = doc.Save();
        doc.Close();

        // fill the form from memory, then make every field read-only
        PdfFormManager form = new PdfFormManager();
        form.Load(blank);
        ((PdfFormFieldTextBox)form.Fields["employee"]).Text = "Jane Doe";
        ((PdfFormFieldTextBox)form.Fields["from"]).Text = "2026-11-02";
        ((PdfFormFieldTextBox)form.Fields["to"]).Text = "2026-11-06";
        ((PdfFormFieldCheckBox)form.Fields["approved"]).Checked = true;
        form.ReadOnly = true;

        form.Save("leave-request-locked.pdf");
        form.Close();
    }
}

Fill a form from JSON values

When the values arrive as data keyed by field name, walk the fields and set each one from the value with its name. A switch on the field's type picks the property to set, so the same loop fills any form whose field names match the keys.

FillFromJson.cs
using System.Text.Json;
using SelectPdf.Universal;

static class FillFromJson
{
    public static void Run()
    {
        // a blank form (made here so the sample runs on its own)
        HtmlToPdf converter = new HtmlToPdf();
        converter.Options.CreateFormFields = true;
        PdfDocument doc = converter.ConvertHtmlString("""
            <h1>Shipping label</h1>
            <p><label>Recipient <input type="text" name="recipient"></label></p>
            <p><label>City <input type="text" name="city"></label></p>
            <p><label>Service <select name="service">
                <option value="standard">Standard</option><option value="express">Express</option>
              </select></label></p>
            <p><label><input type="checkbox" name="fragile"> Fragile</label></p>
            """);
        doc.Save("shipping-label-form.pdf");
        doc.Close();

        // the values, keyed by field name, as they arrive from an API or a database
        string json = """
            { "recipient": "Contoso Ltd", "city": "Berlin", "service": "express", "fragile": "true" }
            """;
        Dictionary<string, string> values = JsonSerializer.Deserialize<Dictionary<string, string>>(json)!;

        // set each field from the value with its name
        PdfFormManager form = new PdfFormManager();
        form.Load("shipping-label-form.pdf");
        foreach (PdfFormField field in form.Fields)
        {
            if (!values.TryGetValue(field.Name, out string? value)) continue;
            switch (field)
            {
                case PdfFormFieldTextBox text: text.Text = value; break;
                case PdfFormFieldCheckBox check: check.Checked = bool.Parse(value); break;
                case PdfFormFieldComboBox combo: combo.SelectedValue = value; break;
                case PdfFormFieldRadioButtonList radio: radio.SelectedValue = value; break;
            }
        }
        form.Save("shipping-label-filled.pdf");
        form.Close();
    }
}
§TROUBLESHOOTING

Common problems and fixes.

A field cannot be found by its name

A converted field is named after the control's name, or its id when it has none, and a name used twice gets a suffix. For a form you did not create, list the fields to see their exact names. A nested field is looked up by its fully-qualified name, such as address.city, which FullName returns.

The PDF has no fields after the conversion

Set Options.CreateFormFields = true before converting, and keep Options.JavaScriptEnabled on: the controls are read by a script after the page's own scripts have run. Hidden, file, image and button inputs never become fields.

A combo box or radio button value is not selected

SelectedValue takes one of the values the field offers, which Items returns. For a converted form these are the value attributes of the options and radio buttons. SelectedIndex selects by position instead.

The filled form is signed, or larger than expected

Save appends the changes to the original document, which keeps an earlier signature verifiable. Set CompactSave = true to write a new, smaller document instead, knowing that a signature the document carried no longer verifies.

The PDF form is password-protected

Use the Load overload that takes a password, for a file, a stream, a byte array or a PdfDocument.

§GOOD TO KNOW

Good to know.

  • With CreateFormFields set to true, text, email, number, date and similar inputs, check boxes, radio buttons, selects and text areas become fillable PDF form fields placed over the controls as they were printed. The default is false. Source
  • Each converted field takes the name of its HTML control, or its id when it has no name, along with the control's current value and its read-only, required and maximum length settings. Source
  • PdfFormManager reads and fills text boxes, check boxes, list boxes, combo boxes and radio button lists in existing PDF documents that contain AcroForm fields. Source
  • By default PdfFormManager saves an incremental update: the loaded document is written unchanged and the changes are appended, which keeps a signature made before the form was filled verifiable. Source
  • Hidden, file, image and button inputs are not converted into fields, and a password input's value is not carried into the PDF. Source
?FAQ

Questions, answered.

Short answers about this guide. The SelectPdf.Universal documentation covers every class and option.

Create a PdfFormManager, call Load with the PDF, get each field from Fields by name, cast it to its type (PdfFormFieldTextBox, PdfFormFieldCheckBox, PdfFormFieldComboBox, PdfFormFieldRadioButtonList or PdfFormFieldListBox), set its value and call Save.
Set converter.Options.CreateFormFields = true and convert a page with an HTML form. Its inputs, selects and text areas become PDF form fields with the names of the controls. PdfHtmlElement has the same CreateFormFields property for HTML drawn into a region of a page.
Load the PDF with PdfFormManager and enumerate Fields. Each PdfFormField has a Name and a FullName, and its class tells you whether it is a text box, a check box, a combo box, a list box or a radio button list.
Yes. Set ReadOnly on the PdfFormManager to make every field read-only, or on a single PdfFormField. To remove the fields and keep only their values on the page, flatten the form.