# PDF Table Extractor: PDF to Excel & CSV Converter with OCR (`pandadad0214/pdf-table-extractor`) Actor

Use this to extract every table from PDF files into Excel and CSV (PDF to Excel converter, OCR for scans). Input: PDF URLs or uploads plus optional page ranges. Output: one row per table with pages, header, row and column counts and cell data, plus Excel and CSV files.

- **URL**: https://apify.com/pandadad0214/pdf-table-extractor.md
- **Developed by:** [Panda Federation](https://apify.com/pandadad0214) (community)
- **Categories:** Automation, Developer tools, AI
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

Pay per event

This Actor is paid per event. You are not charged for the Apify platform usage, but only a fixed price for specific events.
Since this Actor supports Apify Store discounts, the price gets lower the higher subscription plan you have.

Learn more: https://docs.apify.com/actors/running/actors-in-store.md#pay-per-event

## What's an Apify Actor?

An Actor is a serverless cloud program that runs on the Apify platform. It has two run modes.
In Batch mode, an Actor accepts a well-defined JSON input, performs an action which can take anything from a few seconds to a few hours,
and optionally produces a well-defined JSON output, datasets with results, or files in key-value store.
In Standby mode, an Actor provides a web server which can be used as a website, API, or an MCP server.

Apify vocabulary and the platform model are defined once, in the agent quickstart at https://apify.com/agents.md.

## How to integrate an Actor?

If asked about integration, you help developers integrate Actors into their projects.
You adapt to their stack and deliver integrations that are safe, well-documented, and production-ready.

Do not guess an integration path. Every one of them is in the agent quickstart at https://apify.com/agents.md: the Apify MCP server, Agent Skills with the Apify CLI, the JavaScript and Python clients, the REST API, and the account-free path for an agent with no human to sign in. It also carries the rule on stating cost before the first paid run.

For examples already wired to this Actor's own input schema, see the [API](#api) section below.

Each client library has reference documentation the quickstart does not restate: [JavaScript/TypeScript](https://docs.apify.com/api/client/js/docs.md) (`npm install apify-client`) and [Python](https://docs.apify.com/api/client/python/docs.md) (`pip install apify-client`).

# README

## PDF Table Extractor: PDF to Excel & CSV Converter with OCR

> **PDF to Excel** on Apify: pull every table from PDF reports, financial statements and filings into clean Excel and CSV files, with OCR for scanned pages. Apify's free plan includes $5 of monthly platform credit, enough for thousands of pages at $0.001 per page plus $0.003 per table (pricing below).

**Pull every table out of a PDF report, financial statement or government publication into clean Excel and CSV files. One sheet per table, page numbers kept, headers detected, dot leaders and wrapped rows cleaned up, and tables that run over a page break joined back together.**

Copying tables out of PDFs by hand is slow and error-prone: columns shift, numbers land on the wrong row and "Total ........ 1,234" pastes as one cell. **PDF Table Extractor** reads the PDF's own text layer, finds ruled and borderless tables, cleans them and hands you a workbook you can sort, sum and chart straight away.

- 📄 **Digital PDFs, any layout:** ruled grids (cell borders) and borderless, whitespace-aligned tables such as statistical releases, annual reports and 10-K/10-Q statements
- 🧹 **Cleanup built in:** multi-line headers joined ("Sept." + "2026" → "Sept. 2026"), dot leaders stripped, wrapped labels merged back onto their numbers, `$` columns removed, titles and footnotes pulled out of the grid
- 📑 **Multi-page tables joined:** a table that continues on the next page comes out as one table with a page range (`22-35`)
- 🔢 **Real numbers in Excel:** `1,234`, `(56)` and `4.2%` become numbers you can sum. The CSV and dataset keep the text exactly as printed
- 🔍 **Scanned pages handled honestly:** pages with no text layer are detected and listed instead of being parsed into garbage. Optional OCR (beta) reads clean scans and marks those tables **verify**
- 📊 **Excel + CSV + JSON:** an Excel workbook with an Index sheet and one sheet per table, a ZIP of CSVs, one CSV per table, and one dataset row per table with the full data
- 💸 **$0.001 per page + $0.003 per table.** A 20-page report with 8 tables costs $0.044. Scanned pages are flagged for free

### Who it's for

- **Analysts and researchers:** BLS, Census, central bank and agency tables into a spreadsheet in seconds
- **Finance and accounting teams:** balance sheets, income and cash-flow statements from annual reports and filings
- **Data journalists and consultants:** turn a stack of PDF reports into one workbook to compare
- **Developers and AI agents:** call it from the API or MCP and get each table as JSON rows keyed by header

> **Not for coursework.** PDF Table Extractor converts documents you are allowed to use. It isn't meant for completing assignments on someone else's behalf. Always spot-check important figures against the PDF, especially OCR'd pages.

### How to use the PDF to Excel

1. Click **Try for free** and paste one or more **PDF URLs**, **upload PDFs** from your computer, or pick a **key-value store** that already holds PDFs (read-only access to that store only).
2. Optional: limit **Pages** (`1-5, 8, 12-end`) and the **maximum pages per PDF**.
3. Leave **Table detection** on **Auto** unless you know your PDF only uses ruled or only borderless tables.
4. Click **Start**. A 40-page report usually takes under a minute.
5. Download **TABLES_XLSX** (Excel) or **TABLES_CSV_ZIP** from **Storage → Key-value store**, or read the dataset via API.

#### Input example

```json
{
  "pdfUrls": [
    "https://www.bls.gov/news.release/pdf/empsit.pdf",
    "https://www.federalreserve.gov/aboutthefed/files/combinedfinstmt2023.pdf"
  ],
  "pages": "1-12",
  "detection": "auto",
  "ocrScannedPages": false
}
```

### Output example

![Example output table from a real pdf-table-extractor run](https://api.apify.com/v2/key-value-stores/0eeXxTD8eJjgE6yTA/records/shot-pdf-table-extractor)

One dataset row per table (data shortened). This is the BLS Employment Situation, page 4:

```json
{
  "tableNumber": 1,
  "file": "empsit.pdf",
  "pages": "4",
  "title": null,
  "header": ["Category", "Sept. 2025", "July 2026", "Aug. 2026", "Sept. 2026", "Aug. 2026- Sept. 2026"],
  "hasHeader": true,
  "rowCount": 41,
  "columnCount": 6,
  "method": "stream",
  "check": null,
  "notes": [],
  "sheetName": "T1 p4",
  "csvKey": "table-001-p4.csv",
  "data": [
    {"Category": "Civilian noninstitutional population1", "Sept. 2025": "274,226", "July 2026": "275,282", "Aug. 2026": "275,415", "Sept. 2026": "275,554", "Aug. 2026- Sept. 2026": "139"},
    {"Category": "Unemployment rate", "Sept. 2025": "4.4", "July 2026": "4.1", "Aug. 2026": "4.1", "Sept. 2026": "4.2", "Aug. 2026- Sept. 2026": "0.1"}
  ]
}
```

#### Fields

| Field | What it is |
|---|---|
| `tableNumber`, `tableOnFile` | Position across the run and within the file |
| `file`, `sourceUrl` | File name and where it came from |
| `pageStart`, `pageEnd`, `pages` | Page(s) the table is on (a range when it continues over page breaks) |
| `title`, `notes` | Title lines above the table and footnotes below it, kept out of the grid |
| `header`, `hasHeader` | Column names (generic `Column 1…` when no header row was found) |
| `rowCount`, `columnCount`, `data` | Size and the rows as objects keyed by header (first 2,000 rows; the CSV/Excel always have all rows) |
| `method` | `lattice` (ruled grid), `stream` (whitespace-aligned) or `ocr` (scanned page) |
| `check` | Why to look twice, if anything: OCR, no header found, or mostly text |
| `sheetName`, `csvKey` | Where the table is in TABLES_XLSX and its single CSV in the key-value store |

#### Files in the key-value store

| Key | What it is |
|---|---|
| `TABLES_XLSX` | Excel workbook: **Index** sheet (with links) and one sheet per table, title and source page on top, footnotes below |
| `TABLES_CSV_ZIP` | All tables as CSV files in one ZIP |
| `table-001-p4.csv` … | One CSV per table (UTF-8, opens cleanly in Excel) |
| `SUMMARY` | Per file: page count, pages analysed, tables, scanned pages (OCR'd or flagged), empty pages and any error |

### Scanned PDFs

Every page is checked for a text layer first. A page that is just an image (a scan or photo) is **never parsed as if it were text**:

- **OCR off (default), or over the OCR page cap:** the page is skipped, costs nothing and is listed under `scannedNotOcr` in `SUMMARY`, on the Index sheet and in the run status.
- **OCR on (beta):** the page is rendered at about 250 dpi (capped for very large pages), read with Tesseract (English) and parsed. Those tables get `method: "ocr"` and a **verify** note. OCR takes about 5-15 seconds per page and can misread digits (4.4 → 44) and dot leaders, so it suits clean, straight scans where you will check the numbers.

Digital PDFs give exact results. Phone photos, skewed scans and handwriting are out of scope.

### For AI agents

Use this Actor to extract every table from PDF files into structured rows, Excel and CSV. Call it with Apify's MCP server (`https://mcp.apify.com`, tool `call-actor`, Actor `pandadad0214/pdf-table-extractor`) or the API (`POST https://api.apify.com/v2/acts/pandadad0214~pdf-table-extractor/run-sync-get-dataset-items`).

Minimal input:

```json
{"pdfUrls": ["https://example.com/annual-report.pdf"], "pages": "1-10"}
```

Each dataset item includes:

- `summary`: one line, e.g. `Table 3 'Revenue by segment' from report.pdf p12: 14 rows x 5 columns (lattice); columns ...`
- `tableNumber`, `file`, `pages`: where the table is
- `header`: column names
- `rowCount`, `columnCount`: table size
- `method`: `lattice`, `stream` or `ocr`
- `check`: a warning to verify (OCR, no header, mostly text)
- `data`: rows as objects keyed by header (first 2,000 rows; full table in the CSV)

The run's key-value store has a `SUMMARY` record with counts (`tablesTotal`, per-file pages, OCR and scanned pages) and file names (`TABLES_XLSX`, `TABLES_CSV_ZIP`), a one-line `takeaway`. Every input field has a description with formats, units and limits.

### PDF to Excel pricing and free results

**Apify paid-plan discounts:** Bronze members pay 10% less, Silver 20% less and Gold 30% less per result. Free-plan prices are shown below; the discount applies automatically.

Pay-per-event, no subscription:

| Event | Price |
|---|---|
| Page analysed (digital page) | **$0.001** |
| Table extracted | **$0.003** |
| Scanned page OCR'd (beta, only when turned on) | **$0.02** |
| Actor start | $0.00005 |

Empty pages, flagged scanned pages and files that fail to download cost nothing. Your **maximum charge per run** is respected: the run stops cleanly before going over it.

### FAQ

**Is there a free way to try this PDF to Excel?** Yes. Apify's free plan includes $5 of monthly platform credit, enough for thousands of pages at $0.001 per page plus $0.003 per table.

**Which PDFs work best?** PDFs made by software (reports, statements, exports) with a text layer you can select. Those are read exactly, not guessed.

**Why are some headers split oddly?** Group headers that span several columns ("Seasonally adjusted" above five months) are attached to the column they sit over. Rename columns in Excel if you need a different layout, or set **Header row** to *First row* / *None*.

**Can I process password-protected PDFs?** Yes, if you have the password: add it in **PDF password** (stored encrypted).

**Is my file kept?** Downloads are deleted after processing. Results stay in your own Apify storage under your retention settings.

**Can I use it from code or an AI agent?** Yes, via the Apify API, the Python/JS clients, or as a tool through Apify's MCP server.

### More Panda Federation tools

- [Reference Checker](https://apify.com/pandadad0214/reference-checker)
- [Citation Generator](https://apify.com/pandadad0214/citation-formatter)
- [Google Scholar Scraper Alternative](https://apify.com/pandadad0214/literature-search)
- [PubMed Scraper](https://apify.com/pandadad0214/pubmed-evidence-table)
- [Grants.gov Scraper](https://apify.com/pandadad0214/grants-finder)
- [Academic Research MCP Server](https://apify.com/pandadad0214/panda-research-mcp)

[All Panda Federation Actors on Apify](https://apify.com/pandadad0214)

Questions or a custom data feed? Open an issue on this Actor's **Issues** tab.

### Changelog

- **2026-10-30 (agent update):** Built for AI agents: a one-line `summary` on every result, `takeaway` in the SUMMARY record, and input fields with formats, limits and examples.
- **2026-10-30:** New search-friendly title and page, FAQ, safe demo run on empty input, Bronze/Silver/Gold discounts, output screenshot.
- **2026-10-29:** First public release with pay-per-event pricing.

# Actor input Schema

## `pdfUrls` (type: `array`):

Direct links to PDF files. Google Drive and Dropbox share links are converted to direct downloads automatically. Up to 150 MB per file.

## `pdfFiles` (type: `array`):

Or upload PDFs from your computer. They are stored in a key-value store in your Apify account.

## `pdfStore` (type: `string`):

Optional. Pick a key-value store in your account that holds PDFs. The Actor gets read access to this store only.

## `pdfStoreKeys` (type: `array`):

Optional. Keys of the PDFs to process (e.g. REPORT.pdf). Leave empty to process every PDF record in the store (up to 50).

## `pages` (type: `string`):

Optional. Only these pages, e.g. 1-5, 8, 12-end. Leave empty for all pages (up to the page limit below).

## `maxPagesPerPdf` (type: `integer`):

Caps cost and run time on very long documents. You pay per page analysed. Whole number, 1 to 2,000 pages; default 100.

## `detection` (type: `string`):

Auto tries ruled-grid detection first and switches to whitespace (column alignment) detection when that recovers more of the table. Pick one mode if you know your PDF's style.

## `headerDetection` (type: `string`):

Auto finds header rows above the first data row (multi-line headers are joined). First row = always use row 1. None = generic Column 1, Column 2… names.

## `mergeWrappedRows` (type: `boolean`):

Join labels that wrap onto a second line back into one row, so numbers stay on the right line. Default: on.

## `mergeAcrossPages` (type: `boolean`):

When a table carries on over a page break with the same columns, output it as one table with a page range. Default: on.

## `numbersAsNumbers` (type: `boolean`):

Write 1,234 / (56) / 4.2% as real Excel numbers (parentheses = negative) so you can sum and chart them. CSV and dataset keep the text exactly as printed. Default: on.

## `ocrScannedPages` (type: `boolean`):

Pages with no text layer (scans, photos) are always detected. Off (default): they are skipped, listed in SUMMARY and on the Index sheet, and cost nothing. On: they are read with Tesseract OCR (English) and their tables are marked 'verify'. OCR is slow (about a minute per page) and can misread digits and dot leaders, so use it for clean scans and check the numbers.

## `maxOcrPagesPerPdf` (type: `integer`):

OCR has its own cap because it is slow and priced per page. Extra scanned pages are flagged, not charged. Whole number, 0 to 100 pages; default 10.

## `pdfPassword` (type: `string`):

Optional. Only for password-protected PDFs you are allowed to open.

## Actor input object example

```json
{
  "pdfUrls": [
    "https://www.bls.gov/news.release/pdf/empsit.pdf"
  ],
  "pdfStoreKeys": [
    "REPORT.pdf"
  ],
  "pages": "1-5, 8, 12-end",
  "maxPagesPerPdf": 100,
  "detection": "auto",
  "headerDetection": "auto",
  "mergeWrappedRows": true,
  "mergeAcrossPages": true,
  "numbersAsNumbers": true,
  "ocrScannedPages": false,
  "maxOcrPagesPerPdf": 10
}
```

# Actor output Schema

## `table` (type: `string`):

No description

## `xlsx` (type: `string`):

No description

## `zip` (type: `string`):

No description

## `summary` (type: `string`):

Run-level summary record. Agent-friendly keys: `takeaway` (one-line plain-English result of the run).

# API

You can run this Actor programmatically using our API. Below are code examples in JavaScript, Python, and CLI, as well as the OpenAPI specification and MCP server setup.

## JavaScript example

```javascript
import { ApifyClient } from 'apify-client';

// Initialize the ApifyClient with your Apify API token
// Replace the '<YOUR_API_TOKEN>' with your token
const client = new ApifyClient({
    token: '<YOUR_API_TOKEN>',
});

// Prepare Actor input
const input = {
    "pdfUrls": [
        "https://www.bls.gov/news.release/pdf/empsit.pdf"
    ]
};

// Run the Actor and wait for it to finish
const run = await client.actor("pandadad0214/pdf-table-extractor").call(input);

// Fetch and print Actor results from the run's dataset (if any)
console.log('Results from dataset');
console.log(`💾 Check your data here: https://console.apify.com/storage/datasets/${run.defaultDatasetId}`);
const { items } = await client.dataset(run.defaultDatasetId).listItems();
items.forEach((item) => {
    console.dir(item);
});

// 📚 Want to learn more 📖? Go to → https://docs.apify.com/api/client/js/docs

```

## Python example

```python
from apify_client import ApifyClient

# Initialize the ApifyClient with your Apify API token
# Replace '<YOUR_API_TOKEN>' with your token.
client = ApifyClient("<YOUR_API_TOKEN>")

# Prepare the Actor input
run_input = { "pdfUrls": ["https://www.bls.gov/news.release/pdf/empsit.pdf"] }

# Run the Actor and wait for it to finish
run = client.actor("pandadad0214/pdf-table-extractor").call(run_input=run_input)

# Fetch and print Actor results from the run's dataset (if there are any)
print(f"💾 Check your data here: https://console.apify.com/storage/datasets/{run.default_dataset_id}")
for item in client.dataset(run.default_dataset_id).iterate_items():
    print(item)

# 📚 Want to learn more 📖? Go to → https://docs.apify.com/api/client/python/docs/quick-start

```

## CLI example

```bash
echo '{
  "pdfUrls": [
    "https://www.bls.gov/news.release/pdf/empsit.pdf"
  ]
}' |
apify call pandadad0214/pdf-table-extractor --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,pandadad0214/pdf-table-extractor"
        }
    }
}
```

The hosted server signs you in with OAuth on first connect, so no API token belongs in this config. Clients without OAuth support can send an `Authorization: Bearer <APIFY_API_TOKEN>` header instead, using a token from API & Integrations in Apify Console (https://console.apify.com/settings/integrations).

## OpenAPI specification

Download the OpenAPI definition: https://api.apify.com/v2/actors/zjRqoA1WyoRdTaFNp/builds/zlPKebbvs0Ulx2sUb/openapi.json
