Skip to content
Docs Security Sign in
PdfParse

PDF to CSV, every table in its own file

PdfParse finds each table in a PDF or scan and returns it as a separate CSV, with one header row, one record per line and numbers that open correctly in a spreadsheet or load straight into a warehouse. Statements, price lists and reports stop being copy and paste work.

Parse PDF
Printed financial report pages with dense tables fanned out next to a highlighter and a calculator

Get a CSV from one page now

Drop a statement or a report and the CSV tab shows each table the parser found on page one.

Drop a PDF or scan

PDF, PNG or JPG up to 10 MB. Page one is parsed in full, right here.

Or try a sample file
Output

Optional. Comma separated field names, for example invoice_number, total, due_date.

Page one is parsed in your browser and never uploaded. No card needed to try page one.

What one call returns

Page one rendered with every block outlined, next to the JSON your code receives.

  1. Reading text layer
  2. Detecting layout
  3. Extracting tables
  4. Building JSON
Rendered page Page 1 of your document

Headings, paragraphs, tables and totals detected

heading
Invoice
paragraph
Harbor Street Joinery
14 Dock Lane
Portsmouth, NH 03801
key_value
Invoice no.INV-2026-0418IssuedOct 14, 2026DueNov 13, 2026
table
DescriptionQtyUnitAmount
Oak countertop, 2.4 m2640.001,280.00
Cabinet doors, shaker1285.001,020.00
On site fitting1450.00450.00
total
Subtotal2,750.00Tax 8.5%233.75Total dueUSD 2,983.75
paragraph
Payment by bank transfer within 30 days.
Quote the invoice number with your transfer.
Goods remain ours until paid in full.
footer
Harbor Street JoineryPage 1 of 2
Locked page

Pages 2 and later are parsed after you create an account.

Output
{
  "document": {
    "pages": 2,
    "parsed_pages": 1,
    "language": "en"
  },
  "pages": [
    {
      "number": 1,
      "blocks": [
        { "type": "heading", "text": "Invoice", "bbox": [48, 52, 132, 84] },
        { "type": "paragraph", "text": "Harbor Street Joinery, 14 Dock Lane, Portsmouth" },
        { "type": "key_value", "pairs": {
            "Invoice no.": "INV-2026-0418",
            "Issued": "Oct 14, 2026",
            "Due": "Nov 13, 2026" } },
        { "type": "table", "columns": ["Description", "Qty", "Unit", "Amount"],
          "rows": [
            ["Oak countertop, 2.4 m", 2, 640.00, 1280.00],
            ["Cabinet doors, shaker", 12, 85.00, 1020.00],
            ["On site fitting", 1, 450.00, 450.00] ] },
        { "type": "total", "label": "Total due", "value": 2983.75, "currency": "USD", "confidence": 0.98 }
      ]
    }
  ],
  "fields": {
    "invoice_number": { "value": "INV-2026-0418", "confidence": 0.99, "page": 1 },
    "total": { "value": 2983.75, "confidence": 0.98, "page": 1 },
    "due_date": { "value": "2026-11-13", "confidence": 0.97, "page": 1 }
  }
}

Downloads from the demo include a watermark field and cover page one only.

Page one is parsed in your browser, so your file never reaches our servers.

Request
The same request from your code
Read the API reference
$ curl https://api.pdfparse.ai/v1/parse \
  -H "Authorization: Bearer $PDFPARSE_API_KEY" \
  -F file[email protected] \
  -F outputs=json,markdown,csv
200 OK, 1 page parsed

One CSV per table, not one blob per page

Text outside tables never ends up in your rows. Each table is returned in the tables array with its page, row count, column count and a CSV string, and the web app offers the same tables as separate downloads or one export per document.

  • A single header row, even when the PDF prints a two line header
  • Thousands separators and currency signs kept in the text, with the raw cell available in JSON
  • Rows that wrap onto a second line in the PDF joined back into one record
  • Tables that continue on the next page merged into one CSV with the header written once
  • UTF 8 output with standard quoting, so commas inside cells do not break columns
