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 I’m still learning, but I’d really appreciate any guidance or example workflows!
@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:
Use a Read/Write Files from Disk node to save your PDF binary to a temporary path like /tmp/input.pdf.
Use the Execute Command node to run: pdftoppm -png /tmp/input.pdf /tmp/output
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
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:
Is there a recommended way in n8n to convert PDF pages to images (PNG/JPG) within the workflow?
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
For the OCR step specifically, you can skip the pdftoppm + Docker extension setup and use the SealDoc node instead. It runs ocrmypdf + Tesseract internally on a self-hosted SealDoc instance, so nothing leaves your infrastructure.
Node config in n8n:
Resource: Job
Operation: Create
Enable: Run OCR (toggle on)
OCR Languages: eng (or eng+deu, nld+fra, etc.)
The node outputs the extracted text, which you then wire straight into your Ollama node for summarisation or structuring. SealDoc handles the image conversion and Tesseract pass so you don’t need Execute Command nodes or a custom Docker image.
Hey, that sounds interesting. However, as I can see, it becomes paid once you reach a certain size. Also, I can’t access the website because after entering my company information, I end up stuck in an endless loop.
Hey Leon, the endless loop was a real bug. It hit a few people today and we pushed a fix just now. Hard-refresh or clear site data for app.sealdoc.eu if it still shows the old page.
On pricing: the free tier covers 50 documents/month with full OCR and text extraction, which should be enough to evaluate whether it fits your workflow. Paid plans kick in if you need higher volume or retention beyond 24h.
Thank you very much for all the ideas and suggestions so far. Unfortunately, I still have the same issue and I’m continuing to look for a solution.
My goal is to extract text from scanned PDF files that do not contain a text layer. If the files are regular image files instead of PDFs, I can simply use the Ollama “Analyze Image” node and get quite usable results. However, this obviously does not work directly with PDF files.
Is there really no way to process scanned PDFs directly inside an n8n workflow and extract the text from them?
The whole setup should continue to run fully locally and preferably remain completely free of charge.
I’m still happy to receive further suggestions — workflow examples or snippets would also be greatly appreciated
I’m not sure if you’ve already been given this answer, please let me know if you have since the thread is getting too long.
for scanned PDFs, Extract from PDF won’t work because there’s no text layer, we need to convert each page to an image and apply OCR. try installing poppler-utils in the container, use Execute Command to generate PNGs and then send those images to Ollama.
The docs show that n8n has an operation to extract content from PDF, but that’s extraction of existing content in the file, not OCR of scanned images.
The docs explain that if you need to run commands/binaries inside n8n Docker, you should create an image based on the official image and install the necessary packages.
The pdftoppm docs say it converts PDF files to images, generating one image per page.
Somehow every time I try to add something new to the workflow that might solve my main OCR problem, I end up creating even more problems first
I already installed both pdftoppm and ImageMagick inside my Docker container and tried to solve the scanned PDF issue with them. But now I’m stuck at the Read/Write Files from Disk node because I always get the following error:
The file "/temp-files/input" is not writable.
I already searched the forum and Google for this specific error but couldn’t really find a working solution, so I thought I’d ask here again.
What I’m trying to achieve is actually pretty simple:
I just want to convert a scanned PDF into image files inside the workflow using either pdftoppm or ImageMagick, so I can then send those images to the Ollama node for OCR recognition.
So far I haven’t found another fully local and free solution that works reliably for scanned PDFs.
I already tested Tesseract as well, but honestly the OCR quality was pretty bad in my case.
So if anyone has an idea what could be causing the writable error or how to properly handle temporary files in Docker/n8n, I’d really appreciate the help ^^
The /temp-files/input path is the issue - that directory doesn’t exist or isn’t writable in the n8n Docker container by default. Switch to /tmp instead, which is always writable in containers: use /tmp/page-%03d.png as your output path in the Execute Command node.
Also, for the Read/Write Files node to access /tmp, make sure the environment variable N8N_RESTRICT_FILE_ACCESS_TO is set to include /tmp in your Docker config, or isn’t set at all (it restricts file access if defined). If you’re on a recent n8n version, check that the path in the Read/Write Files node matches exactly what pdftoppm or ImageMagick outputs - the %03d pattern generates page-001.png, page-002.png, etc., so you’d read them back by looping through that pattern.
You can use the Execute Command node in n8n to run Tesseract OCR locally. Just install Tesseract and Poppler on your n8n host, then chain it as: Read Binary File → Execute Command (OCR) → HTTP Request to Ollama. For multi-page PDFs, OCRmyPDF in a Docker sidecar is cleaner, and you can call it via HTTP Request node without touching the n8n host. Everything stays 100% local.