---
title: "OCR and documents"
description: "Convert Office files, ebooks and PDFs to Markdown, and read text out of scanned pages."
---

Webfold converts documents through the Superdocuments library. Plain formats convert directly. A PDF page with no text layer falls back to optical character recognition.

## Formats

| Format | Route |
| --- | --- |
| DOCX, DOCM | Markdown through `convert` |
| PPTX | Text per slide |
| XLSX, XLSM, XLSB | One section per sheet; structured sheet reads are available in the library |
| ODT, ODP, ODS | Markdown through `convert` |
| EPUB | Markdown, or spine-ordered text and a book structure in the library |
| RTF, CSV, HTML, text | Markdown |
| Legacy XLS | Through Webfold's own adapter (`webfold convert`), not the library alone |
| PDF | Text extraction to Markdown, with an optional OCR fallback |

```sh
webfold convert report.docx
webfold pdf report.pdf
webfold pdf scan.pdf --chunk 4000
webfold chunk notes.docx --size 3000 --jsonl
```

## How OCR works

1. The PDF parser reads each page's own text layer.
2. A page with no text, or a scan whose only text is a stamp, is rendered to an image with Poppler's `pdftoppm`. Other pages keep their own text.
3. Tesseract recognises the text and it is returned as Markdown with the rest of the document.

:::note
OCR needs `pdftoppm` (Poppler) and `tesseract` installed on the machine. Without them an image-only page returns no text. Pass `--no-ocr` to `webfold pdf` or `webfold convert` to start neither tool: the native text is returned and stderr names the pages that were not read.
:::

In library code:

```rust
let markdown = superdocuments::pdf::extract_file("scan.pdf")?;
```

## Structure, not just text

The library also exposes structured output: `xlsx::read_workbook` and `read_sheet`, `epub::read`, `pdf::outline`, JSON page output and a `DocumentGraph` of regions with provenance.

## What to expect

:::warning
Superdocuments is a research build. The format matrix in its repository lists limits per format: for example DOCX headings come from the document's own styles, and legacy DOC files are read as text only. Mixed born-digital and scanned PDFs and unusual filters need more fixtures. OCR matched Tesseract run alone on eight small test PDFs and on the scanned sets of olmOCR-bench (47.2% of tests passed against 47.1%), so treat its output as a first pass. On 200 public PDFs the native parser scores 0.760 against 0.883 for liteparse, and it trails liteparse on tables and headings.
:::

See the [document benchmark](https://webfold.ai/benchmarks/documents/) for speed figures and their limits.

## Hosted API

```sh
curl -s https://api.webfold.ai/v1/ocr \
  -H "Authorization: Bearer $WEBFOLD_API_KEY" -H "Content-Type: application/json" \
  -d '{"content_base64":"<base64 of scan.pdf>","languages":"eng","max_pages":20}'
```

`POST /v1/ocr` reads the PDF's own text first (`"method": "text"`) and falls back to Tesseract for pages without one (`"method": "ocr"`). The file is sent in the request, up to 25 MiB. `languages` takes Tesseract codes such as `eng+deu`, `max_pages` is 1 to 200, and `timeout_secs` is 1 to 300. A server runs a few OCR jobs at once, so a busy one answers `503`; retry shortly. `POST /v1/documents/convert` does the same for Word, Excel, PowerPoint, OpenDocument, EPUB, RTF, CSV and HTML. See the [API reference](/docs/api-reference).
