Files
pdf/gateway/docs/limits.md
T

4.7 KiB

Supported formats, and what they honestly do

Two ideas are kept apart throughout this service, because conflating them is how customers get surprised:

  • Reproduction — the output is the input's pixels or bytes. Nothing is interpreted, so nothing can be misinterpreted.
  • Reconstruction — the output is the engine's reading of the document. It is labelled lossy, because it is.

Every reconstruction target below is lossy. That is a property of the problem: a PDF records where ink went, not what a paragraph was, and recovering the second from the first is inference.

Conversions

43 converters. pdf → * are reconstructions unless marked otherwise.

From To
pdf docx xlsx csv json md html txt · png jpeg tiff (reproduction) · pdf (passthrough, or searchable)
docx pdf html md txt json · docx (passthrough)
xlsx pdf csv html md txt json
pptx pdf html md txt json
csv xlsx pdf html md
md pdf html
html pdf docx md
txt pdf docx md
png jpeg tiff pdf

pdf → pdf

Byte-identical passthrough by default, and that is a promise: a signed or archived PDF that came back re-encoded would be a different artefact.

With an explicit ocr_policy=force, it instead returns a searchable PDF — the original page images unchanged, with the recognised text laid over them at render mode 3 (drawn, extractable, painting nothing). Automatic routing choosing force is not enough to trigger this: that decision is made to help reconstruction targets recover text, and treating it as permission to re-encode the source would mean every scan came back as a different file.

The searchable path rasterises at 200 dpi, so a 300 dpi scan is resampled down. That is why it is opt-in.

Input limits

Limit Value On exceeding
File size 50 MB 413 resource_limit
PDF pages 200 413 resource_limit
Archive entries bounded 413 resource_limit
Archive uncompressed size bounded 413 resource_limit
Archive nesting depth bounded 413 resource_limit
Archive compression ratio bounded 413 resource_limit

Legacy .doc and .docm are refused with a clear message rather than parsed badly. A PDF with a user password is refused; one with only an owner password is converted, with a warning saying so, because such files are readable and common and refusing them turns away legitimate documents.

For inputs beyond these limits, split the document. Chunking is deliberately the caller's decision: an engine that silently splits a 400-page contract and reassembles it has made a structural choice nobody sanctioned.

Known limitations

Each is disclosed in the output's warnings, not just here.

Embedded Word charts (writers/pdf_from_docx.py) render as a labelled placeholder in docx → pdf. The chart is a full DrawingML plotting specification; rendering it faithfully means implementing a chart engine, and an approximation with wrong axes is worse than an honest placeholder.

OCR page cap — 50 pages per document by default. Beyond it the document converts with a warning naming the pages that were skipped.

Arabic OCR roughly doubles recognition time and runs only when the weights are present. Mixed-script documents are merged per line by score.

Reading order on unusual layouts — recursive XY-cut handles columns, sidebars and pull-quotes. A layout with no straight cut anywhere (heavily overlapping artwork, spiral text) degrades to top-to-bottom.

Table detection is conservative by design. Three detectors are tried, most reliable first, each gated by a plausibility check. Prose that merely lines up in columns will not become a table; a borderless table with irregular spacing may not either. Soup tables are worse than missing ones.

A page that cannot be reconstructed is embedded as a page image rather than having a layout invented for it, and says so in the warnings.

Licensing

Every runtime dependency is permissively licensed and every model is freely redistributable:

Component Licence
FastAPI, uvicorn, pydantic MIT / BSD
pypdf BSD-3-Clause
pypdfium2 (bindings) / PDFium Apache-2.0 / BSD-3-Clause
RapidOCR ONNX Runtime Apache-2.0
ONNX Runtime MIT
Pillow MIT-CMU
python-docx, openpyxl MIT
reportlab BSD-3-Clause
beautifulsoup4, lxml MIT / BSD
markdown-it-py MIT
arabic-reshaper, mammoth MIT / BSD

No component is AGPL, no component is commercial, and no document is sent to a third-party conversion service. The optional Mistral OCR path is off unless a key is configured, and the engine says so in the conversion's warnings when it is used.