Independent guide — not affiliated with IBM or the Docling project. Every command verified on Docling 2.143.1.
  1. Home
  2. Python API
Python API guide

The Docling Python API, from first call to production

Everything you need to call Docling from Python: the converter, the options that actually change results, batch processing that survives bad files, and how to get Markdown, JSON, HTML and pandas tables out of a DoclingDocument. Every snippet below ran on Docling 2.143.1.

Verified on Docling 2.143.1Updated 27 Oct 202612 min read
In short
  • DocumentConverter().convert(source) accepts a path, a URL or an in-memory stream and returns a ConversionResult; the structured output is result.document.
  • Configure PDFs with PdfPipelineOptions inside PdfFormatOption. Defaults: OCR on (auto engine), tables on (accurate), 4 threads, device auto.
  • Use convert_all(..., raises_on_error=False) for batches and check result.status.
  • Export with export_to_markdown(), save_as_json(), export_to_html(); tables become pandas with table.export_to_dataframe(doc=doc).

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.

pythonconvert.py
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#

ArgumentDefaultWhat it does
source—A Path, a string path or URL, or a DocumentStream
headersNoneHTTP headers used when source is a URL (for example an auth token)
raises_on_errorTrueRaise on failure instead of returning a failed result
max_num_pagesno limitSkip documents with more pages than this
max_file_sizeno limitSkip files larger than this many bytes
page_range(1, ∞)Convert only these pages, 1-based and inclusive, e.g. (1, 10)
progress_callbackNoneReceives 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.

python
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).document

Configure the PDF pipeline#

Options are set per input format. For PDFs (and images) that means a PdfPipelineOptions object wrapped in PdfFormatOption:

pythonpipeline_options.py
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:

OptionDefaultNotes
do_ocrTrueOCR runs on regions without a PDF text layer (the default mode)
ocr_optionsOcrAutoOptions()Picks an installed engine; RapidOCR with the standard install
do_table_structureTrueTableFormer rebuilds rows, columns and spans
table_structure_options.modeACCURATEFAST was 11% faster end-to-end in our benchmark
accelerator_options4 threads, device="auto"auto picks CUDA, then Apple MPS, then Intel XPU, then CPU
images_scale1.0Resolution of exported page and picture images
generate_page_images / generate_picture_imagesFalseNeeded if you export images
do_formula_enrichment / do_code_enrichmentFalseFormula → LaTeX; code-block recognition
do_picture_description / do_picture_classificationFalseCaptions and figure types via extra models
do_chart_extractionFalseBar, pie and line charts → tables
document_timeoutNoneStop a document after N seconds
enable_remote_servicesFalseMust be True for API-based models
artifacts_pathNoneLocal 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.

pythonbatch.py
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#

python
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.

FieldContains
textsParagraphs, titles, section headers (with level), list items, captions, footnotes, formulas, code
tablesTableItems with a cell grid (data.num_rows, data.num_cols, spans)
picturesFigures, optional classification and description
groupsLists, chapters and other containers
body / furnitureMain reading-order tree / page headers and footers
pagesPage sizes and, if generated, page images

A real item from our conversion of the Docling technical report:

jsondoc.texts[2] (abridged)
{
  "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" } }]
}
pythonwalk the document
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#

python
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 wantCall
Markdown string / filedoc.export_to_markdown() / doc.save_as_markdown(path)
Lossless JSON (re-loadable)doc.save_as_json(path) · reload with DoclingDocument.load_from_json(path)
HTMLdoc.export_to_html() / doc.save_as_html(path)
Plain textdoc.export_to_text()
Python dictdoc.export_to_dict()
YAMLdoc.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 RAGHybridChunker().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:

python
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_range when you only need the first pages, e.g. for classification.
  • Set document_timeout so 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