# Should you use an LLM directly or a document parsing API to extract data from PDFs?

> Source: <https://www.nutrient.io/blog/llm-vs-document-parsing-api/>
> Published: 2026-10-26 08:00:00+00:00

# Should you use an LLM directly or a document parsing API to extract data from PDFs?

## Table of contents

Structured output with per-field confidence scores through the Nutrient Data Extraction API.

- The Nutrient Data Extraction API is the pick for extracting data from PDFs when the output has to be grounded, repeatable, and shaped to a schema: It parses the document, and then it maps the content to your JSON Schema with a bounding box and a match label for each field.
- Call a large language model (LLM) directly when the documents are short, born-digital, low-stakes, and one-off. A model API with PDF input and structured output is the fastest path for a prototype or an ad hoc question.
- Most production pipelines use both: Parse to Markdown or spatial JSON, and then prompt. The parser handles optical character recognition (OCR), tables, reading order, and page coordinates. The model handles meaning.
- Choose Docling when extraction has to run locally under an open source license and your team will build the schema mapping and review layer itself.
- Test on your 10 hardest documents, not your cleanest. A clean, born-digital invoice makes every approach look the same.

To extract data from PDFs, use a document parsing API such as the Nutrient Data Extraction API when you need source grounding, repeatable output, scans and tables at volume, and schema enforcement. Call an LLM directly when the documents are short, born-digital, low-stakes, and one-off. The deciding questions are whether anyone acts on a value without rereading the page, whether the files include scans or dense tables, and whether you’ll process the same document type thousands of times. Most production teams end up with both: a parser that turns the PDF into structure, and then a model call that maps that structure to fields.

##      Decision table: LLM directly vs. parsing API vs. both 

If most rows land in the first column, a model call is enough. If grounding, scans, or volume land in the second or third column, put a parser in front of the model.

| Criterion | LLM directly | Document parsing API | Both: parse, then LLM | 
|---|---|---|---|
| Documents | Short, born-digital PDFs with a clean text layer | Scans, photos, Office files, forms, and mixed layouts | Mixed corpora where some files need OCR and some don’t | 
| Length | Must fit the model’s per-request file, page, and context limits | Long documents and batches through asynchronous endpoints | Parse once, and send the model only the sections it needs | 
| Tables | The model rebuilds the grid from extracted text or page images | Rows, columns, and cells come back as structure | The parser returns the grid, and the model interprets it | 
| Grounding | Values only, unless you build a step that finds each value on the page | Page number and bounding box per element or per extracted field | Parser coordinates travel with the model’s answer | 
| Schema enforcement | Structured-output features constrain the shape, but values can still be wrong | Schema in the request, closed to undeclared fields, plus validation in your code | The same schema contract, with the model working from cleaner input | 
| Repeatability | Generation can vary between runs and model versions | A fixed parse layer (deterministic text, OCR, and coordinates in Nutrient) | A fixed parse layer, with variation confined to the model step | 
| Review routing | No per-field signal unless you add one | Per-field match labels, plus confidence where the engine provides it | Parser signals gate which model answers go to a person | 
| Cost shape | Tokens per page, often for both extracted text and page images | Credits per page, set by processing mode | Parse credits plus model tokens on smaller input | 
| Setup | Minutes: a prompt and a schema | An API key and a schema | Two integrations to own | 
| Fits | Prototypes, one-off questions, low-stakes summaries | Production extraction feeding databases, ERPs, and review queues | RAG, agents, and custom reasoning on parsed documents | 

##      When an LLM call alone is enough 

