Tools,

Dify OCR, tested on a scanned PDF

0

of 1,955 words indexed, status completed

Get the fixes

Completed, with zero words

10 segments, each one picture link

0 search hits for its words

I saved this as upload.sh, then sent the scan:

curl -s -X POST "$DIFY/v1/datasets/$DATASET/document/create-by-file" \
  -H "Authorization: Bearer $DIFY_KEY" \
  -F 'data={"indexing_technique":"economy","process_rule":{"mode":"automatic"}};type=text/plain' \
  -F "file=@$1"

Then I read what Dify stored:

curl -s "$DIFY/v1/datasets/$DATASET/documents/$1/segments?limit=100" \
  -H "Authorization: Bearer $DIFY_KEY" | jq -r '.data[].content'

Every segment was one line like this:

![image](http://127.0.0.1:5001/files/a656f067-1761-4ed7-ba5f-f2c78c6b5d94/file-preview)

Dify said completed and available. Each page became a link to its picture, with no text, so search found nothing.

Dify reads the text layer only

Dify 1.19.0 sends every PDF to one reader, PdfExtractor. It takes the text layer with pypdfium2 and adds a link for each picture. A scan has no text layer.

The Unstructured setting does not help

Dify has a second ETL setting, for an Unstructured server. I added these lines to .env and restarted:

ETL_TYPE=Unstructured
UNSTRUCTURED_API_URL=http://unstructured:8000/general/v0/general

The scan still gave 0 words and no error, though no server ran at that URL. In 1.19.0 the code sends .pdf files to the same reader for both ETL types.

Scans hit the 15 MB limit

Scanned pages are big. Three copies of the scan, 30 pages and 19.5 MB, got HTTP 413 with an empty message:

{"code":"file_too_large","message":"","status":413}

Add UPLOAD_FILE_SIZE_LIMIT=50 to .env and restart. The 30 pages then went in, still with 0 words.

Fix: OCR the PDF before upload

OCRmyPDF adds a text layer and keeps the pages as they look. Then send the new file:

ocrmypdf --skip-text --jobs 2 scan.pdf scan-ocr.pdf
sh upload.sh scan-ocr.pdf

1,873 of 1,955 true words found

3 search hits for the same words

It took 23 seconds on the Mac. The Doc Extractor node found 1,862 words in the same file.

Five uploads, one scan

10 scanned pages, 1,955 true words
Setup Words found Search hits
Upload as is 0 0
ETL_TYPE=Unstructured 0 0
30 pages, limit raised 0 0
OCRmyPDF first 1,873 3
Our OCR Actor 1,874 2

The search was three words from the scan, Hatton yacht lifeboat, in an economy index. Dify ran in Docker on a Mac.

No OCR install? Use the Actor

Our OCR Actor runs in the cloud. It takes a PDF URL and returns Markdown, and the same upload command sends that to Dify:

curl -s -X POST "https://api.apify.com/v2/acts/brasspage~pdf-ocr-to-markdown/run-sync-get-dataset-items" \
  -H "Authorization: Bearer $APIFY_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"documentUrls": ["https://api.apify.com/v2/key-value-stores/sTnmNrGoSsi7tLQvs/records/dify-scan-10-pages.pdf"]}' \
  | jq -r '.[].markdown' > scan.md
sh upload.sh scan.md

It found 1,874 words, one more than OCRmyPDF, which is free. The Markdown file is 11 KB, far under the upload limit. It costs $0.006 a page.

How I tested it
  • Scan: the 10-page PDF of OCR in n8n, the first 10 of 55 proofread Wikisource book scans, with no text layer. 1,955 true words.
  • Typed page: a 13-word cover sheet, put in front of the scan. Big file: the same 10 pages 3 times.
  • Score: true words found in order, with the scorer of the tessdata test, after the picture links were removed.
  • Dify 1.19.0 on arm64, the default Docker Compose. Each container had 1 CPU, the api and worker 2. A new knowledge base for each setup, economy index, automatic chunks.
  • The login API wants the password in base64. Plain text gets HTTP 401, Invalid encrypted data.
  • The code blocks above are the files that ran. OCRmyPDF 17.13.0 with Tesseract 5.5.4. The Actor: one real run.
What I did not test
  • OCR plugins from the Dify Marketplace. They need an API key or another server.
  • Vision models, the high quality index with embeddings, and the knowledge pipeline.
  • Dify Cloud, other languages, tables, and handwriting.
Sources

Two ways to skip the work

Run it yourself. Our Apify Actor turns scanned PDFs into Markdown, tables included.

Try the Actor

Or send us the scan. Tack, our AI, does the job for $29, up to 50 pages. First page free.

Get one page free

Questions people ask

Does Dify do OCR on scanned PDFs?

Not in the knowledge base or the Doc Extractor node. Dify 1.19.0 reads the PDF text layer only. My 10-page scan gave 0 of 1,955 words, with status completed.

Why is my Dify knowledge base empty after a PDF upload?

The PDF is a scan with no text layer. Dify stores one picture link for each page. Run ocrmypdf --skip-text first, or upload Markdown from an OCR tool.

Does ETL_TYPE=Unstructured add OCR for PDFs in Dify?

No. In 1.19.0, PDF files go to the same text layer reader for both ETL types. My scan gave 0 words with it on.