Of the four major document APIs, exactly one hands you a CSV. The other three return a grid of cells in JSON and leave you to write the file. And asking for a table at all moves you off the cheap meter: $1.50 per 1,000 pages becomes $10.00 on Azure and $15.00 on AWS. Every claim below was read off the vendor's own documentation in August 2026.
Upload a document to extract
Drop files here or click to upload
Up to 50 files
Free plan extracts the first 5, rest can be unlocked after
Uploading...
A merged header cell is where table extraction actually breaks. Drop in the document with the ugliest table, not the cleanest one.
If the PDF has a real text layer, Camelot, Tabula or pdfplumber will pull the table out locally and write the CSV for nothing, and you should stop there. If the PDF is a scan, there is no text to parse and you need a service that detects table structure from the image. Amazon Bedrock Data Automation is the only major API that returns a finished CSV, on representation.csv for every table it finds. AWS Textract, Azure Document Intelligence Layout and Google Document AI all return a cell grid in JSON and expect you to write the file yourself.
The three cheapest recognition meters in the industry, Azure Read, AWS Textract and Google Enterprise Document OCR, all cost $1.50 per 1,000 pages. None of the three detects a table.
Table structure costs $10.00 per 1,000 pages on Azure Layout and $15.00 on Textract. The rows and columns cost 6.7 to 10 times what the words cost, and no "PDF to CSV" listicle mentions it.
Every row states the vendor's own position from its own documentation, read in August 2026. The rate column is the meter you land on when you ask for table structure, not the vendor's cheapest headline price.
| Service | CSV output | What you actually get | Per 1,000 pages |
|---|---|---|---|
| AWS Textract (DetectDocumentText) | No | Text only. This operation does not detect tables at all. | $1.50 |
| AWS Textract (AnalyzeDocument, TABLES) | No | Tables return as TABLE and CELL Block objects. The docs answer with a code sample, "Exporting Tables into a CSV File". | $15.00 |
| Amazon Bedrock Data Automation | Yes, natively | Every TABLE entity carries representation.csv inline, plus csv_s3_uri on the async API. | $10.00 |
| Azure AI Document Intelligence (Read) | No | Read returns paragraphs, lines and words. There is no tables collection in the response. | $1.50 |
| Azure AI Document Intelligence (Layout) | No | Returns a tables array of cells in JSON. The word "csv" does not appear anywhere in the Layout documentation. | $10.00 |
| Google Document AI (Enterprise Document OCR) | No | Returns the Document JSON object. | $1.50 |
| Google Document AI (Form Parser) | No, but Google ships a converter | The API returns pages[].tables. The Document AI Toolbox client library converts a table to a DataFrame, then you call df.to_csv(). | $30.00 |
| Mistral OCR 4 | No | table_format takes null, "markdown" or "html". There is no CSV option. | $4.00 |
Azure rates come from the public Azure Retail Prices API for the eastus region, which timestamps every meter: Read has been $1.50 per 1,000 pages since March 2022, and the current Layout meter took effect in January 2026. The underlying meters are broken down on OCR pricing per 1,000 pages.
Textract's response model is a flat list of Block objects linked by parent-to-child relationships: pages, lines, words, tables, cells, merged cells, selection elements, queries and layout blocks, each with a bounding box and a confidence value. It is a graph of the page, not a document, and certainly not a grid. Turning it into rows means walking the relationships and deciding for yourself what a header is.
AWS is candid about this. Its own answer in the tables documentation is a link to a code sample titled "Exporting Tables into a CSV File". The service gives you the structure; you supply the writer. If you want that step done for you on AWS, the service is Bedrock Data Automation, priced in full on Bedrock Data Automation pricing and compared head to head on Bedrock Data Automation vs Textract.
Because Read cannot do it. Microsoft documents the Read model as returning pages, paragraphs, lines, words and styles, and if you go looking for a tables collection in that response there is not one. Read is the $1.50 per 1,000 page meter, and it is the meter most people quote when they estimate a table extraction project.
Tables come from Layout, which returns rowCount, columnCount and a cells array with rowIndex, columnIndex, columnSpan and a kind of "columnHeader". Layout is $10.00 per 1,000 pages. That is the same 6.7 times jump we found on the markdown meter, for the same underlying reason: layout analysis is a different model, not a flag on the cheap one. The limits on both are on Azure Document Intelligence limits.
If you are writing the CSV yourself, this is the table you need. All four services return the same information and not one of them returns it the same way, which is why porting an export from one vendor to another is more work than it looks.
| Service | Table shape in the response | How you find the header | Merged cells |
|---|---|---|---|
| AWS Textract | TABLE block, then one CELL block per cell with RowIndex and ColumnIndex | EntityTypes contains COLUMN_HEADER on the header cells | Merged cells are published separately as MERGED_CELL blocks under the table's MERGED_CELL relationship |
| Azure AI Document Intelligence (Layout) | tables array with rowCount, columnCount and a flat cells array carrying rowIndex, columnIndex and columnSpan | cell.kind is set to "columnHeader" | Spans live on the cell itself, so one pass over cells is enough |
| Google Document AI | pages[].tables[] split into headerRows and bodyRows, each cell carrying rowSpan and colSpan | Header rows are a separate array, so no flag to check | Spans live on the cell. Form Parser recognizes conventional tables only |
| Amazon Bedrock Data Automation | One TABLE entity with a headers array and four ready-made representations | The headers array is handed to you | A table crossing a page boundary stays one entity, with page_indices listing both pages |
Google is the outlier worth noting: it is the only one that separates headerRows from bodyRows in the response, so there is no flag to test. It is also the only vendor that ships a client-side converter, the Document AI Toolbox, whose documented job includes "Convert Tables to a Pandas Dataframe or CSV". The conversion happens on your machine, not in the response.
None of these throws an exception. Each one produces a CSV file that opens cleanly and contains the wrong numbers, which is the expensive kind of failure.
The docs are explicit: "The cell block type will always have row span of 1 and column span of 1." The real spans live on separate MERGED_CELL blocks hanging off the table's MERGED_CELL relationship. Loop over CELL blocks, which is the obvious way to write it, and every merged cell in the document silently flattens into the wrong column.
All three majors mark headers, and all three do it differently. AWS puts COLUMN_HEADER in the cell's EntityTypes, Azure sets cell.kind to "columnHeader", Google puts them in a separate headerRows array. Assume row one is the header and you will be right most of the time, which is worse than being wrong.
Textract treats an in-table title as real cells: TABLE_TITLE cells sit at RowIndex 1, usually as a merged cell spanning every column. Dump the grid without filtering EntityTypes and the CSV opens with the report's name across five columns, followed by the footers at the bottom.
Plain recognition is $1.50 per 1,000 pages on Azure Read, AWS Textract and Google. None of them returns a table. Asking for tables costs $15.00 per 1,000 on Textract and $10.00 on Azure Layout, so the row structure you need for a CSV costs 6.7 to 10 times what the words cost.
Tabula, Camelot, pdfplumber and pandas.read_html all read the embedded text layer and the ruling lines drawn in the PDF. A scan has neither, so they return nothing at all. Converting a scanned PDF to CSV is a recognition problem first and a parsing problem second.
Textract returns a Confidence on every cell and every word. Azure and Google return equivalents. A CSV file has nowhere to put them, so the moment you write the file you lose the only signal that tells you which of those numbers to check. Keep the JSON next to the CSV.
Open it and try to select a row of the table. If the text highlights, a library such as Camelot or pdfplumber may extract it for free and you can stop here. If nothing highlights, the page is an image and no parser will help you.
Tables are not included in the cheap recognition price anywhere. On AWS that means AnalyzeDocument with FeatureTypes set to TABLES at $15.00 per 1,000 pages. On Azure it means Layout at $10.00 rather than Read at $1.50. Budget from the meter you will actually call.
This is where a CSV pipeline goes wrong, and it goes wrong quietly. Take one genuinely ugly document, one with a multirow header and at least one merged cell, and make that your test case before you write the export.
The CSV is what a person opens. The JSON holds the confidence values, the bounding boxes and the page numbers, and you will want all three the first time somebody says a total looks wrong. Storage costs less than a second extraction run.
The popular Python table extractors work in ways that a scan defeats completely. Camelot's lattice mode traces the ruling lines that were drawn as vector graphics in the PDF. Its stream mode looks at where the text characters sit and infers columns from the whitespace. Tabula does much the same through its Java engine. All of them need something in the file to read.
A scanned page has neither vectors nor characters. It is a single image, so these libraries return zero tables rather than an error, and the script reports success. That silent empty result is the most common reason a PDF to CSV job appears to work in testing on the finance team's exported reports and then produces nothing on the invoices that arrived as scans.
Once you accept that scans need recognition, the choice becomes a pricing question again, and the answers are on the OCR API pricing comparison. The mechanics of pulling a grid out of an image are covered on PDF table extraction.
| Tool | Result on a scanned page |
|---|---|
| Camelot (lattice) | Zero tables. It looks for vector ruling lines, and a scan has none. |
| Camelot (stream) | Zero tables. It infers columns from text positions, and a scan has no text. |
| Tabula | Zero tables, for the same reason. |
| pdfplumber | Empty. Reads the embedded text layer only. |
| AWS Textract (TABLES) | Full cell grid with confidence values, at the $15.00 meter. |
| Azure Layout | Full cell grid with spans and columnHeader flags, at $10.00. |
| Bedrock Data Automation | A finished CSV per table, at $10.00. |
Table-capable meters only, normalized to the same unit. This is the table to take into a budget conversation, because the spread between the cheapest and the most expensive row is 15 times.
| Service | Per 1,000 pages | 100,000 pages | Notes |
|---|---|---|---|
| Mistral OCR 4 (batch) | $2.00 | $200 | Tables as markdown or HTML, not CSV. Batch halves the rate. |
| Mistral OCR 4 | $4.00 | $400 | Confidence scores and block bounding boxes in the same response. |
| Azure AI Document Intelligence (Layout) | $10.00 | $1,000 | Full cell grid with spans and columnHeader flags. You write the CSV. |
| Amazon Bedrock Data Automation | $10.00 | $1,000 | The only meter here that hands you a finished CSV per table. |
| AWS Textract (AnalyzeDocument, TABLES) | $15.00 | $1,500 | Drops to $10.00 per 1,000 above one million pages. Layout is included free with Tables. |
| Google Document AI (Form Parser) | $30.00 | $3,000 | Header and body rows separated for you. Drops to $20.00 above one million pages. Conventional tables only. |
Volume tiers exist but they start high. Textract drops from $15.00 to $10.00 per 1,000 pages above one million pages, and Azure Read drops from $1.50 to $0.60 at the same threshold. Neither hyperscaler publishes a batch discount on these meters, so an overnight job costs what a real-time one does. What else changes at that scale is on high volume OCR APIs.
CSV is the right answer when the document really is a grid and a person is going to open it. A trial balance, a rent roll, a price list, a statement of transactions: those are tables, and a table belongs in a spreadsheet.
It is the wrong answer when the document is a record. An invoice has a header and a set of line items, and CSV has no way to express that relationship. You end up either repeating the invoice number on every row or splitting the document into two files and hoping they stay together. Add the fact that a CSV cell has nowhere to store a confidence value, and you have thrown away the one signal that tells you which figures a person should check.
That is the split worth naming before you choose an output. Rows and columns for a spreadsheet. Prose for a model to read, which is covered on PDF to markdown. Typed, nested fields with confidence for anything you post to another system, which is PDF to JSON extraction.
Real grids that a person opens in Excel: trial balances, rent rolls, price lists, transaction registers.
Feeding a whole document to a model, retrieval and search, anything read end to end.
Invoices, contracts and forms, where a header relates to nested line items and a wrong number has a consequence.
Whatever the format, you need a screen where a person fixes the values that came back uncertain.
If the PDF has a real text layer, a library such as Camelot, Tabula or pdfplumber can pull the table out locally and write the CSV for free. If the PDF is a scan, there is no text to parse and you need an OCR service that detects table structure: AWS Textract with the TABLES feature, Azure Document Intelligence Layout, Google Document AI, or Amazon Bedrock Data Automation, which is the only one of the four that returns a finished CSV.
No. Textract returns tables as Block objects in JSON: a TABLE block linked to one CELL block per cell, each carrying RowIndex, ColumnIndex and a confidence value. There is no CSV output in any Textract operation. AWS answers the question with a documentation code sample called "Exporting Tables into a CSV File", which is to say you write the conversion yourself.
Amazon Bedrock Data Automation is the only major one. Every TABLE entity in its standard output carries a representation object with csv, html, markdown and text versions of the same table at once, and the asynchronous API also writes a csv_s3_uri and one CSV file per table into your output bucket. Textract, Azure Document Intelligence and Google Document AI all return cell-level JSON instead.
More than reading the text does. Plain recognition is $1.50 per 1,000 pages on Azure Read, AWS Textract and Google Enterprise Document OCR, and none of the three detects tables. Table structure costs $15.00 per 1,000 pages on Textract AnalyzeDocument, $10.00 on Azure Layout, $10.00 on Bedrock Data Automation and $30.00 on Google Form Parser.
Because recognizing characters and understanding a grid are different jobs. Plain OCR reports where words sit on the page. Table extraction has to decide which words share a row, which share a column, where a cell is merged across three columns and which row is the header. Every vendor prices that as a separate feature or a separate model, so the cheap meter never includes it.
Yes, but only with OCR. Camelot, Tabula and pdfplumber work by reading the text layer and the ruling lines drawn in the PDF, and a scanned page has neither, so they return an empty result rather than an error. Send the scan to a service that detects table structure from the image, and test it on your worst document rather than your cleanest one.
For a digital PDF, pip install camelot-py or pdfplumber, read the table, and call to_csv on the resulting DataFrame. For a scan, call an OCR API and reconstruct the grid from the response. With Google, the Document AI Toolbox library shortens this: table.to_dataframe() gives you a DataFrame, then df.to_csv() writes the file. With Textract you walk the Block list yourself, and you have to read MERGED_CELL blocks separately or you lose every merged cell.
Almost always because you iterated Textract CELL blocks. The documentation states that a CELL block always reports a row span of 1 and a column span of 1, no matter what the document shows. The real spans are published on separate MERGED_CELL blocks listed under the table's MERGED_CELL relationship, so a loop that reads only CELL blocks flattens every merge and shifts the columns after it.
No. Layout returns tables as JSON: a tables array with rowCount and columnCount, and a flat cells array where each cell carries rowIndex, columnIndex, columnSpan, its content and a kind of "columnHeader" where it is a header. That is everything you need to build a CSV, but Microsoft does not build it for you, and the word "csv" does not appear in the Layout documentation at all.
No. Azure documents the Read model as returning pages, paragraphs, lines, words and styles. There is no tables collection in the Read response. This matters commercially, because Read is the $1.50 per 1,000 page meter and Layout, the model that does return tables, is $10.00. Anyone budgeting a table extraction job from the Read price is out by a factor of about 6.7.
A statement is a table that runs across page boundaries, which is the case most extractors handle worst. Two things matter: whether the service models a table that continues onto the next page as one table, which Bedrock Data Automation does through its page_indices array, and whether you can validate the result, because a statement has a built-in check in that the transactions have to reconcile to the closing balance.
Yes, and at volume the meter is the whole decision. One hundred thousand pages of table extraction is $1,500 on Textract, $1,000 on Azure Layout or Bedrock Data Automation and $3,000 on Google Form Parser. Textract drops to $10.00 per 1,000 above one million pages and Azure Read drops to $0.60, but neither hyperscaler publishes a batch discount, so an overnight job costs exactly what a real-time one does.
Usually not. An invoice is a record with a header and a set of line items, not a grid. Flatten it to CSV and you either repeat the invoice number on every line or lose the relationship between the header and the lines. If the destination is an accounting system, you want typed fields with confidence values and a review step, and the line items as a nested array rather than a second file.
For digital PDFs with a real text layer, a local library costs nothing beyond your own compute and is genuinely the right answer for a one-off job. For scans at volume, Azure Layout and Bedrock Data Automation are the cheapest verified table-capable cloud meters at $10.00 per 1,000 pages, and Bedrock is the one that saves you writing the CSV writer.
The Block model walked through end to end, including the merged-cell trap that corrupts exports.
The hardest part of any CSV conversion, handled on its own terms.
When you need typed, nested fields and confidence values rather than a flat grid.
The other output format, and the same 6.7 times meter jump on both hyperscalers.
Page ceilings, file sizes and throughput quotas on the synchronous and async APIs.
Every vendor normalized to one unit so the meters can be compared directly.
The one AWS meter that does return CSV, priced in full.
The table that runs across page boundaries, and what it costs to extract.
Working code for calling a recognition service and reading the response.
What changes at 100,000 pages a month and above.
File sizes, page ceilings and retention windows across every major service.
The buying decision rather than the rate card.
Every service on this page will produce a convincing CSV from a clean, ruled table. The differences show up on a multirow header with cells merged across columns. Upload that one.
Capability claims on this page were read from each vendor's own documentation on 14 August 2026. Azure rates come from the public Azure Retail Prices API for eastus. Capabilities and rates change. Verify at the source before you sign anything.