Open a checking statement from a large US bank and count the rows in the transaction table. Then count the transactions. On many statements those are different numbers, and the gap is the reason a lot of exported spreadsheets don't add up.
Several banks interleave a "daily ending balance" line inside the transaction list. It has a date on the left and a dollar amount on the right, aligned exactly like a real row. Structurally nothing distinguishes it. Only the description does.
Include it as a transaction and you've added a phantom entry worth your entire account balance. On a month with twenty of them, the export is unusable.
Credit card statements group charges under headings: Payments and Other Credits, Purchases, Cash Advances, Fees Charged. These headings sit inside the table region, in the same font, at the same left margin. A naive parser either treats them as transactions with no amount, or merges them into the description of whichever row follows.
"Beginning balance" is a dated row with an amount. It is not a transaction. Nothing moved. But it's worth keeping the number, because it's the starting point that lets you verify the very first real transaction. A tool that simply deletes the row loses that.
Each of these produces a spreadsheet that looks right. The dates are sensible, the amounts are real numbers, the formatting is clean. You only discover the problem when a total is off, and then you're hunting through hundreds of rows for something you have no reason to suspect.
It also poisons any automated categorisation downstream. A "DAILY ENDING BALANCE" row of $4,210.55 gets categorised as income, and now your monthly revenue figure is wrong in a way that compounds every month you repeat the process.
That last one is worth doing manually whatever tool you use: count the transactions on the final page of the PDF and check the tool found the same number.
Balance snapshots, category headers, and opening balances are recognized and handled correctly.
Try Statement → CSV