CSV
date,description,reference,debit,credit,balance
2024-03-01,Opening balance,,,,"12,400.00"
2024-03-02,Card payment stationery,TX-55102,184.20,,"12,215.80"
2024-03-04,Transfer from client,TX-55188,,"3,500.00","15,715.80"

How the CSV export runs

  1. 1

    Upload one file in the web app, or send many with a batch job through the API.

  2. 2

    Each page is classified, and table regions are separated from paragraphs, headers and footers.

  3. 3

    Rows and columns are rebuilt from ruling lines where they exist and from text alignment where they do not.

  4. 4

    Each table is written to CSV and listed with its page in the response, ready to download or store.

What keeps the columns in line

A CSV is only correct if every value sits under the right header. That is where most PDF converters fail, and where PdfParse spends its effort.

  • Borderless tables are rebuilt from the alignment of text, which is how most bank statements are printed.
  • Merged header cells are expanded so each column gets its own name in the CSV header.
  • Two column pages that hold two separate tables produce two separate CSV files, not one mixed table.
  • Scanned statements are read with OCR first, and digits are checked against column alignment.
  • Repeated page headers and running totals in the footer are kept out of the data rows.

Ask the API for CSV

Set outputs to csv. The response lists every table with its CSV string, and the Node SDK and Python SDK expose them as a list.

curl
curl https://api.pdfparse.ai/v1/parse \
  -H "Authorization: Bearer pp_live_your_key" \
  -F "[email protected]" \
  -F 'outputs=["csv"]' \
  -F "pages=1-5"
Python
import os
from pdfparse_ai import PdfParse

client = PdfParse(api_key=os.environ["PDFPARSE_API_KEY"])
result = client.parse("march-statement.pdf", outputs=["csv"])

for i, table in enumerate(result.tables, start=1):
    path = f"march-statement-p{table['page']}-t{i}.csv"
    with open(path, "w") as f:
        f.write(table["csv"])

Who exports PDF tables to CSV

  • Accounting and finance operations teams turning bank statements and supplier statements into reconciliation files.
  • Procurement teams loading supplier price lists into their purchasing system every quarter.
  • Analysts pulling tables out of annual reports and regulatory filings for a model.
  • Data engineers who need a steady CSV feed from documents that partners only send as PDF.

Plans for CSV export

CSV output is on every plan. Starter covers 2,000 pages a month for $49, or $24 a month billed yearly, and suits a single team exporting statements by hand in the web app. Growth at $149 a month adds batch jobs of up to 500 files and webhooks, so a nightly folder of statements can run without anyone watching. Scale at $499 a month adds a priority queue and 24,000 pages. See pdf extraction api pricing for every limit.

Pricing
  • Starter 2,000 pages, 1 API key, 1 seat $49 per month $24 per month, $288 billed yearly
  • Growth 7,000 pages, 5 API keys, 3 seats $149 per month $74 per month, $888 billed yearly
  • Scale 24,000 pages, 20 API keys, 10 seats $499 per month $249 per month, $2,988 billed yearly
  • Enterprise 72,000 pages, unlimited API keys with per key limits, 25 seats $1,499 per month $749 per month, $8,988 billed yearly

FAQ

Can I get all tables in one CSV file?

Each table has its own CSV because tables usually have different columns. The web app can also export one file per document with a table column that tells you where each row came from.

Does it handle tables without lines?

Yes. Borderless tables are rebuilt from the alignment of words, which covers most statements and price lists.

Which encoding and separator does the CSV use?

UTF 8 with a comma separator and standard double quote escaping. Values that contain commas are quoted, so they stay in one column.

What if a table spans several pages?

The parts are joined into one table, and the repeated header on later pages is written only once.

Can operations staff use it without the API?

Yes. The web app lets anyone upload files, review the tables and download CSV files. It runs on the same engine and counts against the same pages as the API.

Stop retyping tables

Open an account and export the tables from your next statement in a couple of minutes.