Run this before you send the document out, so a signer never receives a form with blanks that should have been filled in:
from pypdf import PdfReader
REQUIRED = 1 << 1 # bit position 2 of the field flags (/Ff)
def missing_required_fields(path):
reader = PdfReader(path)
missing = []
for name, field in (reader.get_fields() or {}).items():
if field.get("/FT") == "/Sig":
continue # signers fill these later
flags = int(field.get("/Ff", 0))
if not flags & REQUIRED:
continue
value = field.get("/V")
if value in (None, "", "/Off"):
missing.append(name)
return missing
print(missing_required_fields("application.pdf")) # for example: ['email', 'agree']
How it works
pypdf's get_fields() returns a dictionary of every interactive field, or None if it cannot locate any form data, which is why the loop falls back to an empty dictionary. Each field's /Ff entry holds its flag bits, and the Required flag is bit position 2 (value 2). The code skips fields that do not have that flag, then treats a missing, empty, or /Off value as unfilled. /Off is how a checkbox stores the unchecked state, so a required checkbox that was never ticked is reported alongside empty text fields. Signature fields (/FT of /Sig) are skipped because the signer completes those later.
Caveats
This only finds fields that the PDF itself marks as required. Plenty of forms mark mandatory fields only with an asterisk, or enforce them with JavaScript, and neither shows up in the flag. If your forms work that way, keep your own list of field names that must be filled and check those instead.
Radio groups and fields nested under a parent can store their value differently from a simple text field, so run the check against a few real forms from your own workflow before relying on it.
Back to All Questions