Where a form's answers are stored
A fillable PDF form holds its questions as named fields. When someone types an answer, the value is stored with the field inside the file. The pypdf documentation describes reading these values by field name, and lists the field types as button, text, choice and signature, with the value held in a property whose format depends on the field type. Fields can be nested, so a field may have a full name made of parts, and a radio button group is stored as a parent with child buttons.
This is why a form can be read directly from its stored field values, without any text recognition: the answer is data, not a picture. What is stored and what a reader displays can still differ, as the XFA note below explains. It also means a form is only as readable as its fields. If the field structure is missing, the answers may be on the page and nowhere else.
Three ways a returned form stops holding data
First, the form may have been printed and scanned, or photographed. The file then holds page images only. Second, it may have been flattened, for example by printing to a new PDF or by a program that merges the answers into the page. The pypdf documentation describes flattening as turning field contents into regular page content, after which the leftover form widgets can be removed. Third, some forms use a different dynamic form format called XFA; the same documentation notes that an XFA entry can override the page content, so what you see and what the standard fields hold may differ.
- Printed and rescanned: no fields at all; text recognition would be needed, with no promised accuracy.
- Flattened: the answers look present, but no field holds them.
- Dynamic-form variant: test a sample before promising anything about the batch.
Decide what a checkbox or a blank becomes
A spreadsheet needs one rule per field type, written down before anyone extracts. For a checkbox: what does ticked become, what does unticked become, and what does never touched become? For a choice list: do you want the stored value or the label people saw? For a text field: is an empty answer blank, or a "no answer" marker? For a radio group: one column with the chosen option, or one column per option?
Test one form of each kind. A form where someone ticked one option, left one blank and typed a multi-line comment shows quickly whether the rules hold together.
- Write the rules in a short table beside the blank form.
- Keep dates exactly as typed and clean them in a separate step if they are mixed formats.
- Keep the original file name on every row so any answer can be traced back.
A safe first check, and the count that proves completeness
Open two returned files, one from a person using a desktop reader and one from a phone or a printer-to-PDF route, and click into an answer. If you can change it, the answer is a field. Keep the blank template so the field list can be compared with what comes back.
The completeness check is a count. Files received must equal rows written plus files listed as exceptions, with every file name appearing once. A file that arrived but produced neither a row nor an exception is a bug in the process.
Where the paid job fits, and where it does not
The one-off form extraction reads up to 200 returned files from one fillable template into one spreadsheet, from £245, and is accepted by the file-count reconciliation, a sample compared with what a PDF reader displays and a field list matching the blank template. The monthly version, from £395 a month, repeats it for each month's batch and is sold by proposal. Both prices are untested proposals. The one-off job is paid after your sign-off, and the monthly service is billed monthly under written terms you agree first. Neither starts until a secure way to hand over the files has been agreed in writing; no upload portal exists yet.
It does not fit forms that ask about health, money, legal matters or other personal subjects. For those, do not send anything; whether and how they could be handled would need a separate conversation. It also does not fit scanned forms. The first enquiry needs the blank form or its field list and the number of returned files, never completed forms.
Sources and limits
- pypdf documentation: interactions with PDF forms Checked 2026-10-11.
- Form field values can be read by name with get_fields or get_form_text_fields; the field type property is Button, Text, Choice or Signature and the value is held in /V, whose format depends on the field type.
- Radio buttons: get_fields returns the parent group while page annotations return the individual child buttons.
- Flattening turns field contents into regular page content and the leftover widgets can then be removed.
- A form may carry an XFA entry, and the page says the XFA form overrides the page content.