A prescribing information document is thirty pages of dense two-column text with a fixed skeleton underneath it. Almost every extraction problem on this document comes from matching that skeleton by heading text when the regulation gives you numbers.
The section order is fixed by regulation
US prescription drug labelling written to the Physician Labeling Rule format is specified at 21 CFR 201.56 and 201.57. The full prescribing information carries an unnumbered boxed warning where one applies, followed by seventeen numbered sections in a mandated order:
1 Indications and Usage 10 Overdosage
2 Dosage and Administration 11 Description
3 Dosage Forms and Strengths 12 Clinical Pharmacology
4 Contraindications 13 Nonclinical Toxicology
5 Warnings and Precautions 14 Clinical Studies
6 Adverse Reactions 15 References
7 Drug Interactions 16 How Supplied/Storage and Handling
8 Use in Specific Populations 17 Patient Counseling Information
9 Drug Abuse and Dependence
The order is the same for every product written to this format, from every manufacturer. Sections that do not apply may be omitted, and when they are, the numbering does not close up — the remaining sections keep their assigned numbers, so a document may run 1, 2, 3, 5, 6, 8, 11 and this is correct rather than a parsing failure. That single property is what makes section number a better anchor than anything else on the page: it is stable across manufacturers, it survives omissions, and it is printed at the start of the heading.
Subsections are numbered decimally beneath their parent — 2.1, 2.2 for dosing in particular populations, 5.1 onward for individual warnings — and the decimal numbering gives you the hierarchy without inferring it from font size. Extract the number and the title as separate fields and you have a tree.
Highlights duplicates the sections you want
This is the trap. PLR labelling opens with Highlights of Prescribing Information, a half-page summary that carries abbreviated versions of the same content: indications, dosage, contraindications, warnings, adverse reactions, drug interactions and use in specific populations, each with a cross reference to the full section. Then comes a table of contents, and only then the full prescribing information.
So the string “CONTRAINDICATIONS” appears at least three times in the document — in Highlights, in the table of contents, and as section 4. A pipeline that finds the heading and takes the text after it returns the two-line Highlights summary, which reads perfectly, is not obviously wrong, and is not the contraindications section. It also carries a statement telling the reader it is not comprehensive, which is the tell if you look for it and easy to miss if you do not.
The defences are structural. Locate the boundary between Highlights and the full prescribing information first — Highlights ends at the revision date line and the FPI begins at a heading that says so — and extract only from within the FPI region. Then, as a check, assert that every section you extracted appeared after that boundary and that no section number appears twice in your output. A duplicate section number means you have picked up the table of contents, which is the other common contaminant and which is easy to distinguish because its entries have no body text between them.
Anchoring on numbers, not on titles
Even inside the FPI, titles are less reliable than they look. Capitalisation varies, some manufacturers add a qualifier to a section heading, and the running header on each page frequently repeats the product name and a section name, which gives a text search several false hits per page.
A workable segmentation looks like this, and none of it is prompting:
- Recover text with coordinates and reading order resolved for two columns. Inserts are typeset in two or three narrow columns and reading order in the file is frequently not visual order — the same problem that afflicts academic PDFs, with the same coordinate-clustering answer.
- Find candidate headings by pattern: a line beginning with an integer from 1 to 17, or a decimal, followed by a title in a heavier or larger face than body text.
- Reject candidates whose number is out of order relative to the previous accepted heading. Section numbers ascend monotonically through the FPI, so a “5” appearing after a “12” is a cross reference in body text, not a heading.
- Take each section’s body as everything between its heading and the next accepted heading, with page headers and footers removed first by position — they repeat on every page and are trivially identifiable by that repetition.
Only after the document is segmented is a language model the right tool, and then for the thing it is good at: pulling a specific fact out of a known section. Ask for the paediatric age range from section 8.4 and you have given it three hundred words of relevant context; ask for it from the whole insert and you have given it thirty pages and a chance to answer from the Highlights summary instead. The general form of that argument is on the extract then reason page.
Old-format inserts and renumbered subsections
Two version problems will appear in any corpus of real inserts.
The first is non-PLR labelling. Products approved before the format was introduced, and never converted, use the older layout with no Highlights section, no numbering, and a different heading set that includes headings such as Clinical Pharmacology, Indications and Usage, Contraindications, Warnings, Precautions, Adverse Reactions and Dosage and Administration in a different order. A number-anchored parser finds nothing in these documents, which is the right behaviour provided you detect the format up front and route to a heading-based path rather than reporting an empty extraction. Detect it by the presence or absence of the Highlights block, which is unambiguous.
The second is subsection renumbering inside section 8. The Pregnancy and Lactation Labeling Rule replaced the old pregnancy letter categories and restructured that section, so an older insert’s 8.x subsections do not mean the same thing as a newer one’s. If you are keying data on subsection numbers across a corpus spanning that change, key on the subsection title as well and record the label revision date from the footer, which every insert carries.
Section numbering, subsection structure and the content requirements for Highlights are cited here as they stand in the current text of 21 CFR 201.56 and 201.57. These are amended, and the authoritative text is the regulation itself — check eCFR title 21 part 201 before writing a section number into validation logic.
The structured version may already exist
Before building any of this, check whether you need to. US labelling is submitted to the FDA as Structured Product Labeling, an HL7 XML standard in which each section is already tagged and identified by a LOINC code, and the agency republishes those files through DailyMed. The document you were about to parse from a scan exists as a tree with the sections already delimited.
That does not make the extraction problem disappear — SPL section bodies still contain tables and nested content, foreign labelling is not in SPL at all, and a printed insert in a carton in a warehouse is not the same artefact as a record in a public database — but it changes what your pipeline is for. Reading the paper becomes the fallback for documents outside the database and a verification path for documents inside it, rather than the primary source. Reaching for the publisher before reaching for a vision model is the cheapest decision available on this document.
Where you do have to read the paper, a corpus of inserts is a long-page vision workload with a wrinkle: a run that hits a document a model declines to process, or a provider outage two thousand pages in, has to continue on another model without a schema change. That is a routing and fallback problem more than a prompting one, and it is worth having the fallback path exercised before the run rather than during it.
Top comments (0)