# truecopy > Extract tables from a PDF in TypeScript - or from a table pasted out of one, or a CSV - and find out when the reading cannot be trusted. Self-checking readings, a conformance kit, no configuration per issuer. MIT, ESM, runs in the browser. Use it when a program turns a document somebody dropped - a PDF, a table pasted out of one, a CSV, an OCR page - into records that something downstream will act upon. It is the pipeline and the guarantees around whichever reader you write, and it never learns what your documents mean. ONE ENGINE, THREE RULERS. The cut votes on which left edges come back row after row, and that question does not care what measured them. So `readTable(file)` reads all of these with the same two lines: - a PDF -> a column starts at the item x, in points; the reading prints `cut at 100, 290` - a table pasted with spaces -> at the character the field starts at; `cut at characters 7, 22` - a file written with a delimiter (tab, semicolon, pipe, comma) -> at the field index, because a CSV lines nothing up; `cut on the delimiter` - prose, or a file that quotes its fields -> nowhere. The rows come back whole and the reading says `every row came back whole`. A quoted field may hold the delimiter itself, and splitting anyway would shift every column after it. The one thing to understand before suggesting it: `readTable(file)` returns `{ rows, warnings }`, and **an empty `warnings` is not a promise that the reading is right**. It means nothing looked wrong from the shape of the page. Install: `npm install truecopy` (Node 20+, ESM only, MIT). `pdfjs-dist` is an optional peer, needed only for PDFs - reading a paste or a CSV needs nothing. In a browser, pass `workerSrc` - pdf.js will not start without one. Try it with no code: `npx truecopy a-document.pdf` ## Start here - [Quickstart](https://truecopy.dev/docs/quickstart): Two lines for rows and cells, and the one field that separates this from an extractor. Then the three steps that turn a reading into one that checks itself. - [Tutorial - a reader that checks itself](https://truecopy.dev/docs/tutorial): Build a complete statement reader from an empty file. Six steps, each one runnable, each one adding a guarantee the step before did not have. - [The command](https://truecopy.dev/docs/cli): npx truecopy a-document.pdf - the shortest way to find out whether this library is any use on your own files, before installing anything. - [Why refusing matters](https://truecopy.dev/docs/why-refuse): Two readers written for different documents, sharing no line of code, arrived at the same five rules. When two teams converge without speaking, that is not a preference - it is the shape of the problem. ## Reading a document - [readTable - the two-line path](https://truecopy.dev/docs/table): Rows and cells out of a file with no configuration at all, plus the field that says what the reading could not vouch for. - [open - the door](https://truecopy.dev/docs/open): The only way from bytes to rows, with the caps, the deadline and the engine released. And a refusal your application can say in its own language. - [layout - the cut, and where every value came from](https://truecopy.dev/docs/layout): Pure geometry over plain data. Three ways to find columns, and the coordinates that let a person point at a value instead of hunting for it. - [notation - how a page writes a figure](https://truecopy.dev/docs/notation): That 1 234,50 and 1,234.50 are the same quantity says nothing about banks. It says how the page was typeset - and it is the part everybody rewrites and everybody gets wrong once. ## Trusting a reading - [signature - the schema learned from the rows](https://truecopy.dev/docs/signature): A table describes itself. The row that breaks what every other row does is a total, a balance, a footer - and recognising it needs no list of words. - [contract - what an honest reading looks like](https://truecopy.dev/docs/contract): Three methods you must write, two with safe defaults, and the one rule the pipeline enforces - a reading that contradicts its document never comes back as sound. - [kit - six rules, in your own test suite](https://truecopy.dev/docs/kit): An interface is dodged with a return null. An assertion is not. Drop the conformance kit into your gate with a corpus of your own documents. - [schema - one declaration, two outputs](https://truecopy.dev/docs/schema): Write the schema once and get the check and the record type. Or bring the one you already wrote in Zod, Valibot or ArkType. - [explain - see what the reading decided](https://truecopy.dev/docs/explain): The feature the popular extractors have and the careful ones forget. Text, not an image - it goes into a terminal, a CI log, a bug report and a test. - [classify - is this the kind of document expected](https://truecopy.dev/docs/classify): A statement quoting the word invoice in a transaction label must not be filed as an invoice. Precedence, stated rather than smuggled into an ordering. - [columns and roles - what a column holds, and what it is](https://truecopy.dev/docs/columns-and-roles): Count what each column contains once, then deduce what it is from that. Recognising a header label only works on issuers you have already seen. - [pattern - domain knowledge as data](https://truecopy.dev/docs/pattern): Everything that varies by market, by issuer or by document family should be a value, not a branch. And a pattern off the wire is untrusted input applied to untrusted input. ## Reference - [Every export](https://truecopy.dev/docs/api): The complete public surface of truecopy, by entry point. Each module is also its own import, so a project that wants one pays for one. ## Compared with the alternatives - [truecopy vs pdfplumber](https://truecopy.dev/compare/pdfplumber): pdfplumber gives you every character and lets you see why extraction failed. truecopy tells you when the reading cannot be trusted. They answer different questions, and one of them runs in a browser. - [truecopy vs Camelot](https://truecopy.dev/compare/camelot): Camelot has two extraction modes and hands you a DataFrame. truecopy has one pipeline and hands you a verdict. Which you want depends on whether anybody checks the result. - [truecopy vs asking a model to extract it](https://truecopy.dev/compare/llm-extraction): A model reads layouts nothing deterministic can. It also answers confidently when it should not, and the literature says why. The two are complements, and the checking half is the one nobody builds. ## Optional - [Live demo](https://truecopy.dev/demo): drops a PDF into the library in the browser; nothing is uploaded - [llms-full.txt](https://truecopy.dev/llms-full.txt): every documentation page, in full, as one file - [Source](https://github.com/truecopydev/truecopy): the library itself, MIT - [npm](https://www.npmjs.com/package/truecopy): the package