Module · The outside world
Document Parser
Lesson 20 of 21 · 6 min
Documents arrive constantly — a signed contract, a purchase order, a supplier's price list, a CV attached to an application. Every one of them is content your workflow cannot see, because a file is not text until something reads it.
This node reads it. Point it at a file, get back the words, and everything downstream — a model, a knowledge base, a CRM field — can work with them.
Where the file comes from
| Field | What it holds |
|---|---|
content_source | Source of document content: input (from previous node), base64, url, file_id (from file_uploads table), or azure_blob (direct blob path) One of: input · base64 · url · file_id · azure_blob Defaults to input. |
file_url | URL to download file from (supports {{variables}}) |
file_id | File ID(s) from template variable - can be single ID or array like {{trigger.file_ids}} (takes priority over selected_file_ids) |
selected_file_ids | File IDs selected from dropdown (used as fallback if file_id template is empty) |
max_chars | Maximum characters to extract Defaults to 100000. |
max_pages | Maximum pages to process (for PDFs) Defaults to 50. |
include_metadata | Include file metadata in output Defaults to true. |
content_source
- What it holds
- Source of document content: input (from previous node), base64, url, file_id (from file_uploads table), or azure_blob (direct blob path) One of:
input · base64 · url · file_id · azure_blobDefaults toinput.
file_url
- What it holds
- URL to download file from (supports {{variables}})
file_id
- What it holds
- File ID(s) from template variable - can be single ID or array like {{trigger.file_ids}} (takes priority over selected_file_ids)
selected_file_ids
- What it holds
- File IDs selected from dropdown (used as fallback if file_id template is empty)
max_chars
- What it holds
- Maximum characters to extract Defaults to
100000.
max_pages
- What it holds
- Maximum pages to process (for PDFs) Defaults to
50.
include_metadata
- What it holds
- Include file metadata in output Defaults to
true.
content_source picks the route: a file uploaded through the product, one referenced by id, a public URL, raw base64, or a path in storage. file_id is the common one — it is how a chat attachment or an uploaded document is addressed.
Eleven formats, and images are not among them. Plain text, markdown, CSV, JSON, PDF, and the Office pairs — Word, Excel, PowerPoint, old and new. A photograph of a document is rejected before anything is attempted. That surprises people, because the node has OCR — but OCR here is for PDFs whose pages are images, not for image files.
A worked example
Somebody attaches a file to a chat message. The parser reads it, and the workflow checks that there was anything to read before it does anything else.
Parse, then check you got something
The condition on char_count is the whole safety story.
Scroll for all 5 steps →
The trigger exposes file_ids for whatever was attached, and the parser takes the list. Everything after that hangs on one number.
Branch on char_count, not on whether the node succeeded. A PDF that is one big scanned image, a password-protected file, a document that is genuinely blank — all of these parse without error and produce almost nothing. Two hundred characters is a reasonable floor for “this is a real document”; below it, say so rather than passing an empty string to a model that will invent a summary of it.
OCR, and what it costs
Some PDFs contain text. Others contain pictures of text — anything scanned, faxed, or exported from a photo. The first kind reads instantly and for nothing. The second needs optical character recognition, and this node will do it for you.
| ocr_fallback | What happens |
|---|---|
auto | The default. Extract normally, and if the average characters per page comes out below the threshold, run OCR on it. Handles the mixed case without you deciding in advance. |
always | OCR every page regardless. For a pipeline where you know everything is scanned. |
never | Never OCR. A scanned document returns near-nothing, and your condition catches it. |
auto
- What happens
- The default. Extract normally, and if the average characters per page comes out below the threshold, run OCR on it. Handles the mixed case without you deciding in advance.
always
- What happens
- OCR every page regardless. For a pipeline where you know everything is scanned.
never
- What happens
- Never OCR. A scanned document returns near-nothing, and your condition catches it.
OCR is a call to a vision model, and it is billed to your organisation. It is not a local library — pages are rendered as images and sent to a model, and the usage is tracked against your account like any other model call. So a workflow that quietly handles the occasional scan is fine, and the same workflow pointed at a folder of five hundred scanned invoices is a bill you did not plan. ocr_model and ocr_dpi are the two levers: the cheaper model and 200 dpi are the defaults for a reason.
ocr_min_chars_per_page is what decides whether auto fires. Fifty characters a page is a low bar — a page with a header and a page number clears it. If documents that clearly need OCR are not getting it, raise the threshold rather than switching to always.
What comes back
| Reference | What you get |
|---|---|
{{alias.text}} | The extracted text. What everything downstream actually wants. |
{{alias.char_count}} · {{alias.word_count}} · {{alias.page_count}} | The size of what you got. The first is the one to branch on. |
{{alias.ocr_used}} · {{alias.ocr_pages_processed}} | Whether OCR ran and how many pages went through it. Log these — they are your only visibility into what the node spent. |
{{alias.text}}
- What you get
- The extracted text. What everything downstream actually wants.
{{alias.char_count}} · {{alias.word_count}} · {{alias.page_count}}
- What you get
- The size of what you got. The first is the one to branch on.
{{alias.ocr_used}} · {{alias.ocr_pages_processed}}
- What you get
- Whether OCR ran and how many pages went through it. Log these — they are your only visibility into what the node spent.
What breaks
An unreadable file is a successful run with no text. This is the same failure that has appeared throughout the course, and here it is especially easy to hit, because the reasons are mundane: the PDF is a scan and OCR is off, the file is protected, the format is one of the many not in the list. The node returns, the run is green, and the next node receives an empty string.
In a batch, unsupported files are skipped rather than failing. Hand it five files where two are images and you get three files' worth of text and a successful run. Compare the number of files you sent with what came back if the count matters.
Both limits truncate silently. max_chars and max_pages stop the read at a hundred thousand characters and fifty pages by default. A sixty-page contract is read as far as page fifty, and nothing says the last ten pages exist. If you are parsing long documents, raise them deliberately and check {{alias.page_count}} against what you expected.
Parsed text is not structured data. A table in a PDF comes out as words in reading order, and a two-column layout can interleave. If you need fields rather than prose, the parser gets you the text and a model gets you the fields — this node does not do the second part.
Try it
- Parse an ordinary text-based PDF and read
{{alias.char_count}}and{{alias.ocr_used}}. OCR should be false and the count high. - Now parse a scan of the same document with
ocr_fallbackonnever. The count collapses and nothing errors. - Switch to
autoand run it again. Watchocr_usedturn true and note how much longer it takes — that is the model call. - Try a
.pngand read the error. It names the eleven formats, which is the fastest way to remember them. - Set
max_pagesto 2 on a long document and compare{{alias.page_count}}with the real page count. That is the truncation nobody tells you about.
Next: API Request — the node for everything the other twenty could not do, and the last one in this path.

