# How to extract tables from a PDF (and keep them as tables)

> Three working ways to extract tables from a PDF — a free online tool, one curl to an API, and Python — plus why extracted tables lose their structure and how to prevent it.

Published: 2026-07-09 · Source: https://marklipi.com/blog/extract-tables-from-pdf


To extract a table from a PDF and keep it usable, convert the PDF to Markdown: the table comes out as rows and columns you can paste into a spreadsheet, a document, or an LLM prompt. If the PDF has a text layer (you can select the text in a viewer), this takes seconds with a free tool or one API call — no OCR, no manual retyping.

The trap most people hit is extracting to *plain text*, where a table collapses into a soup of values with no columns. The fix is choosing an output format that has a native table representation — Markdown — and a tool that detects table geometry instead of just dumping characters.

## Option 1: Free online tool (no signup)

Drag the PDF into the [free PDF to Markdown converter](/pdf-to-markdown). Tables in the text layer come out as Markdown tables:

```markdown
| Date       | Description      | Amount  |
| ---------- | ---------------- | ------- |
| 2026-06-01 | Opening balance  | 4210.55 |
| 2026-06-03 | Direct deposit   | 2900.00 |
```

Copy the rows straight into Excel or Google Sheets (paste splits on the pipes with a quick text-to-columns), or keep them as Markdown for notes and prompts. Files are converted in memory and never stored.

## Option 2: One API call

```bash
curl -s https://api.marklipi.com/convert -F "file=@statement.pdf" | jq -r .markdown
```

No API key, free tier of 100 conversions/day. This is the same engine as the browser tool — full examples for Python and Node are in [the how-to guide](/blog/convert-pdf-to-markdown-python-node-curl).

## Option 3: Python, locally

If you want to stay local and code-first, `pdfplumber` gives you cell-level access:

```python
import pdfplumber

with pdfplumber.open("statement.pdf") as pdf:
    for page in pdf.pages:
        for table in page.extract_tables():
            for row in table:
                print(row)  # ['2026-06-01', 'Opening balance', '4,210.55']
```

You'll handle the edge cases yourself — merged cells, headers repeating on every page, columns detected from ruling lines vs whitespace. That control is the point of going local; the maintenance is the cost.

## Why do PDF tables lose their structure?

A PDF stores no "table" — only characters at x/y coordinates. What looks like a grid is just text positioned to look like one, sometimes with drawn lines, sometimes aligned by whitespace alone. Any extractor must *infer* the grid from geometry. That's why:

- **Plain-text extraction scrambles tables** — it reads in text order, not visual order, so row values interleave.
- **Multi-column detection varies by tool** — whitespace-aligned tables (common in bank statements) are harder than ruled ones.
- **Scanned PDFs are a different problem entirely** — there's no text layer to read, so you need OCR. [Check which kind you have](/blog/pdf-text-layer-vs-ocr) before picking a tool.

## FAQ

### How do I extract a table from a PDF into Excel?

Convert to Markdown first, then paste into Excel and split on the `|` character (Data → Text to Columns), or save as `.md` and convert to CSV with any Markdown tool. For CSV directly from raw data, the [CSV to Markdown table tool](/tools/csv-to-markdown-table) works the other direction.

### Can I extract tables from a scanned PDF?

Not with text-layer tools — a scan has no characters to read. You need OCR-capable software (Marker, Docling, or a vision model). See [the tool comparison](/best-pdf-to-markdown-tools) for which handles scans.

### Does table extraction work on bank statements?

Yes — bank statements are usually digital-native with whitespace-aligned tables, which is exactly what marklipi is tuned for. There's a [dedicated guide for bank statements](/blog/bank-statement-pdf-to-markdown-csv).

