Nodes/ComfyUI-DeepseekOCR-easy/🧠 DeepSeek OCR (Images → Markdown)
ComfyUI Node

🧠 DeepSeek OCR (Images → Markdown)

Scans and PDFs to Markdown, on your own GPU, no API key

By swan7-py·Created 9 months ago·Updated 9 months ago· 4
🧠 DeepSeek OCR (Images → Markdown)
  • images
  • markdown_text
modeGundam
task_typedocument

The name says "easy," and the pitch is the thing people actually want from OCR: drop in an image or a scanned page, get clean Markdown back - tables, formulas, and all - instead of the wall of garbled text most OCR spits out. This node runs DeepSeek-OCR (DeepSeek's open-source document model from fall 2025) locally in ComfyUI. No API key, no network round-trip, nothing leaving your machine. It's the kind of node you reach for when you're building a "digitize my document pile" workflow, or when you want reliable text extraction inside a bigger ComfyUI pipeline rather than tabbing out to a web tool.

What makes DeepSeek-OCR different from the OCR you're used to is that it's a vision-language model, not a classical text detector. It reads the page as an image and generates Markdown tokens, and the <|grounding|> prompt mode even gives you bounding boxes around where each piece of text lives. The community poked at it hard when it dropped and then mostly moved on - it's not a thing you hear about daily anymore, but it's quietly one of the best local options for document-to-Markdown.

How it works

Under the hood this node is a thin wrapper. On first run it loads the model through modelscope's AutoModel in bfloat16 and shoves it onto CUDA (there's no CPU or Mac fallback - you need an NVIDIA GPU). For every image in your batch it saves a temp PNG, calls model.infer() with one of the task prompts, then reads the Markdown result back out. Everything gets written to ComfyUI's output folder: per-page .mmd files in deepseek_ocr_results/, plus one combined deepseek_ocr_output.md that overwrites itself on every run.

One design note: the model is loaded fresh on each execution and freed when you're done (torch.cuda.empty_cache() and all). No caching means the first image of every run pays the weight-loading tax, but it also means the GPU is released the moment the node finishes - handy if you only OCR occasionally.

The inputs that matter

  • images (IMAGE) - your batch. Each image is treated as one page. The pack's own LoadPDFtoImage node feeds straight into this.
  • mode - inference resolution: Tiny, Small, Base, Large, and the default Gundam (1024×640 with cropping). Lower = faster and lighter on VRAM; Large (1280²) is sharper on dense fine print. Gundam is a good default - start there, drop to Base or Tiny if your GPU complains.
  • task_type - decides the prompt sent to the model: document (convert to Markdown, the default), without layouts (plain "Free OCR"), other image, figures in document, and general (describe the image). For scanned documents you want document; for a photo of a sign, other image.

The single output, markdown_text (STRING), is your result. It's an output node, so it previews in the UI, but wire it into a text-display or text-save node if you want to actually keep it - remember it's also already saved to deepseek_ocr_output.md.

Installing it

Two things to install: the pack and the model.

cd ComfyUI/custom_nodes
git clone https://github.com/swan7-py/ComfyUI-DeepseekOCR-easy.git

Restart ComfyUI. Manager users can just search "DeepSeek OCR" (the pack is published on the Comfy Registry). requirements.txt pulls modelscope, pdf2image, pypdf, Pillow, numpy, tqdm - modelscope is the chunky one.

Then the model. Do not use DeepSeek's official weights here - the author is explicit that they break with current transformers. Use the conversion linked in the README:

git clone https://huggingface.co/prithivMLmods/DeepSeek-OCR-Latest-BF16.I64 \
  ComfyUI/models/DeepSeek-OCR-Latest-BF16.I64

The node checks that exact path and raises a clear FileNotFoundError if it's missing.

Gotchas

The big one: the README advertises a custom_prompt override, but in the shipped code that field never made it into the node's inputs - the Python method still expects the argument, which can surface as a TypeError when you run it. Don't build a workflow around custom prompts unless you check the repo for a newer commit. Other things that bite: it's bf16-only on CUDA, so ~6GB VRAM minimum with Tiny/Base and more for Large; the output file is clobbered each run; and if your PDFs won't load at all, the problem is upstream - see the pack's PDF loader and its poppler requirement.

CategorySwanOCR

Inputs (3)

NameTypeDefaultDescription
imagesIMAGE
modeCOMBOGundam5 options: Tiny, Small, Base, Large, Gundam
task_typeCOMBOdocument5 options: document, without layouts, other image, figures in document, general

Outputs (1)

NameTypeDescription
markdown_textSTRING