Unlimited OCR Image
OCR that never phones home
- image
- text
- image
If you've ever tried to pull text out of a scanned page or a dense table in ComfyUI, you know the state of the art was basically "Florence-2 will do its best, I guess." Florence-2 is great at a quick caption; it is not a document parser. Unlimited OCR Image is the opposite tool: it runs Baidu's Unlimited-OCR model - a full multimodal OCR/document-parsing model - inside your ComfyUI process and hands you clean text as a STRING. "Unlimited" is the model's name, not hype. And the nice part for a community rightly twitchy about mystery custom nodes: the name is also a lie in the good way - it calls no API, needs no key, and ships no server.
How it works
The node takes a ComfyUI IMAGE tensor, writes it out as temporary PNGs, and feeds them to Unlimited-OCR through Hugging Face Transformers. Two details matter for how you use it:
- It's in-process, not a server. The README is explicit: no vLLM, SGLang, FastAPI, or OpenAI-compatible backend. That kills the classic "run a second process" setup pain - one Python environment, one restart.
- Multi-image batches are real. Feed it a batch and it calls the model's
infer_multi, which is how you OCR a whole multi-page scan in one run. Bumpngram_windowup to ~1024 for that; the default 128 is small for multi-page jobs.
The inputs that matter
Most widgets you can leave alone. The ones you'll actually touch:
image- the only wire. Anything that outputs an image tensor.prompt- defaults to<image>document parsing.and adds<image>for you if you forget it. Leave it alone unless your job isn't plain document parsing.image_mode-gundam(default) orbase. In code terms:gundamdownsizes and crops into tiles (better for high-res, dense pages),baseprocesses the whole image at 1024px. Dense documents → keepgundam; a clean single figure →baseis fine.device/dtype-autofor both on a CUDA box: it picks CUDA + bfloat16, and drops to CPU + float32 if there's no GPU. Slow on CPU, but it works.clean_markup- strips the model's<|det|>...<|/det|>layout tags. Keep it on for reading; flip it off only if you need the box coordinates.unload_after_run- frees the cached model and clears CUDA cache when done. Handy if your sampler needs the VRAM back after a rare OCR call.
What you get out
Two outputs: text (STRING, the OCR result) and image (the original image, passed straight through) - which is what lets you chain this into a bigger graph, OCR a page and keep the same image for inpainting. It's also an output node, which mostly matters for API work: with save_results on, it writes ComfyUI/output/FireOCR/fire_ocr_<id>.txt and reports it through the API history so RunPod-style workers can grab it. If you're purely interactive, save_results still writes debug files (result.md, result_with_boxes.jpg, …) - turn it off if you don't want the clutter.
Installing it
The honest gotcha first: this pack is not on the Comfy Registry yet (the README says so), so Manager's search-by-name may come up empty. The reliable path is manual:
cd ComfyUI/custom_nodes
git clone https://github.com/endman100/ComfyUI-UnlimitedOCR.git
pip install -r ComfyUI/custom_nodes/ComfyUI-UnlimitedOCR/requirements.txt
Then restart ComfyUI. The requirements are transformers>=4.57.1, einops, addict, easydict, matplotlib, PyMuPDF, psutil - no pinned torch, since ComfyUI manages that. That transformers>=4.57.1 floor is your one real dependency risk: if another node pins an older transformers, the shared environment can silently break one of them. Worth knowing before you stack this onto a node zoo.
The model itself is the heavy part - a safetensors weights download plus custom modeling code. Put it at:
ComfyUI/models/Unlimited-OCR/baidu-Unlimited-OCR
The node finds that folder automatically; otherwise it checks extra_model_paths.yaml keys (unlimited_ocr, llm, LLM), then falls back to pulling baidu/Unlimited-OCR from Hugging Face on first run. It loads via trust_remote_code=True - the node only executes code from whatever path you select in model, but that's still "runs the repo's Python," so it's the one field worth reading before you point it at something random.
Common issues
- "Model not found" - it's not at one of the search locations above. Download it to
models/Unlimited-OCR/baidu-Unlimited-OCRor set the full local path inmodel. - Import errors at startup - almost always the
transformersfloor. Update transformers, then restart. - Slow first run - the first inference downloads and loads the model; it stays cached per (model, device, dtype) after that.
OCR in ComfyUI has historically been a desert - the community answer was Florence-2 for short text and a separate external tool for documents. This is the first serious local-document-parser option that drops straight into a graph. For dense pages and tables, it earns its keep; for a caption or a two-word label, keep Florence-2 and save the VRAM.
Inputs (12)
| Name | Type | Default | Description |
|---|---|---|---|
| image | IMAGE | — | |
| model | STRING | baidu/Unlimited-OCR | — |
| prompt | STRING | <image>document parsing. | — |
| image_mode | COMBO | gundam | 2 options: gundam, base |
| device | COMBO | auto | 4 options: auto, cuda, cuda:0, cpu |
| dtype | COMBO | auto | 4 options: auto, bfloat16, float16, float32 |
| max_tokens | INT | 81921–32768 | — |
| ngram_size | INT | 351–256 | — |
| ngram_window | INT | 1281–4096 | — |
| clean_markup | BOOLEAN | true | — |
| save_results | BOOLEAN | true | — |
| unload_after_run | BOOLEAN | false | — |
Outputs (2)
| Name | Type | Description |
|---|---|---|
| text | STRING | — |
| image | IMAGE | — |