Table Extraction From Financial PDFs
Why pulling a clean, structured table out of a financial filing's PDF is harder than it looks, and the practical techniques — from layout analysis to LLM-assisted parsing — used to turn a page of visually-aligned text back into rows and columns.
Prerequisites: Structured Extraction From Filings With LLMs
A quarterly earnings filing has a balance sheet laid out as a table — line items down the left, values in columns for the current and prior period. To a human, the table is obvious: columns line up visually, rows are clearly separated. To a computer, a PDF typically contains no concept of "table" at all — just a collection of text pieces, each with an x-y position, with no built-in label saying which belong to the same row. Extracting a usable table means reconstructing that structure from position data, or from an LLM's read of the layout.
The idea: a PDF describes ink positions, not structure
Most PDFs record text as instructions like "draw this string starting at this x-y coordinate" — optimized for visual rendering, not logical structure. A table row and a paragraph are stored identically at this level: just strings with page coordinates. Reconstructing "this is a table" means inferring structure from that layout — text whose y-coordinates cluster together is probably the same row; text whose x-coordinates line up down the page is probably the same column.
Two broad approaches handle this. Layout-based extraction tools (pdfplumber, Camelot) look for visual cues — ruled lines, consistent column gaps, aligned whitespace — and use geometric rules to group text into rows and columns. This works well on cleanly gridlined filings, and fails on inconsistent spacing, merged cells, or footnote markers that break the expected alignment. LLM-assisted extraction instead feeds the page's text or an image directly to a language model and asks it to output the table's structure, leveraging its ability to recognize "this looks like a table row" the way a human would even on messy layouts — at the cost of needing schema-constrained output to make the answer usable downstream, and needing verification since the model can misread values.
Worked example: a footnote marker breaking a naive column split
Consider a row: "Total revenue" followed by two numbers (in millions), where the current-period number also carries a footnote reference, rendered as "1,245¹" with the superscript "1" positioned slightly above and to the right. A layout tool splitting purely by x-coordinate gaps might see three fragments in that cell — "1,245", the superscript, a stray gap — and either misread the value as "12451" or split the row into the wrong column count, throwing off every column to its right.
A well-tuned layout pipeline handles this by treating small superscript-sized text at a different y-baseline as a footnote marker to strip, verified by checking the row's column count matches the header row. An LLM-assisted approach handles it differently: asked to extract revenue as a number, it typically recognizes "1,245¹" as 1,245 with a footnote, the way a human reader would — but that correctness needs checking against the source, since a model can occasionally merge or drop a footnote incorrectly with no visible sign.
Treat that curve as "extraction accuracy" against "how standardized the layout is": both do well on clean, gridlined tables, but layout-based extraction degrades faster as formatting gets messier, since geometric rules have no fallback once their spacing assumptions stop holding.
What this means in practice
Neither approach is complete alone for a production pipeline processing filings from many companies, each with its own PDF-generation quirks: layout-based extraction is fast and cheap on standardized layouts, while LLM-assisted extraction handles messier layouts better but costs more per page and needs its output checked, since a model can misread a number confidently and silently. A common pattern runs the cheap layout extractor first and falls back to LLM-assisted extraction only where the layout tool's confidence signals — inconsistent column counts across rows, for instance — suggest it failed.
A PDF stores positioned text, not table structure, so extracting a table means reconstructing rows and columns from layout cues (fast but brittle on messy formatting) or an LLM's understanding of the page (more robust, but needing verification since a confident misread produces no visible error).
The easy trap is trusting an extracted number just because it parsed cleanly into a table cell — whether from a layout tool or an LLM. A misplaced footnote marker, a merged column, or a model's confident misread can all produce a plausible-looking number that is simply wrong, with nothing in the pipeline's output to flag it. Spot-checking extracted values against the original page, especially for figures feeding directly into a trading signal, isn't optional.
Related concepts
Practice in interviews
Further reading
- Camelot / pdfplumber documentation, table extraction from PDFs
- SEC EDGAR documentation, filing formats