Independent guide — not affiliated with IBM or the Docling project. Every command verified on Docling 2.148.0.
  1. Home
  2. Recipes
Recipes

Docling recipes — copy, paste, it runs

Short, complete scripts for the jobs people actually do with Docling. We ran every one of them on Docling 2.148.0 against the Docling technical report and a Word file before publishing.

Verified on Docling 2.148.0Updated 6 Nov 202612 min read
In short
  • Each recipe is self-contained: imports, conversion, output.
  • Set do_ocr = False in recipes for born-digital PDFs — it is the biggest speed-up.
  • Keep one DocumentConverter per process and reuse it.

1 · PDF to Markdown with images as files#

pythonpdf_to_md_with_images.py
from pathlib import Path
from docling.datamodel.base_models import InputFormat
from docling.datamodel.pipeline_options import PdfPipelineOptions
from docling.document_converter import DocumentConverter, PdfFormatOption
from docling_core.types.doc import ImageRefMode

opts = PdfPipelineOptions(do_ocr=False, generate_picture_images=True, images_scale=2.0)
converter = DocumentConverter(format_options={InputFormat.PDF: PdfFormatOption(pipeline_options=opts)})

doc = converter.convert("report.pdf").document
out = Path("out"); out.mkdir(exist_ok=True)
doc.save_as_markdown(out / "report.md", artifacts_dir=Path("images"), image_mode=ImageRefMode.REFERENCED)
print(sorted(p.name for p in (out / "images").glob("*.png"))[:3])

Pictures are written as PNG files into out/images and linked from the Markdown with relative paths. A relative artifacts_dir is resolved against the Markdown file's folder — if you leave it out and save into a subfolder, docling-core 2.106.0 nests the images one level deeper (out/out/report_artifacts), which surprised us in testing.

2 · Convert a whole folder, survive bad files, write a report#

pythonbatch_folder.py
import csv
from pathlib import Path
from docling.datamodel.base_models import ConversionStatus
from docling.document_converter import DocumentConverter

src, out = Path("inbox"), Path("out")
out.mkdir(exist_ok=True)
converter = DocumentConverter()

with open(out / "report.csv", "w", newline="") as f:
    log = csv.writer(f)
    log.writerow(["file", "status", "pages", "seconds"])
    files = [p for p in src.iterdir() if p.is_file()]
    for res in converter.convert_all(files, raises_on_error=False):
        name = res.input.file.name
        if res.status in (ConversionStatus.SUCCESS, ConversionStatus.PARTIAL_SUCCESS):
            res.document.save_as_markdown(out / f"{res.input.file.stem}.md")
        secs = sum(sum(t.times) for k, t in res.timings.items() if k == "pipeline_total")
        log.writerow([name, res.status.value, len(res.pages), round(secs, 1)])

pipeline_total is only filled when profiling is on (settings.debug.profile_pipeline_timings = True); otherwise the seconds column is 0.

3 · Every table to CSV and one Excel workbook#

pythontables_to_csv_excel.py
import pandas as pd
from docling.document_converter import DocumentConverter

doc = DocumentConverter().convert("report.pdf").document
with pd.ExcelWriter("tables.xlsx") as xls:
    for i, table in enumerate(doc.tables, start=1):
        df = table.export_to_dataframe(doc=doc)
        df.to_csv(f"table_{i}.csv", index=False)
        df.to_excel(xls, sheet_name=f"table_{i}", index=False)
        print(i, df.shape, "page", table.prov[0].page_no)

openpyxl, which pandas uses to write .xlsx, is installed with Docling.

4 · One Markdown file per page#

pythonper_page.py
from docling.document_converter import DocumentConverter

doc = DocumentConverter().convert("report.pdf").document
for page_no in sorted(doc.pages):
    md = doc.export_to_markdown(page_no=page_no)
    with open(f"page_{page_no:03d}.md", "w") as f:
        f.write(md)
print(len(doc.pages), "pages written")

5 · Find pages that need a human look#

Each ConversionResult carries a confidence report with parse, layout, table and OCR scores per page and an overall grade (poor, fair, good or excellent).

