Convert a scanned PDF to Excel
Convert a scanned PDF to Excel by reading each page image into structured fields, spot-checking against the source, then exporting a UTF-8 BOM CSV Excel opens cleanly.
A scanned PDF is not really a spreadsheet hiding inside a file — it is a picture of a document. Each page is an image of rows, columns, and totals that look like a table to a human but are just pixels to a computer. That is why "export to Excel" buttons rarely exist for scans: there are no cells to export, only an image. To get real rows you have to read the page back into structured fields, then write those fields out as a file Excel can open.
That is exactly the workflow here. You take the document image (a scanned page, a phone photo, a faxed receipt), extract the values as named fields, and export a CSV that opens directly in Excel — UTF-8 with a byte-order mark, so Japanese, Korean, and Chinese text land in the right columns instead of turning into mojibake. The payoff to "convert scanned PDF to Excel" is that CSV.
Why a scan can't go straight to Excel
When you scan a paper invoice, the result is a raster image — the same kind of file as a JPEG photo. space-ocr accepts those raster formats directly: JPEG, PNG, GIF, BMP, TIFF, and WebP. If your source is a multi-page PDF, you have two paths: drop the PDF straight into the space-ocr app and it renders each page to an image for you automatically, or — if you're calling the REST API directly — export each page as an image first (PNG or TIFF) and send those. Either way, the OCR runs on page images.
The engine reads each image, finds the values, and returns the source coordinates a value was read from where it can resolve them — an axis-aligned box plus a four-point quad that follows the tilt of the page, both on a 0–1000 normalized grid. Where it cannot resolve a region, or where the characters do not line up with what is printed, the value comes back flagged for review instead of passing quietly. Once the page is structured into fields, turning it into Excel is just a CSV download. The hard part — and the part worth getting right — is the read, not the export.
From document image to structured fields
Upload a document image — or just drop a photo or a PDF — and the values come out as named fields, not a wall of text. The fastest path is to let the app suggest the fields for you: drop the page and it proposes a schema automatically, with no setup. If you already know which columns you want, declare them yourself instead — a name and a type per column, reused for every page you add to that sheet. Watch a scan turn into labeled columns:
For documents with repeating rows — invoice line items, receipt products — declare an array field with child columns. Each line on the page becomes its own row, which is what you want when the spreadsheet has to add up. If you are wrangling those repeating rows specifically, see extract line items from invoices for the field-spec details.
{
"image": "https://example.com/scanned-page-01.png",
"imageType": "url",
"fields": [
{ "name": "vendor", "type": "string" },
{ "name": "invoice_date", "type": "string" },
{ "name": "total", "type": "string" },
{
"name": "line_items", "type": "array",
"children": [
{ "name": "description", "type": "string" },
{ "name": "unit_price", "type": "string" },
{ "name": "qty", "type": "string" }
]
}
]
}The values are not normalized for you. A printed 7,855 comes back as 7,855 — commas, decimals, and full-width characters are kept as they were read rather than rewritten into a canonical number, so your totals reconcile against the page. The currency symbol you see in the app is UI decoration, not part of the value. Nothing you write in a field's description changes that — a value has to stay close to what was printed for its coordinates and its cross-check to mean anything. values is still the model's reading of the page, so when you need a character-exact comparison, use evidence.printed_text: the raw OCR glyphs at those coordinates. If you need a number to compute with, the API can hand you one beside the printed text: declare the field's type as number, integer or date and the response carries a parsed normalized copy alongside values.
Spot-check, then export to Excel
Before you import anything into Excel, sanity-check the read. Hover a value and the source region lights up on the original image, so your eye goes straight to the spot instead of re-reading the whole scan.
You don't have to inspect every value by eye either, because the read comes back with its own work list. data.review.flagged holds one entry per value that needs a second look, each with the path of the value and the reasons it was flagged: text_mismatch when the characters didn't line up with the page, nobox when no source region could be resolved, missing when a field you declared as required came back empty. The cell's verified is the verdict on that — false as soon as anything is flagged. Work that list and leave the rest alone. evidence.match_ratio sits on the cell as supporting detail, not as a threshold you're meant to gate on.
Export the CSV that opens in Excel
When the fields look right, export the sheet. You get <sheetName>.csv with a header row of your column names; array fields expand into column.child columns and repeating line items unfold into sub-rows. The file is UTF-8 with a BOM, which is the specific detail that makes Excel open CJK text cleanly on double-click. Any manual corrections you made override the original OCR value in the export.
The export itself costs 1 credit on the Free and Pay-as-you-go plans; on Starter and Pro, downloads are free. Re-downloading the same data is free on any plan.
To open it in Excel: just double-click the .csv. Because of the BOM, Excel reads it as UTF-8 automatically — no Text Import Wizard, no garbled characters. From there, Save As → .xlsx if you need a native workbook. If your end goal is a plain CSV pipeline rather than Excel specifically, the companion guide on turning scanned documents into CSV covers the same export end to end.
Doing it at scale via the API
For a folder of scans, create a sheet with your column schema once, then upload page images to that sheet. Each image is read against that schema and appended as rows you can later export as one CSV.
POST /upload takes up to 20 files per request, 20 MB per file and 28 MB for the whole request; anything larger comes back as a 413. Each page costs 1 credit ($0.05, tax included). The call is asynchronous by default: the response carries a jobs[] array, and each result arrives through the ocr.completed webhook or a GET /jobs/{jobId} poll. Adding wait=true, as the request below does, waits inline instead — up to 30 seconds per image, with anything slower returned as status: "pending" for you to collect afterwards. If you retry a request, send an Idempotency-Key so the repeat replays the cached response instead of scanning twice. The full request/response shapes are in the API docs.
curl -X POST https://api.space-ocr.com/upload \
-H "Authorization: Bearer $SPACE_OCR_API_KEY" \
-F "path=/Invoices 2026" \
-F "files=@scan-page-01.png" \
-F "files=@scan-page-02.png" \
-F "wait=true"How to convert a scanned PDF to Excel
- Add your PDF or page imagesIn the space-ocr app, just drop the PDF — each page is rasterized to an image automatically, so there's nothing to convert. If you call the REST API directly, export each page as a raster image first, since the engine reads raster images (JPEG, PNG, GIF, BMP, TIFF, WebP), not PDF bytes.
- Read the page into fieldsExtract the values as named fields. The quickest way is to let the app auto-suggest the fields from the page; you can also declare the columns yourself. Declare an array field for repeating line items.
- Spot-check the valuesHover a field to highlight where it was read from on the original scan, then work through the values the read flagged for review. The API returns them in data.review.flagged with a reason for each, so you check those and leave the rest as they are.
- Export the CSVExport the sheet to a CSV. It is UTF-8 with a BOM and expands array line items into sub-rows, with any manual corrections overriding the original OCR value.
- Open in ExcelDouble-click the CSV — Excel reads the BOM and opens your rows with columns aligned and CJK text intact. Save As .xlsx if you need a native workbook.