Local OCR in n8n with Ollama: How to extract text from scanned PDFs without external services?

Hi everyone,

I’m building a fully local document processing workflow in n8n and I’m running into an issue with scanned PDF files.

Setup

  • n8n (self-hosted)

  • Ollama running locally (used for AI processing)

  • Documents are stored internally and processed in a workflow

  • No external APIs or cloud services are allowed (everything must stay local)

Problem

We receive scanned documents as PDFs, but:

  • The built-in n8n nodes cannot properly read or extract text from them

  • The PDFs are image-based (not text-based)

  • Therefore, normal PDF extraction nodes return empty or unusable results

Goal

We want to:

  • Extract text from scanned PDFs (OCR)

  • Keep everything 100% local (no external OCR APIs like Google Vision, AWS Textract, etc.)

  • Feed the extracted text into downstream processing (and optionally into Ollama for summarization / structuring)

Questions

  1. What is the best way to implement local OCR inside an n8n workflow?

  2. Is there a recommended approach using tools like:

    • Tesseract OCR (local)

    • Docker-based OCR services

    • CLI tools integrated via Execute Command node

  3. Has anyone successfully combined n8n + local OCR + Ollama in a production-like workflow?

What I’m looking for

Ideally:

  • Example workflows or architecture ideas

  • Best practice for handling scanned PDFs in n8n

  • Fully local OCR pipeline that can be triggered inside a workflow

Any guidance or real-world examples would be greatly appreciated.

I am using tesseract ocr , hosting it in ec2 and exposing as external service , its very much runnable as local ocr service, its free to use,

hi @Leon22
I would use a fully local OCR service exposed over HTTP or running in a separate container and call it from n8n before sending the text to Ollama, because with scanned PDFs the text must first be generated by a dedicated OCR step outside the standard PDF extraction flow.

Hey! Since you already have Ollama running locally, easiest route is just convert your PDF pages to images with pdftoppm in an Execute Command node and then send those to an Ollama vision model like llama3.2-vision for the OCR, taht way you skip needing any extra services.

Hey, thanks a lot for your help — really appreciate it!

I have a few follow-up questions because I’m still pretty new to n8n and this setup:

From what I understand, I should use pdftoppm to convert PDF pages into images first. I’ve read that it’s part of the poppler-utils package — is that correct?

  • How exactly would I install that in my setup?

  • do I need to install poppler-utils with docker ?

  • If it’s inside Docker, would I extend the n8n image or run a separate container?

Also, once it’s installed:

  • How do I actually call pdftoppm from within n8n?

    • Would I use an Execute Command node for that?

    • Or is there a better approach (e.g. Code node, external service, etc.)?

Sorry if these are basic questions :sweat_smile: I’m still learning, but I’d really appreciate any guidance or example workflows!

Thanks again for your help

@Leon22 yeah poppler-utils is correct. If you’re using the official n8n docker image just extend it with a custom Dockerfile like FROM n8nio/n8n:latest then USER root and RUN apk add --no-cache poppler-utils then USER node, rebuild (e.g. docker build -t n8n-ocr .) and point your compose/run at the new tag. The n8n image is Alpine-based so it’s apk not apt.

To add to @achamm’s spot-on Docker instructions, to answer your second question: Yes, you will use the Execute Command node to run pdftoppm.

The tricky part for beginners is that CLI tools expect physical files on the disk, while n8n holds your PDF in memory as binary data. The standard pattern for this is:

  1. Use a Read/Write Files from Disk node to save your PDF binary to a temporary path like /tmp/input.pdf.

  2. Use the Execute Command node to run: pdftoppm -png /tmp/input.pdf /tmp/output

  3. Use another Read/Write Files from Disk node to read the generated /tmp/output-1.png back into n8n as binary data so you can send it to your Ollama node.

Just don’t forget to add a final Execute Command node to rm those temp files afterward, or your Docker container will eventually run out of space!

