Convert one document#
The whole API starts from DocumentConverter. Creating it is cheap; models load on the first conversion and are reused afterwards, so keep one converter for the life of your process.
from docling.document_converter import DocumentConverter
converter = DocumentConverter()
result = converter.convert("https://arxiv.org/pdf/2408.09869") # path, URL or DocumentStream
print(result.status) # ConversionStatus.SUCCESS
doc = result.document # a DoclingDocument
print(doc.export_to_markdown()[:300])convert() returns a ConversionResult. Besides document it carries status, errors, pages, timings and confidence (per-page quality scores), which are useful for routing low-confidence pages to human review.
What convert() accepts#
| Argument | Default | What it does |
|---|---|---|
source | — | A Path, a string path or URL, or a DocumentStream |
headers | None | HTTP headers used when source is a URL (for example an auth token) |
raises_on_error | True | Raise on failure instead of returning a failed result |
max_num_pages | no limit | Skip documents with more pages than this |
max_file_size | no limit | Skip files larger than this many bytes |
page_range | (1, ∞) | Convert only these pages, 1-based and inclusive, e.g. (1, 10) |
progress_callback | None | Receives document, phase and per-page progress events |
Signatures read from DocumentConverter.convert in 2.143.1. convert_all() takes the same arguments with an iterable of sources.
Convert from memory#
When a file arrives as bytes — an upload, an S3 object, an email attachment — wrap it in a DocumentStream. The file name's extension decides which backend reads it.
from io import BytesIO
from docling.datamodel.base_models import DocumentStream
from docling.document_converter import DocumentConverter
data = open("report.pdf", "rb").read() # or bytes from S3, an API, …
stream = DocumentStream(name="report.pdf", stream=BytesIO(data))
doc = DocumentConverter().convert(stream).documentConfigure the PDF pipeline#
Options are set per input format. For PDFs (and images) that means a PdfPipelineOptions object wrapped in PdfFormatOption:
from docling.datamodel.accelerator_options import AcceleratorOptions
from docling.datamodel.base_models import InputFormat
from docling.datamodel.pipeline_options import (
PdfPipelineOptions, TableFormerMode, TableStructureOptions,
)
from docling.document_converter import DocumentConverter, PdfFormatOption
opts = PdfPipelineOptions()
opts.do_ocr = False # born-digital PDFs: 3.7x faster in our test
opts.do_table_structure = True
opts.table_structure_options = TableStructureOptions(mode=TableFormerMode.ACCURATE)
opts.accelerator_options = AcceleratorOptions(num_threads=8, device="auto")
opts.document_timeout = 300 # seconds; partial result after this
converter = DocumentConverter(
format_options={InputFormat.PDF: PdfFormatOption(pipeline_options=opts)}
)These are the defaults that matter most, read from the model fields of PdfPipelineOptions in 2.143.1:
| Option | Default | Notes |
|---|---|---|
do_ocr | True | OCR runs on regions without a PDF text layer (the default mode) |
ocr_options | OcrAutoOptions() | Picks an installed engine; RapidOCR with the standard install |
do_table_structure | True | TableFormer rebuilds rows, columns and spans |
table_structure_options.mode | ACCURATE | FAST was 11% faster end-to-end in our benchmark |
accelerator_options | 4 threads, device="auto" | auto picks CUDA, then Apple MPS, then Intel XPU, then CPU |
images_scale | 1.0 | Resolution of exported page and picture images |
generate_page_images / generate_picture_images | False | Needed if you export images |
do_formula_enrichment / do_code_enrichment | False | Formula → LaTeX; code-block recognition |
do_picture_description / do_picture_classification | False | Captions and figure types via extra models |
do_chart_extraction | False | Bar, pie and line charts → tables |
document_timeout | None | Stop a document after N seconds |
enable_remote_services | False | Must be True for API-based models |
artifacts_path | None | Local model folder for offline use |
For OCR engines and languages see the OCR guide; for the vision-language pipeline see VLM & Granite-Docling. The config builder writes this code for you.
Batch conversion that survives bad files#
convert_all() yields results lazily, so memory stays flat on large folders. With raises_on_error=False, a corrupt file becomes a failed result instead of an exception.
from pathlib import Path
from docling.datamodel.base_models import ConversionStatus
from docling.document_converter import DocumentConverter
converter = DocumentConverter()
files = sorted(Path("inbox").glob("*.pdf"))
out = Path("out"); out.mkdir(exist_ok=True)
for res in converter.convert_all(files, raises_on_error=False):
name = res.input.file.stem
if res.status in (ConversionStatus.SUCCESS, ConversionStatus.PARTIAL_SUCCESS):
res.document.save_as_markdown(out / f"{name}.md")
res.document.save_as_json(out / f"{name}.json")
else:
print(f"{name}: {res.status.value}", [e.error_message for e in res.errors])The statuses defined in 2.143.1 are pending, started, failure, success, partial_success and skipped. partial_success usually means a timeout or a page that failed — the document still has the pages that worked.
Restrict which formats are accepted#
from docling.datamodel.base_models import InputFormat
from docling.document_converter import DocumentConverter
converter = DocumentConverter(
allowed_formats=[InputFormat.PDF, InputFormat.DOCX, InputFormat.PPTX]
)Files of any other format are rejected rather than converted — handy for upload endpoints. The full list of 36 InputFormat values is on the formats page.
Inside a DoclingDocument#
A DoclingDocument is a tree plus flat lists of items. Each item has a label, its text or data, and prov (provenance: page number and bounding box), so you can always trace an answer back to where it came from on the page.
| Field | Contains |
|---|---|
texts | Paragraphs, titles, section headers (with level), list items, captions, footnotes, formulas, code |
tables | TableItems with a cell grid (data.num_rows, data.num_cols, spans) |
pictures | Figures, optional classification and description |
groups | Lists, chapters and other containers |
body / furniture | Main reading-order tree / page headers and footers |
pages | Page sizes and, if generated, page images |
A real item from our conversion of the Docling technical report:
{
"self_ref": "#/texts/2",
"label": "section_header",
"level": 1,
"text": "Version 1.0",
"prov": [{ "page_no": 1,
"bbox": { "l": 283.31, "t": 511.98, "r": 328.69, "b": 503.43,
"coord_origin": "BOTTOMLEFT" } }]
}for item, level in doc.iterate_items():
page = item.prov[0].page_no if item.prov else None
print(level, item.label, page, getattr(item, "text", "")[:60])Tables to pandas#
for i, table in enumerate(doc.tables):
df = table.export_to_dataframe(doc=doc)
print(f"table {i}: {df.shape}")
df.to_csv(f"table_{i}.csv", index=False)Pass doc=doc: it lets the table resolve its captions and references. On our test document, Docling found 3 tables; the first came out as a 4 × 8 grid.
Export formats#
| You want | Call |
|---|---|
| Markdown string / file | doc.export_to_markdown() / doc.save_as_markdown(path) |
| Lossless JSON (re-loadable) | doc.save_as_json(path) · reload with DoclingDocument.load_from_json(path) |
| HTML | doc.export_to_html() / doc.save_as_html(path) |
| Plain text | doc.export_to_text() |
| Python dict | doc.export_to_dict() |
| YAML | doc.save_as_yaml(path) |
| DocTags (for VLM training/eval) | doc.export_to_doctags() / doc.save_as_doctags(path) |
| WebVTT (audio/video transcripts) | doc.export_to_vtt() / doc.save_as_vtt(path) |
| Chunks for RAG | HybridChunker().chunk(doc) — see RAG & chunking |
Images in the output
Markdown, HTML and JSON can carry pictures three ways via image_mode: PLACEHOLDER (a comment marks the spot — the default), EMBEDDED (base64 inline) or REFERENCED (PNG files next to the document). Images must have been generated during conversion:
from docling_core.types.doc import ImageRefMode
opts.generate_picture_images = True # in PdfPipelineOptions, before converting
opts.images_scale = 2.0
...
doc.save_as_markdown("report.md", image_mode=ImageRefMode.REFERENCED)Other input formats#
Office, HTML, Markdown and most XML formats do not use the PDF pipeline at all: they are parsed directly from their structure, so they convert in a fraction of a second and need no OCR or layout model. Images go through the same pipeline as PDFs. Audio and video use the ASR pipeline. Details per format are on the supported formats page.
Performance tips that matter#
- Turn OCR off for born-digital PDFs — the single biggest win in our measurements (8.5 → 2.3 s/page).
- Reuse one converter. The first conversion includes model loading (our cold run was 27.5 s vs 20.8 s warm for the same 9 pages).
- Use
page_rangewhen you only need the first pages, e.g. for classification. - Set
document_timeoutso one pathological file cannot stall a batch.
More numbers in the performance guide.
Frequently asked questions
How do I convert a PDF to Markdown with Docling in Python?
Create a DocumentConverter, call convert() with the file path or URL, then call result.document.export_to_markdown(). For a born-digital PDF, set pipeline_options.do_ocr = False for a large speed-up.
How do I convert many files without stopping on errors?
Use converter.convert_all(paths, raises_on_error=False) and check each result.status, which is one of success, partial_success, failure or skipped.
How do I get tables out of Docling as a DataFrame?
Loop over result.document.tables and call table.export_to_dataframe(doc=result.document). pandas is installed with the standard docling package.
Can Docling convert a file from memory instead of disk?
Yes. Wrap bytes in DocumentStream(name='file.pdf', stream=BytesIO(data)) and pass it to convert(). The name's extension tells Docling which format to use.
How do I limit the pages Docling converts?
Pass page_range=(1, 10) to convert(), or max_num_pages to skip documents that are longer than a limit.
Sources
- Docling source: docling/document_converter.py (2.143.1)
- Docling source: PdfPipelineOptions (docling/datamodel/pipeline_options.py)
- Official docs: DoclingDocument concept
- Docling technical report (arXiv 2408.09869)