How to Extract Tables From a PDF in Python
Jul 11, 2026 • 6 min read
Extract tables from a PDF in Python: Camelot and tabula-py for digital PDFs, an OCR API for scanned PDFs. Keep rows and columns aligned and export to CSV, Excel or JSON.
// Try it now
PDF, JPG, PNG, BMP, HEIC, TIFF
Upload a document to extract
Drop files here or click to upload
Up to 50 files
Uploading...
Last updated July 2026.
To extract tables from a PDF in Python, use Camelot or tabula-py for digital PDFs that already contain text: both return the table as a pandas DataFrame you can export to CSV. Camelot suits tables with visible gridlines, tabula-py suits tables separated by whitespace. Neither reads scanned PDFs, because a scan is an image with no text layer, so for scans you call an OCR API that reconstructs the grid. DocuOCR reads both types and returns the rows and columns as Excel, CSV or JSON.
Pulling a table out of a PDF is harder than pulling text, because you have to keep the rows and columns aligned, not just read the characters. Python has good free tools for this, but they all assume the PDF has real text inside it. The moment you hand them a scan, they return an empty table and it looks like the code failed. Here is how to extract tables the right way for each kind of PDF, with code.
How do I extract tables from a PDF in Python?
For a digital PDF, start with Camelot or tabula-py. Camelot is built for lattice-style tables, the ones with visible lines around the cells, and it returns a list of tables you can convert to DataFrames:
import camelot
tables = camelot.read_pdf("report.pdf", pages="all")
for t in tables:
print(t.df) # a pandas DataFrame
tables[0].to_csv("out.csv")
tabula-py, a wrapper around the Java tabula engine, is better for stream-style tables that have no borders and rely on whitespace between columns. pdfplumber is a third option when you want to write custom logic against a table's coordinates. All three are free, and all three share the same requirement: the PDF must already contain selectable text. They read the text layer and infer the table structure from where that text sits on the page.
Can I extract tables from a scanned PDF in Python?
Not with Camelot, tabula-py or pdfplumber. A scanned or photographed PDF holds an image of the page, with no text layer for those libraries to read, so they return an empty table. This is the most common table-extraction failure, and it is not a bug: there is genuinely nothing for a text-based tool to parse. To get a table out of a scan, you first need OCR to recognize the characters, and then a step that rebuilds the grid from where those characters sit.
That is what an OCR service does in one pass. It reads the page image, detects the table, and returns the rows and columns as structured data. You can call one from Python the same way you would any REST API. If your documents are a mix of clean exports and scans, an OCR route means one code path instead of a fragile "try the library, fall back to OCR" branch. The PDF table extraction guide covers which services keep table structure and which only return loose text.
How do I keep the rows and columns aligned?
Alignment is where table extraction earns its keep. A tool that just reads text left to right will merge two columns or split one row across two, and you end up with a jumbled CSV. Camelot and tabula-py handle alignment well on clean digital tables because they can see exactly where each character sits. On messy layouts, merged cells or multi-line rows, they struggle, and that is where AI-based extraction helps: it recognizes the visual structure of the table rather than guessing from spacing alone. With DocuOCR, a multi-column statement or a price list comes back as a real grid, with merged cells and multi-line entries kept in place, ready to load into a database or a spreadsheet.
Camelot vs tabula-py vs an OCR API
Choose by the document. For digital PDFs with clean, gridded tables, Camelot is accurate and free. For digital PDFs with borderless tables, tabula-py usually reads them better. For scanned PDFs, or a mix you cannot control, an OCR API is the only option that returns anything, and it also exports straight to Excel, CSV or JSON so you skip the DataFrame-to-file step. The honest tradeoff: the libraries cost nothing but only cover digital files and need per-layout tuning, while the API costs per page and covers everything with less code. Many teams use both, the free libraries for known-clean sources and the API for the rest.
If your end goal is simply a spreadsheet rather than a DataFrame, you may not need Python at all. Converting the PDF straight to Excel gives you the tables as a clean .xlsx, scanned or not, with no code to write.
How do I extract a table from a PDF to a pandas DataFrame?
Camelot and tabula-py both give you a DataFrame directly: camelot.read_pdf returns table objects whose .df attribute is a DataFrame, and tabula.read_pdf returns a list of DataFrames. From an OCR API you get JSON, which loads into pandas in one line with pd.DataFrame(table["rows"]). That JSON route has an advantage for scanned or irregular documents: because the service has already reconstructed the grid, the DataFrame arrives clean rather than needing a second cleanup pass. Reading the tables back as JSON is exactly what the OCR API in Python returns, so a scanned bank statement lands as tidy rows the same way a digital one does.
How do I extract tables from many PDFs at scale?
Batch them through an API rather than opening files one by one on a single machine. Post each PDF, add backoff for rate limits, and collect results as they complete, using webhooks so you are not blocking on each call. Because table extraction on scans is CPU-heavy, doing it locally with OCR plus a library gets slow fast, while a hosted service parallelizes it for you. High-volume table work often feeds accounting: if the tables are bank statements headed for your books, you can convert a PDF statement straight to QuickBooks instead of building the whole pipeline yourself.
The short version
Extracting tables from a PDF in Python splits on the same line as everything else: digital or scanned. For digital PDFs, Camelot handles gridded tables and tabula-py handles borderless ones, both free and both returning pandas DataFrames. For scanned PDFs, those libraries return nothing, and you need an OCR service to read the image and rebuild the grid. To cover both with one code path and get Excel, CSV or JSON out the other side, use a tool that runs OCR and keeps the rows and columns aligned.
Extract your documents with DocuOCR
Upload a document and get clean, structured data in seconds. No template setup required.
Start free