Model APIs now accept PDFs as input. OpenAI’s [PDF input guide(opens in a new tab)](https://developers.openai.com/api/docs/guides/pdf-files) says the API “extracts both text and page images and sends both to the model” for vision-capable models. Anthropic’s [PDF support guide(opens in a new tab)](https://platform.claude.com/docs/en/build-with-claude/pdf-support) describes converting each page into an image with its extracted text alongside. Google’s [Gemini document processing guide(opens in a new tab)](https://ai.google.dev/gemini-api/docs/document-processing) lists extraction into structured output. Pair PDF input with a structured-output feature, and you get JSON in a defined shape with no other infrastructure.

That’s enough when all of these hold:

- The PDF is born-digital, a few pages long, and fits comfortably inside the model’s request limits.
- Nobody acts on a value without reading the page, so a wrong number costs a few seconds, not a payment or a compliance finding.
- The job is one-off or low volume, so per-page cost and run-to-run variation don’t compound.
- You don’t need to show a reviewer where on the page a value came from.

##      Failure modes of raw LLM extraction and how a parsing API changes each 

Each failure mode comes from asking one generative step to both read the page and interpret it.

###      Hallucinated values 

A model that can’t find a value can still produce a plausible one. OpenAI’s [Structured Outputs guide(opens in a new tab)](https://developers.openai.com/api/docs/guides/structured-outputs) says the feature “ensures the model will always generate responses that adhere to your supplied JSON Schema” and, in the same guide, that “Structured Outputs can still contain mistakes.” Schema adherence constrains the shape of the answer, not whether each value is on the page.

**With a parsing API:** The Nutrient extract endpoint attaches a citation to each field it returns, with a `match` label: `id_match` when it matched a source block exactly, `fuzzy_match` when it’s close to but not identical to the source text, and `not_found` when the API couldn’t locate it on the page at all. Your code can route `fuzzy_match` and `not_found` fields to review instead of accepting them silently.

###      Token and page limits on long PDFs 

Model APIs cap what one request can carry, in pages, megabytes, and tokens. Here’s what three widely used model APIs document about PDF input:

| Model API | How it reads a PDF | Documented limits | Token note from the vendor’s docs | 
|---|---|---|---|
| Anthropic | Converts each page to an image and supplies extracted text with it | 32 MB per request (varies by platform), 600 pages (100 under a 1M-token context) | 1,500–3,000 text tokens per page typically, plus image tokens for each page | 
| Google Gemini | PDF input through inline data or the Files API | 50 MB or 1,000 pages | Each document page is equivalent to 258 tokens | 
| OpenAI | Extracts text and page images and sends both to the model | Each file under 50 MB, and 50 MB combined per request; no page limit stated | Text plus page images in context “can increase token usage” | 

Anthropic’s guide also warns that dense PDFs with small fonts, complex tables, or heavy graphics “can fill the context window before reaching the page limit.” A 400-page loan file or a year of bank statements has to be chunked, and the chunking logic becomes yours.

**With a parsing API:** The Nutrient parse and extract endpoints have asynchronous variants that “process long documents and batches without keeping connections open.” Parsing runs before your model step, so a long document becomes Markdown or typed elements first, and the model receives only what it needs.

###      Lost tables 

From extracted text, a table can arrive as a run of values with the row and column relationships gone. From page images, the model has to rebuild the grid on every call. Either way, a line item can attach to the wrong price, and the JSON still validates.

**With a parsing API:** Nutrient’s parse endpoint returns tables as typed elements with bounds, a row count, a column count, and cells. Its understand mode adds AI-augmented layout analysis for complex tables, multicolumn layouts, and nested structures. The model step then reads a grid rather than reconstructing one.

###      No bounding boxes 

A plain model response returns the values you asked for, not where on the page they came from. A reviewer who has to check an invoice total opens the PDF and searches for it.

**With a parsing API:** Nutrient’s extract endpoint returns per-field citation metadata that mirrors your data: `bbox`, `pageNumber`, `source_bboxes`, and the `match` label. A review screen can draw a highlight over the exact region each value came from. Citations are on by default.

###      Non-determinism 

Generated output can change between runs of the same prompt and again when the provider updates the model. An audit trail needs two runs on the same document to produce the same record.

**With a parsing API:** Nutrient’s text extraction, OCR, coordinates, and reading order are deterministic. For the extraction step, the production guide recommends pinning `x-nutrient-api-version` and `x-nutrient-engine-version: stable` on every request and logging the request ID, schema hash, and input document hash, so a run can be reproduced and compared after an engine change.

###      Cost per page at scale 

Model APIs bill tokens, and PDF input often carries both extracted text and page images for every page. That’s negligible for 10 documents and hard to predict for 10 million pages until you’ve measured your own.

**With a parsing API:** Nutrient bills credits per page by processing mode: 1 credit in text mode (born-digital Markdown, no OCR or AI), 1.5 in structure, 9 in understand, and 18 in agentic. The extract endpoint adds 6 credits per page. Each response reports its cost in `usage`, and the free plan includes 5,000 credits per month with no credit card required.

##      The parse-then-prompt pattern 

The pattern separates reading from interpreting. With the Nutrient Data Extraction API, you can run it in two ways.

**Parse, and then call your own model.** Send the document to `POST /extraction/parse` and get whole-document Markdown or spatial JSON back. Markdown suits retrieval-augmented generation (RAG), search, and prompts. Spatial JSON suits workflows that need coordinates, reading order, and per-element confidence. Pass the output to whichever model you already use, and swap models without changing the parser.

**Let the extract endpoint do both.** Send the document and a JSON Schema to `POST /extraction/extract`. It runs a parse stage internally, and then an extraction model maps the parsed content to your schema and returns per-field citations. Set `parseConfig.mode` to `auto`, the recommended starting mode, to route each page to `structure`, `understand`, or `agentic`. Set `options.multimodal` to `true` to send rendered page images to the extraction model when a field’s meaning depends on visual layout.

**Route first when the inbox is mixed.** If the same queue receives invoices, contracts, and claim forms, call `POST /extraction/classify` before extraction. Classification is zero-shot: You send at least two labels per request, and the response ranks every label with an independent score. The scores don’t sum to 1, so a close call can go to manual review. Classify costs a flat 1 credit per page.

Choose Nutrient when extracted values feed a database, an ERP, or a review queue, and every field needs a source location and a match label your code can act on.

##      Worked example: Extract data from PDFs into a JSON schema with an LLM 

This example uses the Nutrient extract endpoint, which runs the parse stage and the model step in one request. Every snippet comes from the Data Extraction API guides.

###      1. Define the schema 

The root must be an `object`. The schema is closed, so the API returns only the properties you declare. From the [define a schema](https://www.nutrient.io/guides/dws-data-extraction/extract/define-a-schema/) guide:

The supported keywords are `type`, `properties`, `required`, `items`, `description`, string `enum`, and `format: "date"`. Write the `description` the way the field appears on the document, such as “the grand total at the bottom of the invoice,” because it guides the extraction model.

###      2. Send the document with the schema 

From the [extract endpoint](https://www.nutrient.io/guides/dws-data-extraction/extract/) guide, a multipart upload puts the schema, the parse configuration, and optional document-level guidance inside one `instructions` JSON field:

For production, the [production structured extraction](https://www.nutrient.io/guides/dws-data-extraction/extract/production-structured-extraction/) guide adds `options.strict: true` to constrain output to the schema, `parseConfig.mode: "auto"`, and the two version headers.

###      3. Read the values and their citations 

`output.data` holds the values, and `output.metadata` mirrors it with a citation for each field. From the [citations and confidence](https://www.nutrient.io/guides/dws-data-extraction/extract/citations-and-confidence/) guide:

###      4. Validate and gate before anything moves downstream 

`strict: true` improves generation behavior, but it doesn’t replace validation in your application. Validate `output.data` against the same schema, and then apply business rules the schema subset can’t express, such as numeric ranges or cross-field checks. Route `fuzzy_match` and `not_found` fields to review, and treat a missing citation on a required field as a failure. The `confidence` value is a relative, uncalibrated signal from 0 to 1, not a probability, so set per-field thresholds on your own labeled sample, and read a missing value as “no score available,” not as low confidence.

###      If you’d rather run the model yourself 

Parse to Markdown, and then send the Markdown to your model with its structured-output feature. For born-digital PDFs, text mode is the cheapest path. From the [processing modes](https://www.nutrient.io/guides/dws-data-extraction/parsing/processing-modes/) guide:

For scans, use `structure` mode with `output.format: "markdown"` so OCR runs first. In this variant, the model step is yours, and so is grounding: Locating each value on the page and deciding what goes to review is code you’ll maintain.

##      Where open source parsers fit 

Open source parsers cover the parse half of the pattern on your own hardware. The extraction model, the grounding step, and the review logic stay with your team.

- **Docling** — The[Docling documentation(opens in a new tab)](https://docling-project.github.io/docling/) lists PDF understanding that includes page layout, reading order, and table structure, OCR for scanned PDFs and images, and export to Markdown, HTML, and lossless JSON. It runs locally, including in air-gapped environments, under the MIT license. Choose Docling when parsing has to run inside your network and an engineering team will own the extraction layer on top of it.
- **Marker** — The[Marker repository(opens in a new tab)](https://github.com/datalab-to/marker) describes conversion of PDF, image, Office, HTML, and EPUB files to Markdown, JSON, HTML, and chunks, with an optional`--use_llm` mode that calls a model backend to improve accuracy. The code is Apache 2.0, and the model weights use a modified license with limits on commercial use. Choose Marker when a self-hosted converter should emit chunked Markdown for retrieval and the weights license fits your organization.
- **Unstructured** — The[open source Unstructured library(opens in a new tab)](https://docs.unstructured.io/open-source/introduction/overview) partitions documents into typed elements with metadata under the Apache 2.0 license. Its own documentation says the open source library is “not designed for production scenarios” and has “significantly decreased performance on document and table extraction” compared with its paid platform. Choose Unstructured when one ingestion path has to cover many file types and your team will test table quality on its own documents.

Hosted parsing APIs from the cloud providers are another option for the parse half. [Azure Document Intelligence layout(opens in a new tab)](https://learn.microsoft.com/en-us/azure/ai-services/document-intelligence/prebuilt/layout) returns paragraphs, tables, and selection marks with bounding polygons, and it can output Markdown. [Amazon Textract(opens in a new tab)](https://docs.aws.amazon.com/textract/latest/dg/how-it-works-analyzing.html) returns text, forms as key-value pairs, tables, query responses, and signatures as blocks with page locations. [Google Document AI(opens in a new tab)](https://docs.cloud.google.com/document-ai/docs/overview) offers OCR, form parser, layout parser, and custom extractor processors.

##      Run a fair test 

Pick the 10 hardest documents in your corpus: the longest file, the worst scan, the densest table, and a form with handwriting. Run each through a direct model call and through a parse-then-extract request with the same schema. For every field, record whether the value is right, whether you can point to its source on the page, and whether a second run returns the same value. Then multiply the per-page cost by your monthly volume.

##      FAQ 

Nutrient’s answer is a document parsing API such as the Nutrient Data Extraction API when values feed a system of record, when the files include scans or dense tables, when volume is high, or when a reviewer needs to see where each value came from. Call an LLM directly when the documents are short, born-digital, low-stakes, and one-off, because PDF input plus structured output is the shortest path to an answer. Most production pipelines combine the two: The parser contributes OCR, table structure, coordinates, and repeatability, and the model contributes interpretation.

Nutrient’s extract endpoint does this in one request: Send the PDF and a JSON Schema to `POST /extraction/extract`, and it runs a parse stage, maps the content to your schema with an extraction model, and returns `output.data` plus per-field citations in `output.metadata`. Keep the schema’s root an `object`, set `options.strict` to `true`, validate the result in your own code, and route `fuzzy_match` and `not_found` fields to review. To run your own model instead, parse to Markdown with `POST /extraction/parse` and pass the Markdown to your model’s structured-output feature, and grounding becomes your job.

Nutrient recommends testing that on your own pages, because the answer varies by scan quality and table density. Model APIs read scans as page images, so the model performs recognition and table reconstruction in the same step as interpretation, with no separate signal when a cell is misread. The Nutrient Data Extraction API runs OCR in more than 100 languages, returns tables as typed elements with cells and bounds, and offers an agentic mode with a vision language model (VLM) for degraded scans and cursive handwriting. Even there, its guide warns that an ambiguous word can be read confidently but wrong, so keep a human review step for high-stakes fields.

Nutrient’s approach is to check every extracted value against its source on the page and label the result, rather than trust the model to report its own uncertainty. The extract endpoint returns a `match` label per field (`id_match`, `id_match_multiblock`, `id_match_partial`, `fuzzy_match`, or `not_found`), with a bounding box and a confidence score where the engine provides one. Add instructions such as “Extract values exactly as shown. Do not infer missing values,” and send ungrounded or low-confidence fields to review. No setup makes a model incapable of error, so the review gate matters more than the prompt.

Nutrient prices the Data Extraction API in credits per page, so the cost of a parsing API is predictable from page count and mode: 1 credit per page in text mode, 1.5 in structure, 9 in understand, and 18 in agentic, plus 6 per page for schema extraction. Model APIs bill tokens, and the OpenAI and Anthropic PDF guides say PDF input includes page images as well as extracted text. Which is cheaper depends on your documents, your model, and how much of each page the model needs to see. Parse-then-prompt can reduce model input when the model reads Markdown instead of page images. Measure both on a representative sample, including the cost of reviewing wrong values.

Nutrient is the hosted path when you need schema-shaped JSON with per-field citations, and an open source parser is the self-hosted path when documents must stay on your hardware and your team will build the extraction and review layer. Choose Docling when local, air-gapped parsing with layout, reading order, and table structure is the requirement. Choose Marker when you want chunked Markdown from a self-hosted converter and the model weights license fits your use. Choose Unstructured when one library has to partition many file types and your team will test its table output first. Nutrient also runs extraction on your own servers through its Java and Python SDKs under a separate SDK license.
