Pull the tables out of a PDF into a real spreadsheet — separate columns, numbers you can actually sum, and a preview so you can see what was found before you download. It runs on your device; the PDF is never uploaded.
Yes — Convertlo turns a PDF into an editable spreadsheet, and it does it in your browser. Drop the PDF in (nothing is uploaded), optionally set a page range, press Extract tables, check every page in the preview and correct any cell by double-clicking it, then download .xlsx, .csv or .json.
12A stay text rather than being guessed at.| Capability | Supported | Detail |
|---|---|---|
| Input | ||
| Digital PDF | Yes | Text-based PDFs from any producer. |
| Scanned PDF | Yes | Tick Read scanned pages (OCR). |
| Image PDF | Yes | Same as a scan — pages holding a picture rather than characters. |
| OCR | Yes | Tesseract in WebAssembly, running on your device. English only. |
| Multi-page PDF | Yes | No page limit. |
| Password-protected PDF | Yes | You type the password; it is used on your device only. |
| Photo or screenshot | Yes | Via image to PDF first. |
| Handwriting | No | Printed characters only. |
| Batch of many files | No | One document at a time — there is no server to queue on. |
| Extraction | ||
| Table extraction | Yes | From the ruling lines where a table has them; from the whitespace where it does not. |
| Rows and columns | Yes | Recovered from position, since a PDF stores no table. |
| Multi-page tables | Yes | Grouped into one sheet; repeated headings removed and counted. |
| Several tables per page | Yes | Stacked or side by side, detected and offered separately. |
| Page selection | Yes | A page range such as 1-3, 7. |
| Table selection | Yes | Tap a detected table or drag a box round any area. |
| Numeric values | Yes | Thousands separators dropped; brackets become negatives. |
| Percentages | Yes | 12% becomes 0.12. |
| Financial values | Yes | Debit, credit, balance, amount and account columns identified and typed. |
| Statement reconciliation | Yes | Opening − debits + credits = closing, checked and reported. |
| Formatting preserved | Yes | Optional: fonts, colours, borders, alignment, widths, merges. |
| Cell editing before download | Yes | Double-click any cell in the preview. |
| Dates | No | Converted only when the order is unambiguous; otherwise left exactly as printed. |
| Output | ||
| Excel XLSX | Yes | One sheet per table, with real column widths. |
| CSV | Yes | No sheets, so several tables land in one grid. |
| JSON | Yes | Records keyed by the table’s own column names, with typed numbers. |
| Google Sheets | Yes | By clipboard — tab-separated text plus an HTML table, so it lands in cells. |
| Excel XLS (97–2003) | No | Not written. .xlsx opens in Excel 2007 and later, Numbers, LibreOffice and Sheets. |
| API | No | A browser page, not an endpoint. There is no key to get. |
| Processing | ||
| Local processing | Yes | Reading, recognising and writing all happen in your browser. |
| No file upload | Yes | Verifiable in the Network tab — no request carries your document. |
| No server processing | Yes | Which is why there is no page limit, no queue and no watermark. |
| No signup | Yes | No account, no sign-in, no email. |
| Free | Yes | Nothing is metered, because nothing runs on our machines. |
| Watermark | No | None, on any output. |
| Offline use | No | The page and the OCR engine have to load first. Once they have, the conversion itself needs no network. |
Every row is behaviour the page ships today, and each one is checked against the tool itself by our test suite — including the No rows, which are there on purpose. A capability stated falsely is worse than one not stated.
A PDF has no idea it contains a table. It stores each fragment of text with a position on the page, and the rows and columns you see are just an arrangement of those positions. Any converter has to infer the grid back out.
The naive approach groups text by where each fragment starts horizontally. It falls apart on the most common table there is: one with right-aligned figures. A column of numbers aligned to the right starts at a different horizontal position on every row, so grouping by start position invents a new column for each one.
This tool works from the whitespace instead. Every fragment occupies a horizontal band, those bands are merged across the whole page, and the gaps left between them are the column separators. Left-aligned labels, right-aligned totals and centred headings all resolve to the same columns because the gaps between them are the same either way.
It is the title. A page headed Acme Bank — Statement of Account with Page 1 of 3 over on the right holds two pieces of text separated by a wide gap, which is precisely what a table row looks like from the outside. But the title string itself is long enough to cover the gap between the first two columns — and because the bands are a union, one line covering a gap is enough to weld two columns together for every row on the page.
Measured on a five-column statement: Date and Description came back in the same cell on every row of every page. That is the single most common document anyone brings to a converter like this, so it is worth being precise about the fix.
Throwing the row away is the wrong answer. A subtotal line reading TOTAL … 4.65 also holds exactly two cells, and losing a real data row is far worse than keeping a heading. So the rows that end up in the spreadsheet and the rows that decide where the columns go are treated as two different sets. Rows are considered most table-like first, and a row is only given a say in the column positions if adding it does not merge columns the earlier rows already agreed on. A title line is kept out of that vote and still lands in the sheet, in the columns the vote produced.
Two simpler rules were tried first and both measured wrong, which is worth recording because both sound obviously right. Ignoring rows set in a larger font than the body wrecks any table whose header is bigger than its body — the header is frequently the only row that establishes the last column, so that column vanishes. Ignoring rows with too few cells fixes a five-column statement and cannot help a three-column one, where a two-cell title is only one cell short of a real row.
Inferring a grid is only necessary when the PDF does not state one. A table drawn with borders already contains its own geometry: the rules are vector paths in the page, with exact coordinates. Where they are present this tool reads them and uses them, and only falls back to the whitespace method when they are not.
That matters most for the cases inference gets wrong. A heading sitting above a table no longer bridges the gaps between its columns, because the heading is outside the rules. An empty cell stays an empty cell rather than shifting everything after it. A cell whose text wraps onto a second line stays one cell.
Reading the rules as vectors is also why this stays fast and exact. Camelot, the best-known implementation of the same idea, renders the page to an image first and finds the lines in pixels; here they are read straight from the page's own drawing operators, so there is no rendering step and no resolution to lose. Borders that are drawn as very thin filled rectangles rather than strokes — which plenty of producers do — are picked up too.
A framed callout is not a table, so the rules have to enclose at least two rows and two columns before they are treated as one, and a single underline under a heading is ignored.
A spreadsheet full of numbers stored as text is barely more useful than the PDF. Cells that are unambiguously numeric are converted to real numeric values: thousands separators are removed, a figure in brackets becomes a negative in the accounting convention, and a percentage becomes the fraction Excel expects.
Anything that could be misread is deliberately left alone. Dates keep their formatting rather than turning into serial numbers, and a reference like 12A or 1.2.3 stays exactly as written. Guessing wrong on a reference number is worse than leaving it as text.
One sheet per page and everything in one sheet are both wrong for the commonest multi-page document there is. A statement whose transactions run from page 1 to page 3 and whose summary sits on page 4 is two tables, not four and not one. Per page you get the transactions cut into three; all in one welds the summary onto the end of them, where its Category column lands under Date.
Merge matching tables groups the pages first and gives each table its own sheet, named after whatever the document calls it. A page continues the one before it when all three of these hold:
We measured this over ten multi-page PDFs built for the purpose, run through this page's own extraction engine. Every genuine continuation had all of its column positions line up, including one whose widest cell grew on the second page and shifted a column along. The case where the positions are the only evidence available — a different table with the same number of columns and no header at all — had a third of them line up. So the rule is “all of them”, with no threshold to tune. Take that test out and exactly that document is merged into the statement, silently, because nothing in the sheet would say so. The other tests carry the other documents: the column count is the only thing separating a page whose Credit column is empty, and the header is the only thing separating two tables of the same width under different headings. Across all ten documents the grouping is right on every one, with no table wrongly merged and none wrongly split.
The failure that matters is a wrong merge, so every rule leans against it. Two tables in one sheet means a column stops meaning the same thing halfway down and nothing tells you. A wrong split is in front of you in the preview, and the other two modes are one dropdown away. That is also why the mode is only ever suggested — when the grouping finds a table that really does run across pages — and never forced.
One measured limitation, worth knowing before you trust it. A column that is empty on one page of a table — a Credit column on a page with no credits — is dropped from that page, so it comes back with fewer columns than its neighbours and is treated as a separate table. Merging it anyway would shift every cell one column across from that row down, which is worse than an extra sheet. Use All pages in one sheet for that document, or ✂ Choose table to line the pages up by hand.
Sheet names come out of the document: the first line above the table on its first page, trimmed to the 31 characters Excel allows, with the characters Excel forbids removed and a number added if two tables share a name. Nothing is invented — a table with no heading above it is called Table 1.
A statement or a long report prints its column header at the top of every page. Merge those pages into one sheet naively and you get a header row sitting in the middle of your data — which quietly breaks a sort, and every pivot table and SUM built on top of it. The row looks harmless until the day the numbers are wrong.
A repeated header is removed here, and the count is reported rather than done silently. The rule is deliberately narrow: a row is only treated as a running header if it appears near the top of every page, and only the first few rows of each page are ever considered, so a header can never be matched against the body. A genuine data row repeating word for word at the top of all of them is not something that happens; leaving a header in would be a nuisance, but dropping a row of real data would be a fault. Turn the checkbox off and every header is kept.
Two things that look like details and are not. The rule cannot be “drop the first row of each page after the first”, because the first row of a real statement is its title, not its header. It cannot be a longest-common-prefix either, because that title reads Page 2 of 3 and so never matches the one before it. And when a running header is found, the pages are evidently one continuous table, so no blank separator row is inserted between them — a blank row breaks a sort exactly as effectively as a stray header does.
Beside the download there is 📋 Copy for Google Sheets and a link that opens a blank Sheet. Copy, switch tab, press Ctrl+V — the table lands in cells, not in one column. The button names the table it will copy, and in merge matching tables mode that is the whole running table, the same thing the download would put on one sheet.
What goes on the clipboard is not a CSV, and that is the whole trick. A CSV pasted into a Sheet arrives as a single column until you go and find Data → Split text to columns. Spreadsheets talk to each other in tab-separated text, so that is what the text flavour is — and the clipboard also carries an HTML table in the same write, which is what a spreadsheet actually prefers.
Two flavours is not belt and braces. Tab-separated text has no quoting convention that survives a paste, so a cell containing a tab or a line break destroys the row it is in. We measured it: a seven-row table with one tab and one line break in it comes back from a tab-separated parse as eight rows, every one of them a column too wide — silently, with no error anywhere. The HTML flavour has no such problem, because its cell boundaries are tags rather than characters. Anything that only sends tab-separated text is carrying that bug whether it knows it or not.
A cell whose text begins with =, +, - or @ is a formula to every spreadsheet ever written. A phone number typed +44 20 7946 0958 becomes an error; a +4 in a Change column silently becomes the number 4. So those cells get a leading apostrophe, the universal "keep this as text" marker, and the count is reported next to the button rather than done quietly.
The guard is deliberately narrow, and the narrowness is the safety. A cell this tool turned into a real number is never touched, so a negative figure keeps its minus sign and stays a number you can sum. Only text is prefixed. Measured across every test document in this project — 1,866 cells — 26 began with one of those characters: 20 were text and are protected, 6 were genuine negative numbers and are left exactly as they are.
The reason to do this at all is that the paste and the download have to agree. +4 is a text cell in the .xlsx, so it has to be a text cell in the Sheet too; without the apostrophe the two outputs would quietly differ and you would have no way of knowing which one was right. The test suite compares them cell by cell.
Because it would mean handing a web page access to your Google Drive, and this page does not ask for that. Every converter that offers one-click export has to: it signs you in, takes a Drive permission, and creates the file from its own servers.
Be clear about what the clipboard does and does not buy you, though. Once the table is in a Google Sheet it is on Google's servers — that is what a Sheet is. The difference is that you choose the moment, it is only the table and never the PDF, and this page never gets a token to your account. The PDF itself is read entirely on your device either way. If you would rather not involve Google at all, download the .xlsx and open it in Excel, Numbers or LibreOffice.
For a big table the download is still the better route: in Google Sheets use File → Import → Upload and pick the .xlsx, which brings the column widths with it. The clipboard is the fast path for one table you can see.
The Output control picks between two jobs that pull in opposite directions.
| Structured data | Preserve appearance | |
|---|---|---|
| For | Sorting, formulas, pivot tables, feeding something else | Reading, sharing, keeping a document recognisable |
| Gives you | Clean columns — Date | Description | Amount | The same columns, wearing the page's fonts, colours and rules |
| Extra download | None | About a megabyte of writing library, once |
Structured data is the default and is unchanged — if that is what you were using, nothing about it moves. Preserve appearance is the same extraction with the formatting painted back on, so the cells hold exactly the same values either way.
Each of these was measured against a deliberately over-formatted statement — bold white header on a dark fill, alternating row shading, ruled borders, right-aligned figures, a red negative, a merged title band and five different column widths — and each is read back out of the finished .xlsx in the test suite rather than taken on trust:
A PDF does not contain a table. It contains characters at coordinates and shapes at coordinates; the rows and columns you see are an arrangement your eye makes. Everything above is inferred from that, so the honest limits are real ones:
If what you need is a picture of the page rather than a spreadsheet of it, a converter is the wrong tool — that is what printing to PDF already gave you.
Drop in a locked PDF and the page asks for the password, opens it, and extracts the table. The password is typed here, used here, and goes nowhere else — the same promise the document itself gets. It is held in memory for the length of one conversion: not sent anywhere, not written to storage, not put in the address bar, not logged, and cleared out of the field the moment it is accepted. There is nothing to clean up afterwards because nothing was kept.
That is the part a tool running on someone else's server cannot offer. Uploading a confidential PDF is one decision; uploading it together with the password that opens it is a different one, and it is the reason a lot of people never convert these documents at all.
This is the most misunderstood thing about PDF security, and getting it wrong means asking people for a password they have never had.
| User password (open password) | Owner password (permissions password) | |
|---|---|---|
| What it does | Encrypts the contents. Without it there is nothing to read. | Sets flags asking readers not to copy, print or edit. |
| Can anything open the file without it? | No. | Yes — it opens for everyone. |
| What this page does | Asks you for it. | Opens it and extracts, with no prompt. |
An owner password does not encrypt anything against the reader. The file is stored with an empty user password, so it opens normally; the restrictions are a flag that a viewer may choose to honour, and the PDF engine in your browser — like every other PDF library — simply does not. We verified this rather than assuming it: a PDF carrying only an owner password opens here with no password at all, and its text comes straight out.
So this page does not prompt for one, because there is nothing you could usefully type. If that is not what you wanted from the restriction, the honest answer is that the PDF format never delivered it; a permissions flag is a request, not a lock.
All four schemes the format uses, each tested end to end against a genuinely encrypted file: RC4 40-bit, RC4 128-bit, AES-128 and AES-256. If your PDF opens in a reader with a password, it opens here with the same one.
What this will not do is work out a password you do not have. There is no guessing and no brute force — with AES-256 that is not a policy, it is arithmetic. A wrong password is reported as wrong, and you can try again as often as you like; each attempt happens on your own machine, so nobody is counting them.
If you want the password gone from the file for good rather than just for this conversion, unlock-pdf takes the PDF and the password and writes out an unprotected copy — also in your browser.
Pick JSON (.json) in the format control and a table becomes an array of records, keyed by its own column names:
[
{
"date": "2026-09-04",
"description": "Deposit",
"amount": 3420
}
]
Note 3420 and not "3420". The same Numbers as numbers tick that makes a cell summable in Excel makes it a JSON number, so an accounting negative in brackets comes out as -123 and a percentage as 0.12. Untick it and every value is a string.
Not in the JSON — in working out which row of a PDF holds the field names. Get that wrong and every record is keyed off something that is not a column name, which is both useless and hard to notice.
We measured the route this replaces. It took row 0 of every page stacked together and used that as the field names — and row 0 of a real document is the title. Across the 37 test documents in this project, 12 came back with at least one unusable key — 28 keys in all: an empty string, a _1 collision artifact, or page furniture like "Page 1 of 2" standing in as a field name. One bank statement produced {"": …, "Northbridge Bank": …, "_1": …, "Page 1 of 2": …}. And every value was a string, including money.
The rule now used finds the header row instead of assuming it, and it is right on all 37:
Date | Description | Amount from the transactions under it.Name | Email, Time | Monday — where the first can never fire. Every cell has to be filled, which is what rejects a ragged metadata line while still accepting a real header.14/04/2026 16:42 · Till 3 · Served by Amy line becomes your field names.A table that simply starts with data has no header, and the page says so rather than inventing one. Its fields are numbered column_1, column_2 and nothing is lost. That is the safe answer: keying records off a data row would swallow that row into the key names. If the detection gets it wrong either way, untick First row is field names and you get numbered fields with every row kept.
Payments | Amount | Deductions | Amount. Two keys called amount means one column overwrites the other in every record; the second becomes amount_2.column_2, not "". An empty key is legal JSON and useless, and two of them collide.null, not "", and every record carries every key — so the shape is fixed and row.amount ?? 0 does what you expect..xlsx, where it is a row like any other, but {"date": null, "description": "Acme Bank Statement"} is not a row of the table.One table gives the bare array above — what everyone means by "PDF to JSON". Several give {"tables":[{"name": …, "pages": […], "rows": […]}]}, because flattening a statement and its summary into one list would silently mix records of two different shapes. Which one you are getting is written next to the download button, and the preview shows a real record before you commit to anything.
The Sheets control decides how many tables there are, exactly as it does for Excel — so the JSON and the .xlsx can never describe different things. Choosing All pages in one sheet always gives the bare array.
Set Extraction to Financial and two things change. Every column is given a role — date, description, money out, money in, balance, amount, account — and the cells are typed accordingly: money as a number carrying a #,##0.00 format, a percentage as the fraction Excel expects, a date as a real Excel date, and an account number pinned to text. Then, if the document is a statement, the arithmetic is checked: opening balance − debits + credits = closing balance.
That last one is the part no format-based check can do. Extraction from a PDF is inference, and the failure that survives every other test is a digit: a cell that reads 1550.00 where the page says 1250.00 is a perfectly well-formed number in a perfectly well-formed money column. Nothing about its shape is wrong. The only thing that knows it is wrong is the balance underneath it.
We took a statement that reconciles to the penny and changed one digit in one cell. Measured on the real extraction, through the shipped engine:
| Document | Verdict |
|---|---|
| Statement, extracted correctly | ✓ Reconciles. Opening 1842.17 − debits 1523.94 + credits 5580.22 = closing 5898.45, out by 0.00. |
| Same statement, one digit misread | ⚠ Does not add up — out by 300.00. |
It deliberately does not say which cell. One misread figure breaks the arithmetic of every row after it, so a per-cell version accuses correct cells as often as wrong ones — we measured that directly and it ran at 14–17% precision, which is why it is not here. One verdict about the whole document is a true statement; a pointed finger would not be.
Telling somebody their good data is broken is the expensive failure, so the check declines far more often than it runs. It needs a balance column, a debit and credit pair or a single signed amount column, and at least three balances to follow; short of any of that it says what is missing and claims nothing about the totals.
Thirteen other documents from our test set went through it — invoices, receipts, a purchase order, a payslip, a financial report, a price list, a timetable, a quotation, a delivery note, a generic table and a supplier's statement of account. Eleven declined to check at all. The two that were checked were themselves statements, and both reconciled. Not one document was told its figures were wrong when they were not.
A disagreement is also not proof that the extraction is at fault. A statement can carry a line this arithmetic does not know about — an interest adjustment printed outside the columns, a brought-forward figure that is not a transaction — and the page says so rather than pronouncing on it. What the number gives you is a reason to look, and where to look first.
03/04/2026 is the third of April to half the world and the fourth of March to the other half, and a PDF does not record which. Guessing silently rewrites every date in the column, and a statement with the months and days swapped is worse than one that never became a date at all.
So a date column becomes real Excel dates only when something in it settles the order: a day component above 12 somewhere in the column, an ISO 2026-03-04 shape, or a month name. Otherwise every value is left exactly as it was printed, and the page says why. Nothing is half-converted — the whole column goes one way or the other, so a column of dates can never end up as a mixture of real dates and text that sorts differently.
Because a spreadsheet will destroy them otherwise. 00417829 becomes 417829 the moment it is a number, and a sort code like 20-31-05 is read as a date by every spreadsheet that has ever existed. Account numbers, sort codes, IBANs and masked card numbers are pinned to text format, so they arrive exactly as printed and stay that way when the file is reopened.
Drop in a bank statement and the page says Bank statement detected. Six kinds are recognised, and each one changes what the page suggests next. The label is advice about what to do; the decision to combine the pages is taken separately, from whether a table really does run across them, because a statement whose pages do not line up is exactly the document that combining would spoil:
| Detected | What follows from it |
|---|---|
| Bank statement | One table running across pages, so the transactions become one sheet and the repeated header is dropped — both shown in the controls, both reversible |
| Invoice | The line items are one block with an address and totals around them; ✂ Choose table takes just the items |
| Purchase order | Same shape — the ordered lines are one block among delivery details |
| Receipt | Usually photographed rather than exported, so the OCR tick is the thing to reach for |
| Payslip | Payments and deductions sit side by side and read as one wide table; take them one at a time |
| Financial report | Often several tables to a page, and brackets for negatives — both already handled |
| Anything else | Nothing is said at all |
The label never changes what was extracted, and it no longer changes any setting either. It tells you what the page thinks it is holding and what to reach for next. The one setting that is chosen for you — combining pages — comes from the pages themselves rather than from the label, and is visible in the control directly above the preview and reversible in a click. A label that quietly reshaped your grid would be a worse version of the problem it is meant to solve.
The hard part is not recognising a bank statement. It is refusing everything else. A quotation carries every commercial word an invoice has — unit price, subtotal, VAT, total — and is not an invoice. A delivery note carries every structural word of a purchase order — supplier, deliver to, part number, quantity — and is not one. A remittance advice lists invoice numbers on every line. A supplier's statement of account says both "statement of account" and "invoice number", with an opening and closing balance. We built all four, and a fifth that talks like a bank while being an invoice, and tested against them: 15 of 15 correct, with no document given the wrong label.
Three rules get there, and the thresholds are where they are because that is where all three matter. A type has to name itself — without that gate the delivery note becomes a purchase order at any threshold, because its vocabulary is a purchase order's. It has to clear a score floor, or the remittance advice becomes an invoice. And it has to beat the runner-up by a margin, or the supplier's statement of account becomes a Bank statement — which is the one that would actually mislead somebody. Set the floor higher and the gates stop changing any outcome at all; that is how this was nearly shipped carrying two rules that did nothing.
Two honest limits. It reads English printed phrases, so a French invoice will simply not be recognised — that is a missing label, not a failed conversion, and everything else works as normal. And a document that is none of the six says nothing rather than guessing: a survey table, a timetable and a trade price list all go through silently, which is the behaviour you want from something that only speaks when it knows.
The preview covers every page that produced rows, not just the first: step through them with the arrows or jump straight to one from the list. A converter that shows you page 1 and lets you discover page 7 in Excel is not really offering you a check. Each page also says which method produced it — read from the table's own ruling lines, or inferred from the spacing — so you know how much to trust it before you open the file.
The workbook itself is set up to be readable on opening: columns are sized to their contents rather than left at Excel's default of about eight characters, which otherwise leaves every description column truncated until you widen it by hand.
Every column is shown, not the first few, because the point of the preview is to check the cells rather than glance at them — and anything that came out wrong can be corrected in place before you download.
When a cell cannot be what its column is, the preview marks it and the page says Review 2 cells before export rather than letting you find out in Excel. The classic case is a scan that read a zero as the letter O:
| Cell | Why | |
|---|---|---|
1,250.00 | ✓ | a number in a column of numbers |
12O0.00 | ⚠ | contains a letter, so it cannot be one |
This is not a confidence score, and the difference is the whole design. A confidence score asks the recogniser how sure it felt. We measured that on our own scans and turned it down: the words it read wrongly averaged 84 and the words it read correctly averaged 89. Re-measured head to head against what ships, a confidence threshold flags cells on a 100 dpi scan that contains no errors at all, and runs at 38% and 56% precision on the two degraded pages — four flags in ten being false alarms at best.
The check that ships asks a question with an answer instead: is this cell consistent with the column it sits in? 12O0.00 in a money column is not a hesitant reading — the recogniser may be perfectly sure of it — it is a cell that cannot be a number where everything around it is. Measured on the same pages, that flagged 2 of 2 and 9 of 9 genuinely wrong cells and nothing else: 100% precision, and nothing at all on six correctly-extracted typed tables. On a grid deliberately corrupted with the classic confusions — O for 0, l for 1, S for 5 — it found every one.
The unflattering half, which matters just as much: this finds one kind of error, not all of them — it catches about one in five of the mistakes OCR makes on a bad scan. Most of the rest are in description text, where there is nothing to check a word against. So a page with no marks is not a page with no errors, and the copy will not pretend otherwise — the marks are a head start, not a guarantee, which is why the preview still shows you every row.
We also built the obvious companion — checking that a running balance column actually adds up — and did not ship it. On a clean document it is perfect and finds nothing; on the degraded scans where it would earn its keep it ran at 14–17% precision, and on the worst page the column was mangled enough that it could not recognise a balance column at all and raised nothing. One misread balance also breaks the arithmetic of two rows, so it points at a correct cell as often as a wrong one. A flag you cannot trust is worse than no flag, because you stop reading.
Reading a table out of a PDF is inference — a PDF stores positioned text, not rows and columns — so on a difficult document a handful of cells come out wrong however good the rules are. The old answer was to download the workbook and fix them in Excel, with the original PDF no longer in front of you. Now you fix them here: double-click any cell, including the header row, type, and press Enter.
It works from the keyboard as well, because a table of corrections done only with a mouse is slower than the spreadsheet you are trying to avoid. Tab to a cell and press Enter or F2 to open it; Enter saves, Esc cancels, and Tab saves and moves to the next cell.
An edit is stored against the cell, not written into the extraction. That sounds like an implementation detail and it is the reason everything else keeps working: switch between one sheet per page and a merged sheet, turn numeric typing on and off, change to CSV — your corrections survive all of it, and undo puts the page back to exactly what was read from the PDF. Type the extracted value back into a cell and the edit is removed rather than recorded as one that happens to match, so the count beside the download only ever reports work you actually did.
An edited number is typed the way the workbook types it, so the screen shows what Excel will receive rather than what you typed: enter 1,250.00 and the cell right-aligns as 1250, a real number you can sum. Clearing a cell is a real edit too — an empty cell stays empty rather than the old value quietly returning.
Cells the page can tell are wrong are marked for you before you start — see cells that need a second look. That check is deliberately not a confidence score, and that section explains why.
Two limits worth knowing. You can correct cells here, not add or delete rows and columns — that is a spreadsheet's job and you have one. And nothing is stored: edits live in the page while it is open, so reloading loses them, which is the same reason your PDF never reaches a server.
A report page is not a table. It is a title, a paragraph, a table, a heading and then another table — and a converter that reads the whole page merges all of it into one grid. Here is what that actually costs, measured on a page carrying a three-column headcount table above a five-column revenue table: read whole, it comes back as eleven rows of six columns, with every row half empty and both headers sitting in the wrong places. Read separately, the same page gives a clean 5 × 3 and a clean 5 × 5.
So after extraction each page offers ✂ Choose table. The page is drawn as you would see it in a reader, with any tables it found outlined on top. Tap one to extract just that table, or drag a box round any area at all — a quarter of an invoice, one block of a financial statement, the left half of a two-up layout. The sheet and the download rebuild immediately, and Whole page puts it back. Nothing is uploaded to do this either; the page is rendered and the selection applied on your device.
Four rules, and each one was kept because there is a document only it can handle: a line that is not part of a table ends the block above it; a vertical gap more than twice the normal row spacing starts a new one; a sustained change of two or more columns starts a new one; and that change has to last two rows before it counts. That last rule is not fussiness — without it a SUBTOTAL … 2,470 line in a five-column table splits the table in half, which we measured before fixing it. A single empty column is only a difference of one, so a statement with nothing in its Credit column stays one table.
Tables set side by side are found too, and this one is worth explaining because the obvious approach is wrong. You cannot look for the widest column of whitespace and call it the gutter. On an ordinary invoice — a label column on the left, figures pushed over to the right — the gap inside the table measures 60.5 character-widths, three times wider than the real gutter in a genuine two-up layout, which measures 19.4. Every width threshold that finds the gutter also cuts that invoice in half, and cutting a real table in half is a worse outcome than not splitting at all.
So the test is structural instead. Only the widest gap in a block is ever a candidate. Both sides of it have to hold at least two columns of their own — that is what rescues the invoice, whose widest gap has a single column to its left, and the statement, whose widest gap has one column to its right. The gutter has to be at least ten character-widths, which keeps a tight four-column table (widest internal gap: 6.6) intact. And it has to be at least 1.4 times the next widest gap: a real gutter scores 1.63, while a subtotal table scores 1.13 and a statement 1.11.
What it still will not catch: a two-up layout whose gutter is no wider than the gaps between its own columns — we measured one at 9.4 character-widths against column gaps of 9.0, a ratio of 1.04. That is genuinely ambiguous from position alone, and the page offers nothing rather than guessing, because the cost of guessing wrong is a table cut in half. Drag a box round each side and it takes a second — and if you do not need them as two sheets, this is the layout whole-page reading already handles best: both of our two-up fixtures come back as six clean columns with no empty cells at all, just the two tables' columns in one grid. It also stays quiet when it finds only one table, because one table is not a choice.
Drawing a selection is the feature every competitor puts behind an upload: SimpleTool, CatchPDF and Adobe all offer a visual table selection, and all of them send your document to a server to do it. A PDF you would want to crop a table out of — an invoice, a payroll report, a bank statement — is usually exactly the sort of PDF you would rather not upload.
A scan is a picture of a page. There is no text in the file at all, so there is nothing to place in cells — which is why most converters hand back an empty spreadsheet, and why the honest ones tell you to go and find an OCR tool. Tick Read scanned pages (OCR) and this page reads them itself.
The recognition runs on your device, the same as everything else here. Nothing is sent anywhere: the only thing that leaves your browser is a one-off download of about 6 MB of recognition engine from a CDN, which the browser then caches. That is the part worth saying out loud, because every other OCR converter for scanned PDFs — Adobe, Smallpdf, OnlineOCR — uploads your document to a server to do it. A scanned bank statement or payroll report is exactly the kind of file you would rather not upload.
It is decided per page, so a document with a scanned insert among typed pages works throughout: pages that have text are read from their text layer, pages that do not are recognised. The preview marks which is which, and so does the page list.
Two different things are being asked here, and they have very different answers. We measured both by building scanned PDFs at known quality and running them through this exact pipeline.
The table structure is the reliable part. Every degradation we tried still produced all five columns of a five-column statement: 150 dpi, 100 dpi, 75 dpi, even 56 dpi with heavy grain, JPEG quality 0.4, and up to 1.5° of skew. Empty cells stayed empty instead of shifting the row along. That is because the columns come from where the words sit on the page, and a word's position survives a bad scan long after its letters stop being legible.
The characters are a recognition, and recognitions are wrong sometimes. On a 30-row statement scanned at 150 dpi we got every one of the 60 money figures exactly right. On a deliberately rough 82 dpi version of the same page, 53 of 60 — so seven wrong numbers, sitting in a spreadsheet looking exactly like the right ones. Check the figures against the original. That is not a disclaimer, it is the single most important thing to know about any OCR'd spreadsheet, including the ones you pay for.
Tesseract's own confidence score cannot tell you which cells to check — on our scans the words it got wrong averaged 84 while the words it got right averaged 89, and a threshold at 70 flags cells on a page that has no errors at all. What does work is checking a cell against the column it sits in, which catches roughly one OCR mistake in five at 100% precision; cells that need a second look has the numbers.
Two smaller findings, in case they save you time elsewhere. Rendering the page bigger before recognising it helps only up to the resolution of the scan itself — 91% of cells at 1×, 100% around 2–3×, and back down to 97% at 4×, where you are just interpolating. And of the two published English models, the 2.95 MB one and the 10.9 MB one recovered identical cells and identical numbers in identical time on every table we tried, so this page downloads the small one.
Merged cells, stacked headers and text that wraps onto a second line inside one cell are all genuinely ambiguous from position alone, and no free tool gets them consistently right. That is exactly why the preview exists: look at it before you download, rather than discovering the problem in Excel.
Two tables stacked on one page used to be read as a single grid with their columns interleaved. They are now detected and offered separately — see picking one table out of a page — and anything the detection misses can be selected by hand. A rotated page, a photograph taken at a steep angle, or handwriting will still not come out well — OCR wants a flat, reasonably square, reasonably sharp page. If you only have a photo, retake it square-on in good light before blaming the converter.
This page is the tool. Everything below goes deeper on one thing than would fit here, and each one is written around a different question.