Extracting Filing Status and Dependents From a Form 1040
9 min read · updated August 11, 2026
The filing status cluster is five checkboxes in a row near the top of a Form 1040. It looks like the easiest thing on the page to extract, and it is the field where a model is most likely to give you an answer with no way of telling you it was a guess.
Five boxes, one enum
The five are single, married filing jointly, married filing separately, head of household, and qualifying surviving spouse. Exactly one applies to a return. That gives you a five-member enum and a hard invariant: precisely one box is marked, and zero or two marks is a document problem to surface rather than a tie to break.
One of the five was renamed. What is now “qualifying surviving spouse” was printed as “qualifying widow(er)” on earlier revisions of the form, for the same status. If you process returns from more than one year — and anyone handling amended returns or historical files does — your enum needs a stable internal identifier plus a per-year label map, so that a fifth box reading differently on a 2019 return still resolves to the same member. Keying the enum on the printed English is how a historical archive ends up with two statuses that are the same status.
The IRS publishes the current form and its instructions at About Form 1040. Read the revision you are processing; captions in this area have changed more than once.
The box that changes what a name means
Beside the checkbox row is a text field, and on current revisions its meaning is determined by which box was ticked. If married filing separately is checked, the taxpayer writes their spouse’s name there. If head of household or qualifying surviving spouse is checked, they write the qualifying person’s name there instead, in the case where that person is a child who is not claimed as a dependent.
So a schema with a field called spouse_name populated from that text is correct on one return and wrong on another, and the wrongness is invisible: a real person’s name lands in a field describing a relationship that does not exist. Extract the checkbox first, then interpret the string according to it, and store the raw text alongside whatever you resolve it to.
This ordering — resolve the discriminator, then read the field it governs — is the general pattern for every conditional area on a government form, and the 1040 has several.
What counts as a tick
On a scanned or photographed return the mark itself is the ambiguity. A tick may be a check, an X, a filled box, a diagonal stroke, or a pen line that starts in the intended box and overruns into the next one. A fold shadow reads as a mark. A speck from the scanner glass reads as a mark. And a return prepared by software has a printed glyph in a fixed position that looks nothing like handwriting.
The mistake is asking the model for the answer. “What is the filing status on this return” produces one of five words, in the same confident register as everything else, with no channel for uncertainty and no way to distinguish a clean tick from a smudge the model resolved on your behalf.
Ask instead for a per-box state — each of the five boxes reported as marked, unmarked or ambiguous, with a short description of what is in the box — and resolve it yourself:
boxes = {
"single": "unmarked",
"mfj": "unmarked",
"mfs": "marked",
"hoh": "ambiguous", # "faint diagonal stroke, may be a fold"
"qss": "unmarked",
}
marked = [k for k, v in boxes.items() if v == "marked"]
ambiguous = [k for k, v in boxes.items() if v == "ambiguous"]
if len(marked) == 1 and not ambiguous: accept
else: crop the cluster, re-ask, then reviewThe re-ask on a tight crop is worth the extra call for the same reason it is on a blurry receipt: the checkbox row occupies a tiny fraction of a full page, and sending it alone spends far more of the model’s effective resolution on it.
The dependents grid stops at four
Below the status cluster is a small table for dependents, with columns for name, taxpayer identification number, relationship to the taxpayer, and checkboxes indicating which credit the dependent qualifies for.
The printed grid has four rows. A taxpayer with five dependents ticks a box indicating there are more than four and attaches a statement listing the rest. An extractor that reads the grid and reports a dependent count is therefore capped at four, and a family of six comes back as a family of four — a wrong answer that is well-formed, internally consistent, and produced by a correct reading of the document’s printed area.
So the “more than four” checkbox is not a minor field. It is the flag that tells you the grid is a truncation, and it should be extracted before the rows and should force the record incomplete until the attachment is located. This is the same structural idea as the Schedule K-3 checkbox on a Schedule K-1: a mark on the form that reports on the completeness of the form.
Within a row, two further points. Identification numbers are sensitive and should be masked everywhere they are not strictly needed. And the per-row credit checkboxes are their own small mutually-exclusive cluster, so they deserve the same per-box treatment as the status cluster rather than a single question about which credit applies.
The nearby boxes that are not filing status
The top of a 1040 is crowded with other checkboxes within a few centimetres of the status row, and an extraction targeting “the checkboxes at the top” will collect them all.
- A digital asset question with its own yes and no boxes, which are not part of any other cluster.
- Standard deduction boxes indicating that the taxpayer or spouse can be claimed as a dependent on someone else’s return, or that a spouse itemises separately. These are independent flags, not mutually exclusive, so the single-mark invariant does not apply to them.
- Age and blindness boxes for taxpayer and spouse. The age caption embeds a literal date — born before a specific day in a specific year — and that year advances with every revision. Anything that learned this region from one year’s form and matches on caption text will silently stop matching, which is one of the reasons this page carries a revisit date.
Treating each cluster as a named group with its own invariant — exactly one of five, exactly one of two, any combination of four — is what keeps them apart. A flat list of checkbox states with no grouping cannot express that only one filing status may be marked, and so cannot detect the case where two were.