pythonlow_confidence.py
from docling.document_converter import DocumentConverter

res = DocumentConverter().convert("report.pdf")
conf = res.confidence
print("document:", conf.mean_grade.value, round(conf.mean_score, 3))
for page_no, scores in sorted(conf.pages.items()):
    print(page_no, scores.mean_grade.value, round(scores.layout_score, 3))

6 · Figures with their captions#

pythonfigures.py
from docling.datamodel.base_models import InputFormat
from docling.datamodel.pipeline_options import PdfPipelineOptions
from docling.document_converter import DocumentConverter, PdfFormatOption

opts = PdfPipelineOptions(do_ocr=False, generate_picture_images=True, images_scale=2.0)
conv = DocumentConverter(format_options={InputFormat.PDF: PdfFormatOption(pipeline_options=opts)})
doc = conv.convert("report.pdf").document

for i, pic in enumerate(doc.pictures, start=1):
    img = pic.get_image(doc)
    if img is not None:
        img.save(f"figure_{i}.png")
    print(i, pic.prov[0].page_no, pic.caption_text(doc)[:70])

7 · Convert bytes (S3, an upload, an email attachment)#

pythonfrom_bytes.py
from io import BytesIO
from docling.datamodel.base_models import DocumentStream
from docling.document_converter import DocumentConverter

data = open("report.pdf", "rb").read()        # e.g. s3.get_object(...)["Body"].read()
doc = DocumentConverter().convert(DocumentStream(name="report.pdf", stream=BytesIO(data))).document
print(doc.name, len(doc.texts))

8 · Only the first pages#

pythonfirst_pages.py
from docling.document_converter import DocumentConverter

res = DocumentConverter().convert("report.pdf", page_range=(1, 2))
print(len(res.pages), "pages converted")
print(res.document.export_to_markdown()[:200])

9 · Word, PowerPoint and Excel to Markdown#

pythonoffice.py
from docling.document_converter import DocumentConverter

converter = DocumentConverter()
for name in ["memo.docx"]:                     # .pptx and .xlsx work the same way
    md = converter.convert(name).document.export_to_markdown()
    print(md)

Office files skip the layout and OCR models: our two-paragraph Word file with a table converted in a fraction of a second.

10 · Save once, re-export later without reconverting#

pythonreexport.py
from docling.document_converter import DocumentConverter
from docling_core.types.doc import DoclingDocument

DocumentConverter().convert("report.pdf").document.save_as_json("report.json")

doc = DoclingDocument.load_from_json("report.json")   # instant, no models
doc.save_as_html("report.html")
print(doc.export_to_text()[:120])

11 · Chunks to JSONL for a vector store#

pythonchunks_jsonl.py
import json
from docling.chunking import HybridChunker
from docling.document_converter import DocumentConverter

doc = DocumentConverter().convert("report.pdf").document
chunker = HybridChunker(max_tokens=512)
with open("chunks.jsonl", "w") as f:
    for i, ch in enumerate(chunker.chunk(doc)):
        f.write(json.dumps({
            "id": f"report-{i}",
            "text": chunker.contextualize(ch),
            "headings": ch.meta.headings,
            "pages": sorted({p.page_no for it in ch.meta.doc_items for p in it.prov}),
        }) + "\n")

12 · A web page to Markdown#

pythonhtml_url.py
from docling.document_converter import DocumentConverter

doc = DocumentConverter().convert("https://en.wikipedia.org/wiki/Optical_character_recognition").document
print(doc.export_to_markdown()[:400])

HTML is parsed from the DOM, so it converts quickly with headings, lists and tables intact.

Frequently asked questions

Where are the official Docling examples?

The Docling documentation has an examples section at docling-project.github.io/docling/examples. The recipes here are independent, shorter and each was run on Docling 2.148.0.

Do these recipes work with older Docling versions?

Most do from 2.x, but some APIs used here (the confidence report, docling.chunking imports) are recent. Upgrade to the version shown at the top of the page if something is missing.