> ## Documentation Index
> Fetch the complete documentation index at: https://docs.filerouter.dev/llms.txt
> Use this file to discover all available pages before exploring further.

# Parse Output Formats: Markdown, Pages, Images, and More

> FileRouter normalizes nine output types into one result shape. Unsupported outputs fail before any provider I/O — request only what you need.

Every `parse()` or `compare()` call produces a `ParseResult` whose normalized data lives exclusively under `result.outputs`. You tell FileRouter exactly which outputs you want by passing an `outputs` array in your options — you are never charged for, or forced to receive, outputs you did not ask for. Top-level result fields like `pageCount`, `usage`, `warnings`, and `timing` remain at the root of the result regardless of which outputs you request.

## Requesting outputs

Pass an array of output IDs to `outputs` in your parse options. You must request at least one:

```ts request-outputs.ts theme={null}
import { FileRouter } from "@file_router/sdk"
import { llamaparse } from "@file_router/sdk/llamaparse"

const router = new FileRouter({
  providers: { llamaparse: llamaparse() },
})

const result = await router.parse("https://example.com/report.pdf", {
  provider: "llamaparse",
  outputs: ["markdown", "pages"],
})

// Normalized outputs are under result.outputs
console.log(result.outputs.markdown)     // full document as Markdown string
console.log(result.outputs.pages)        // array of per-page objects

// Top-level metadata stays at the result root
console.log(result.pageCount)            // total number of pages
console.log(result.provider)             // "llamaparse"
console.log(result.warnings)             // any parse warnings
console.log(result.timing.durationMs)    // how long the parse took
```

## Available output IDs

The valid output identifiers are exported from the SDK as `parseOutputIds`:

```ts output-ids.ts theme={null}
import { parseOutputIds } from "@file_router/sdk"

// ["chunks", "html", "images", "json", "markdown", "metadata", "pages", "tables", "text"]
console.log(parseOutputIds)
```

<Accordion title="chunks">
  The document split into semantic chunks suitable for embedding and retrieval. Each chunk carries enough context to be inserted into a vector store. Currently supported by **Datalab** only.
</Accordion>

<Accordion title="html">
  The document rendered as an HTML string. Preserves headings, lists, and basic table markup. Currently supported by **Datalab** only.
</Accordion>

<Accordion title="images">
  An array of `ParsedImage` objects extracted from the document. Each image may include a URL, a base64 `data` string, a `caption`, a `bbox` (bounding box), and the `pageNumber` it appeared on. Supported by **LlamaParse**, **Mistral OCR**, and **Datalab**.
</Accordion>

<Accordion title="json">
  The document as structured JSON. The exact shape is provider-native — LlamaParse returns its items representation; Mistral OCR and Datalab return their own JSON structures. Supported by **LlamaParse**, **Mistral OCR**, and **Datalab**.
</Accordion>

<Accordion title="markdown">
  The full document as a Markdown string. This is the most universally supported output — all three providers produce it. When `pages` is also requested, per-page Markdown is available on each page object as well.
</Accordion>

<Accordion title="metadata">
  Document-level metadata as a key-value map (`Record<string, unknown>`). Supported by **LlamaParse**, **Mistral OCR**, and **Datalab**.
</Accordion>

<Accordion title="pages">
  An array of `ParsePage` objects — one per document page. Each page object carries the `pageNumber` and any per-page fields that the provider produced (Markdown, text, HTML, images, tables, confidence, dimensions, and warnings). Supported by **LlamaParse**, **Mistral OCR**, and **Datalab**.
</Accordion>

<Accordion title="tables">
  An array of `ParsedTable` objects extracted from the document. Each table may include a `markdown` representation, an `html` representation, raw `rows`, a `format` hint, and the `pageNumber`. Supported by **LlamaParse**, **Mistral OCR**, and **Datalab**.
</Accordion>

<Accordion title="text">
  The full document as plain text, stripped of Markdown formatting. Supported by **LlamaParse** only.
</Accordion>

## Provider output support

<Warning>
  Not every provider supports every output. If you request an output that the provider you selected does not support, FileRouter raises a `FileRouterError` **before** making any API call. No credits are consumed and no partial results are returned. Check the provider's declared capabilities before requesting unusual outputs.
</Warning>

You can inspect what a configured provider supports at runtime:

```ts check-capabilities.ts theme={null}
import { FileRouter } from "@file_router/sdk"
import { datalab } from "@file_router/sdk/datalab"

const router = new FileRouter({
  providers: { datalab: datalab() },
})

const caps = router.providers
// caps.datalab.capabilities.outputs → ["chunks", "html", "images", "json", "markdown", "metadata"]
```

## Result shape reference

<ResponseField name="result.outputs" type="Partial<ParseOutputValues>">
  All normalized parse outputs live here, keyed by the output ID you requested. Fields are only present if you included the corresponding ID in your `outputs` array.

  <ResponseField name="outputs.markdown" type="string">
    Full document Markdown.
  </ResponseField>

  <ResponseField name="outputs.text" type="string">
    Full document plain text (LlamaParse only).
  </ResponseField>

  <ResponseField name="outputs.html" type="string">
    Full document HTML (Datalab only).
  </ResponseField>

  <ResponseField name="outputs.pages" type="ParsePage[]">
    Per-page content objects, sorted by page number.
  </ResponseField>

  <ResponseField name="outputs.images" type="ParsedImage[]">
    All extracted images across the document.
  </ResponseField>

  <ResponseField name="outputs.tables" type="ParsedTable[]">
    All extracted tables across the document.
  </ResponseField>

  <ResponseField name="outputs.json" type="unknown">
    Provider-native structured JSON.
  </ResponseField>

  <ResponseField name="outputs.metadata" type="Record<string, unknown>">
    Document-level metadata.
  </ResponseField>

  <ResponseField name="outputs.chunks" type="unknown">
    Semantic chunks for retrieval (Datalab only).
  </ResponseField>
</ResponseField>

<ResponseField name="result.pageCount" type="number">
  Total number of pages detected in the document.
</ResponseField>

<ResponseField name="result.provider" type="string">
  The ID of the provider that produced this result (e.g. `"llamaparse"`).
</ResponseField>

<ResponseField name="result.warnings" type="ParseWarning[]">
  Any warnings raised during parsing, including per-page issues. Each warning has a `code`, a `message`, and an optional `pageNumber`.
</ResponseField>

<ResponseField name="result.timing" type="object">
  Parse timing data: `startedAt` (ISO string), `completedAt` (ISO string), and `durationMs` (number).
</ResponseField>

<ResponseField name="result.usage" type="object">
  Provider-reported consumption: `pages`, `credits`, and `costUsd` — each optional depending on what the provider reports.
</ResponseField>

<ResponseField name="result.quality" type="object">
  Provider-native quality score, if available. Includes a `score` and an optional `scale`. Do not compare scores across different providers — each provider uses its own scale.
</ResponseField>

## Including the raw provider response

By default, FileRouter discards the original provider response after normalizing it. If you need to inspect the native response — for debugging, auditing, or accessing data that FileRouter does not yet normalize — pass `includeRaw: true`:

```ts include-raw.ts theme={null}
const result = await router.parse("https://example.com/report.pdf", {
  provider: "mistral-ocr",
  outputs: ["markdown"],
  includeRaw: true,
})

// result.raw contains the complete, unmodified Mistral OCR response
console.log(result.raw)
```

<Warning>
  `includeRaw: true` is opt-in for good reason. Provider responses can be very large — especially when the document contains many images or detailed per-page JSON. Enabling it in production increases result storage size and memory pressure. Use it for debugging and inspection, not as a default.
</Warning>