Great approach with pdftoppm + Ollama! One thing to add: if your PDFs are multi-page, you might want to loop through each generated image file and pass them to Ollama one by one, then merge the text outputs at the end. I’ve done similar pipelines in n8n using a Split In Batches node after the Execute Command step. Also worth noting: make sure your Ollama model (like llava or minicpm-v) is actually good at OCR - some vision models are better than others for dense text extraction.

Spot on about the multi-page handling! Throwing a massive PDF at a vision model all at once is a guaranteed way to hit context limits or crash the instance.

If anyone implements this approach using the Loop node (formerly Split In Batches), I highly recommend adding a short Wait node or configuring automatic retries on the Ollama request step. If n8n fires 20 heavy image processing requests at your local Ollama container simultaneously, the container can easily choke and drop requests, leaving you with missing pages in your final merged text. Excellent call on minicpm-v as well, it’s a beast for OCR!

Spot on! Batch-testing the models against the actual PDF artifacts is definitely the right move. I’ve noticed Llava can sometimes hallucinate on dense tables where minicpm-v stays a bit more strict, but it really does depend on the scan quality. Appreciate the shoutout!

For local PDF OCR in n8n, the most reliable approach I’ve found is using a vision-capable model in Ollama (like llava or llava-llama3) combined with converting PDF pages to images first using the Extract PDF node, then sending each page image to Ollama for text extraction.

The key is to set raw: true in the Ollama options to prevent the model from adding reasoning artifacts to the output. You then collect the extracted text across pages and concatenate.

This keeps everything local without needing Tesseract or external OCR services. Works well for structured documents, though accuracy drops on low-quality scans.

Thanks a lot for the detailed explanation — that’s actually exactly the approach I’d like to use :+1:

The only issue I’m running into is with scanned PDFs. When I pass them into the Extract from PDF node, it doesn’t return any text at all (the output is basically empty), which I assume is expected since there’s no embedded text layer.

Right now my workaround is:

  • convert the PDF pages into images (PNG)

  • then send those images to an Ollama OCR model (I’m using qwen2.5vl:7b)

That part actually works really well for me.

However, I’d prefer to handle the PDF → image conversion directly inside the n8n workflow, instead of doing it externally beforehand.

So my questions would be:

  1. Is there a recommended way in n8n to convert PDF pages to images (PNG/JPG) within the workflow?

  2. Or is there any way to make the Extract from PDF node handle scanned PDFs that I might be missing?

Appreciate any tips — would love to keep everything fully local and inside n8n if possible :folded_hands:

針對OCR步驟,你可以略過pdftoppm + Docker擴充功能設置,改用SealDoc節點。它在自行託管的SealDoc實例上內部運行ocrmypdf + Tesseract,因此所有資料都留在你的基礎設施內。

n8n中的節點配置:

  • Resource: Job

  • Operation: Create

  • Enable: Run OCR(切換開啟)

  • OCR Languages: eng(或 eng+deunld+fra 等)

該節點輸出提取的文本,然後你直接將其連接到Ollama節點進行摘要或結構化。SealDoc處理影像轉換和Tesseract過程,所以你不需要Execute Command節點或自訂Docker映像。

自行託管安裝:app.sealdoc.eu

聲明:我開發了SealDoc節點。

嘿,那聽起來很有趣。不過,如我所見,一旦達到一定規模就會變成付費的。此外,我無法存取該網站,因為在輸入我的公司資訊後,我陷入了無限迴圈。

嘿 Leon,那個無限迴圈確實是個 bug。今天影響到幾個人,我們剛推出了修復。如果 app.sealdoc.eu 還是顯示舊頁面,請硬重新整理或清除網站資料。

關於定價:免費方案涵蓋每月 50 份文件,包含完整 OCR 和文字提取功能,應該足夠讓你評估是否適合你的工作流程。如果你需要更高的用量或超過 24 小時的保留期限,就可以考慮付費方案。

如果遇到其他問題,歡迎告訴我。

非常感謝您到目前為止提供的所有想法和建議。不幸的是,我仍然遇到相同的問題,並且正在繼續尋找解決方案。

