PDF Structured Table Extractor
Pricing
Pay per event
PDF Structured Table Extractor
Extract structured tables from public PDF URLs into JSON rows and coordinate-aware cells with page provenance, confidence scores, and parsing warnings.
Pricing
Pay per event
Rating
0.0
(0)
Developer
Stas Persiianenko
Maintained by CommunityActor stats
0
Bookmarked
2
Total users
1
Monthly active users
a day ago
Last modified
Categories
Share
Turn tables in public digital PDFs into structured JSON rows and coordinate-aware cells. This PDF table extractor downloads up to 50 documents per run, detects table-like regions from positioned text, and preserves the source URL, file name, page number, table number, bounding box, confidence score, and parsing warnings.
Use the Actor for recurring document pipelines, spreadsheet exports, comparisons, and data-quality review. It works without a browser, proxy, account, or external AI API.
What does PDF Structured Table Extractor do?
- Validates that each input is a public HTTP(S) URL.
- Follows only validated public redirects.
- Enforces download timeout and file-size limits.
- Verifies the downloaded bytes are a PDF.
- Reads digital text and its coordinates with PDF.js.
- Groups aligned text into rows, cells, and table records.
- Writes one dataset item per detected table.
- Stores per-document failures and run totals in the
OUTPUTkey-value-store record.
The default dataset is ready for JSON, CSV, Excel, Google Sheets, Make, Zapier, or custom ETL consumers.
Who is it for?
- Data engineers ingesting recurring public reports.
- Analysts converting PDF tables to rows for spreadsheets or notebooks.
- Compliance teams reviewing structured values with page-level evidence.
- Researchers collecting comparable tables from document archives.
- Automation builders scheduling extraction and comparing later runs.
Choose PDF Text Extractor when you need full document text rather than structured table cells. Choose HTML Table Extractor for tables embedded in web pages.
Why use it?
Unlike plain PDF-to-text output, every result keeps a two-dimensional rows array and flattened cells with row/column indexes and PDF coordinates. Quality signals make ambiguous output reviewable instead of hiding uncertainty. One bad URL does not discard successful documents in the same batch.
No OCR or generative model is used, so digital PDFs are processed predictably and economically. Private-network destinations are rejected to protect your run from server-side request forgery.
Input parameters
| Field | Type | Default | Purpose |
|---|---|---|---|
urls | string[] | required | 1–50 direct public PDF URLs |
maxTables | integer | 100 | Global cap on emitted table records |
pageNumbers | integer[] | all | Optional one-based pages to process in every PDF |
includeHeaders | boolean | true | Separate a first row only when it looks distinct from later data rows |
minRows | integer | 3 | Minimum aligned rows for a detected table |
minColumns | integer | 2 | Minimum positioned cells in each qualifying row |
maxFileSizeMb | integer | 25 | Reject larger documents, maximum 100 MB |
timeoutSecs | integer | 60 | Per-download timeout, from 5 to 300 seconds |
Raising minRows can suppress short list-like regions. Raising minColumns focuses extraction on wider tables. Use pageNumbers when a large report has known table pages.
Getting started
- Open the Actor input page.
- Add one or more direct public PDF URLs.
- Keep the default detection settings for the first run.
- Click Start.
- Open Dataset → Detected tables.
- Review
confidenceandparsingWarningsbefore downstream use. - Export the dataset or connect it to your workflow.
Try this real input:
{"urls": ["https://raw.githubusercontent.com/tabulapdf/tabula-java/master/src/test/resources/technology/tabula/campaign_donors.pdf"],"maxTables": 25,"minRows": 3,"minColumns": 2,"includeHeaders": true}
Output fields
| Field | Meaning |
|---|---|
sourceUrl | Final validated PDF URL after redirects |
fileName | File name from response headers or URL |
pageNumber | One-based source page |
tableIndex | Table sequence within the source document |
headers | Inferred header row, or null |
rows | Two-dimensional array of structured data rows |
cells | Flattened cells with row/column indexes and coordinates |
rowCount, columnCount | Detected table dimensions |
boundingBox | Combined PDF-coordinate bounds of the table |
extractionMethod | digital-text-position in this release |
confidence | Heuristic score from 0 to 1 |
qualitySignals | Column consistency, fill ratio, and page text-item count |
parsingWarnings | Review signals for inconsistent, empty, or ambiguous structure |
extractedAt | ISO timestamp |
Real output example
A local run on the campaign donor example detected a 55-row, 7-column table with 0.99 confidence:
{"type": "table","sourceUrl": "https://raw.githubusercontent.com/tabulapdf/tabula-java/master/src/test/resources/technology/tabula/campaign_donors.pdf","fileName": "campaign_donors.pdf","pageNumber": 1,"tableIndex": 1,"headers": ["Apellido", "Nombre", "Matricula", "Cuit", "Fecha", "Tipo", "Importe"],"rows": [["Abal Medina", "Juan Manuel", "...", "...", "...", "...", "..."]],"rowCount": 55,"columnCount": 7,"confidence": 0.99,"qualitySignals": {"consistentColumnRatio": 0.98,"filledCellRatio": 1,"detectedTextItems": 405},"parsingWarnings": []}
The actual cells array also includes rowIndex, columnIndex, value, x, y, width, and height for every detected cell.
Quality and parsing-error signals
confidence is not a claim that every semantic column is perfect. It measures geometric consistency and filled cells. Review records when:
parsingWarningsis non-empty;- merged or spanning cells create inconsistent column counts;
- a document uses multi-line headers;
- a numbered list is geometrically similar to a two-column table;
- layout changes between scheduled runs.
Download failures are listed in the OUTPUT record with their URL and error. If every document fails, the run fails with a non-zero status. If a valid digital PDF has no qualifying table, it completes with zero table records.
How much does it cost to extract structured PDF tables?
Pricing uses one start event per run and one table event per detected table. The current source configuration starts at $0.005 per run and the BRONZE table rate is $0.0196 per table, with lower per-table rates at higher usage tiers.
At the BRONZE rate:
- 5 detected tables: about $0.103 total.
- 25 detected tables: about $0.495 total.
- 100 detected tables: about $1.965 total.
These examples combine the start fee and table events. The platform shows the active tier and maximum charge before each run. Failed downloads and PDFs with no detected table do not produce table events.
Batch and recurring workflows
- Schedule a monthly batch of public financial reports.
- Compare normalized
rowswith the previous dataset. - Alert when table dimensions or selected values change.
- Export new table records to Google Sheets or a warehouse.
- Keep
sourceUrl,pageNumber, and cell coordinates with every transformed record for auditability.
For recurring documents, use stable direct URLs where possible and retain the source dataset ID alongside your transformed output.
Export to CSV or Excel
Each dataset item represents one table and contains nested rows. JSON preserves the complete structure. For flat CSV or Excel output, map each element of rows to a separate downstream row and copy sourceUrl, pageNumber, and tableIndex onto it. Apify integrations, Make, Zapier, or a short script can perform that expansion.
Run with the Apify API
Replace APIFY_TOKEN with your token.
cURL
curl -X POST \"https://api.apify.com/v2/acts/automation-lab~pdf-structured-table-extractor/runs?token=APIFY_TOKEN" \-H "Content-Type: application/json" \-d '{"urls":["https://raw.githubusercontent.com/camelot-dev/camelot/master/docs/_static/pdf/foo.pdf"],"maxTables":10}'
JavaScript
import { ApifyClient } from 'apify-client';const client = new ApifyClient({ token: process.env.APIFY_TOKEN });const run = await client.actor('automation-lab/pdf-structured-table-extractor').call({urls: ['https://raw.githubusercontent.com/camelot-dev/camelot/master/docs/_static/pdf/foo.pdf'],maxTables: 10,});const { items } = await client.dataset(run.defaultDatasetId).listItems();console.log(items);
Python
from apify_client import ApifyClientimport osclient = ApifyClient(os.environ['APIFY_TOKEN'])run = client.actor('automation-lab/pdf-structured-table-extractor').call(run_input={'urls': ['https://raw.githubusercontent.com/camelot-dev/camelot/master/docs/_static/pdf/foo.pdf'],'maxTables': 10,})items = client.dataset(run['defaultDatasetId']).list_items().itemsprint(items)
Use with MCP and AI agents
Add the Actor to Claude Code:
claude mcp add --transport http apify \"https://mcp.apify.com?tools=automation-lab/pdf-structured-table-extractor"
Claude Desktop
Add this JSON under mcpServers in the Claude Desktop configuration:
{"mcpServers": {"apify": {"url": "https://mcp.apify.com?tools=automation-lab/pdf-structured-table-extractor"}}}
Cursor
Add the same apify server URL in Cursor Settings → MCP.
VS Code
Add the same apify server URL to your VS Code MCP server configuration.
Example prompts:
- “Extract tables from these three public report URLs and summarize warnings.”
- “Run the PDF table extractor on pages 4, 7, and 9, then return source coordinates for cells containing percentages.”
- “Compare structured rows in this month’s PDF with the previous dataset.”
Limits
- Digital-text PDFs only; image-only scans need OCR before this Actor.
- Password-protected or encrypted PDFs may fail.
- It does not log in, solve CAPTCHAs, or access private files.
- Irregular, rotated, borderless, spanning, or deeply nested tables may need threshold adjustment or manual review.
- A geometric detector can classify aligned numbered lists as tables.
pageNumbersapplies to every URL in a batch.- The Actor does not edit PDFs and is not a PDF table editor.
Legality and responsible use
Process only documents you are authorized to download and reuse. Respect copyright, licensing terms, privacy obligations, and source-site policies. Public availability does not automatically permit every redistribution or commercial use. Avoid exposing personal or sensitive data through public datasets.
Troubleshooting
The run returned zero tables. Confirm the PDF contains selectable text, remove pageNumbers, lower minRows to 2, or lower minColumns to 2. An image-only scan requires OCR.
Columns are split or merged incorrectly. Review cells and coordinates, adjust detection thresholds, and keep parsingWarnings with downstream records.
The URL works in my browser but fails here. Use a direct public PDF URL without login, cookies, expiring access, or a private-network address. Check the OUTPUT record for the exact HTTP, size, timeout, or signature error.
One URL failed in a batch. Successful documents still produce results. Failed URL details remain in OUTPUT; rerun only those URLs after fixing access.
FAQ
Does it use OCR or AI?
No. This release uses PDF.js digital text positions. That keeps extraction deterministic and inexpensive, but scanned pages are unsupported.
Can it process several PDFs?
Yes. Supply up to 50 URLs and cap total output with maxTables.
Are headers always removed from rows?
No. With includeHeaders: true, the first row is separated only when it differs enough from later numeric data rows. Otherwise headers is null and all detected rows remain in rows with a warning.
Can I trace a value back to the PDF?
Yes. Every table includes the source URL and page number; every flattened cell includes PDF coordinates.
Does it charge for failed URLs?
Failed URLs do not produce table events. A run still has its one-time start event.
Related Automation Lab Actors
- PDF Text Extractor — extract full and per-page PDF text and metadata.
- HTML Table Extractor — extract structured tables from web pages.
- JSON Diff Tool — compare normalized table output between recurring runs.
Support
If a reproducible digital PDF is parsed incorrectly, open an Actor issue with the public URL, input, expected page/table, and a link to the run. Do not include private documents or credentials.