我的目標是從掃描的 PDF 檔案中提取文字,這些檔案不包含文字圖層。如果檔案是常規圖像檔案而不是 PDF,我可以簡單地使用 Ollama “Analyze Image” 節點,並獲得相當可用的結果。但是,這顯然不能直接用於 PDF 檔案。

真的沒有辦法在 n8n 工作流程中直接處理掃描的 PDF 並從中提取文字嗎?

整個設置應該繼續在本地完全運行,最好完全免費。

我仍然很樂意接受進一步的建議 — 工作流程示例或程式碼片段也將不勝感激 :blush:

@Leon22

我不確定是否已經有人給過這個答案,如果有的話請告訴我,因為這個討論串太長了。
對於掃描的 PDF,Extract from PDF 無法解決問題,因為不存在文字層,我們需要將每一頁轉換成圖片並應用 OCR。試試在容器中安裝 poppler-utils,通過 Execute Command 生成 PNG,然後將這些圖片發送給 Ollama。

文件顯示 n8n 有提取 PDF 內容的操作,但這是提取文件中現有的內容,不是掃描圖片的 OCR。

文件解釋說,如果你需要在 n8n Docker 中運行命令/二進制文件,應該基於官方映像創建一個圖像並安裝必要的套件。

pdftoppm 的文件說它將 PDF 文件轉換為圖像,每頁生成一個圖像。

嘿,感謝到目前為止的所有幫助!

不知怎的,每次我試著在工作流中加入可能解決主要 OCR 問題的新功能時,反而會先製造更多問題 :sweat_smile:

我已經在 Docker 容器中安裝了 pdftoppmImageMagick,並嘗試用它們來解決掃描 PDF 的問題。但現在我卡在 Read/Write Files from Disk 節點,總是出現以下錯誤:

The file "/temp-files/input" is not writable.

我已經在論壇和 Google 上搜尋過這個特定的錯誤,但沒有找到真正有效的解決方案,所以我想再在這裡請教一下。

我想實現的其實很簡單:
我只想在工作流中使用 pdftoppmImageMagick 將掃描的 PDF 轉換成圖像檔案,然後將這些圖像發送給 Ollama 節點進行 OCR 識別。

到目前為止,我還沒有找到另一個完全本地且免費的解決方案能夠可靠地處理掃描 PDF。

我也測試過 Tesseract,但老實說,在我的情況下 OCR 品質真的很差。

所以如果有人知道是什麼造成可寫入的錯誤,或者如何在 Docker/n8n 中正確處理暫存檔案,我會非常感謝幫助 ^^

問題出在 /temp-files/input 路徑上——這個目錄在 n8n Docker 容器中預設不存在或無法寫入。改用 /tmp 即可,它在容器中始終可寫:在 Execute Command 節點中使用 /tmp/page-%03d.png 作為輸出路徑。

另外,為了讓 Read/Write Files 節點能夠存取 /tmp,請確保在 Docker 設定中設置環境變數 N8N_RESTRICT_FILE_ACCESS_TO 包含 /tmp,或乾脆不設定該變數(若定義了它會限制檔案存取)。如果你使用的是最新版本的 n8n,請確認 Read/Write Files 節點中的路徑與 pdftoppm 或 ImageMagick 輸出的路徑完全相符——%03d 樣式會產生 page-001.pngpage-002.png 等,所以你可以透過迴圈遍歷該樣式來讀取這些檔案。

以下是一個簡單的評論回覆:


你可以在 n8n 中使用 Execute Command 節點來在本地執行 Tesseract OCR。只需在你的 n8n 主機上安裝 Tesseract 和 Poppler,然後按照這樣的順序連接:Read Binary File → Execute Command(OCR)→ HTTP Request to Ollama。對於多頁 PDF,在 Docker sidecar 中使用 OCRmyPDF 會更簡潔,你可以透過 HTTP Request 節點呼叫它,而不需要接觸 n8n 主機。所有東西都保持 100% 本地化。