> This page is for version v2026-02-09 (default).
> For other versions, use one of these documentation indexes:
> - v2026-02-09 (default): https://docs.extend.ai/2026-02-09/llms.txt
> - v2025-04-21: https://docs.extend.ai/2025-04-21/llms.txt
> - v2024-12-23: https://docs.extend.ai/2024-12-23/llms.txt

> ## Documentation Index
> Fetch the complete documentation index at: https://docs.extend.ai/llms.txt
> Use this file to discover all available pages before exploring further.
>
> ## API version
> The current API version is `2026-02-09`, served at the site root (no version prefix in URLs).
> If this page URL contains `/2025-04-21/` or `/2024-12-23/`, you are reading an older API version.
> Prefer the current docs at https://docs.extend.ai/llms.txt unless the user explicitly needs that older version.
> Do not treat older-version pages as the source of truth for new integrations.

# Parsing Overview

> Parsing converts any document into clean, layout-aware, LLM-ready markdown and structured blocks.

**Parsing** converts documents into clean, structured, LLM-ready content. It turns PDFs, images, spreadsheets, presentations, and scanned files into layout-aware markdown, split into chunks, alongside a block-level breakdown (text, tables, figures, and key-value pairs) with spatial metadata. Use it as the foundation for RAG pipelines, custom ingestion workflows, downstream extraction, and agents.

## Quick start

We'll parse a sample bank statement. For this quick-start we've uploaded the file [here.](https://extend-public-files.s3.us-east-2.amazonaws.com/bank_statement_example.pdf)

![Bank statement page 1](/_fern-img/6054ef645b2cc17010f5472ca513d6b4c02ad1c15ba0abc4dbe982408f517322.webp)

Grab a key from the [Developers](https://dashboard.extend.ai/developers) page and store it as the `EXTEND_API_KEY` environment variable. If you're using an SDK, see the [installation instructions](/sdks).

```bash
export EXTEND_API_KEY="your_api_key_here"
```

#### Python

```python
from extend_ai import Extend

client = Extend()

response = client.parse(
    file={
        "url": "https://extend-public-files.s3.us-east-2.amazonaws.com/bank_statement_example.pdf",
    }
)

print(response)
```

#### TypeScript

```typescript
import { ExtendClient } from "extend-ai";

const client = new ExtendClient();

const response = await client.parse({
  file: {
    url: "https://extend-public-files.s3.us-east-2.amazonaws.com/bank_statement_example.pdf",
  },
});

console.log(response);
```

#### Java

```java
import ai.extend.ExtendClient;
import ai.extend.requests.ParseRequest;
import ai.extend.types.FileFromUrl;
import ai.extend.types.ParseRequestFile;
import ai.extend.types.ParseRun;

ExtendClient client = ExtendClient.builder().build();

ParseRun response = client.parse(ParseRequest.builder()
    .file(ParseRequestFile.of(FileFromUrl.builder()
        .url("https://extend-public-files.s3.us-east-2.amazonaws.com/bank_statement_example.pdf")
        .build()))
    .build());

System.out.println(response);
```

#### Go

```go
package main

import (
	"context"
	"fmt"
	"log"

	extend "github.com/extend-hq/extend-go-sdk"
	client "github.com/extend-hq/extend-go-sdk/client"
)

func main() {
	c := client.NewClient()

	response, err := c.Parse(context.TODO(), &extend.ParseRequest{
		File: &extend.ParseRequestFile{
			FileFromURL: &extend.FileFromURL{
				URL: "https://extend-public-files.s3.us-east-2.amazonaws.com/bank_statement_example.pdf",
			},
		},
	})
	if err != nil {
		log.Fatal(err)
	}

	fmt.Println(response)
}
```

#### cURL

```bash
curl -X POST "https://api.extend.ai/parse" \
  -H "x-extend-api-version: 2026-02-09" \
  -H "Authorization: Bearer $EXTEND_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "file": {
      "url": "https://extend-public-files.s3.us-east-2.amazonaws.com/bank_statement_example.pdf"
    }
  }'
```

> **Tip**
>
> Want to parse your own document? [Upload it](/api-reference/endpoints/file/upload-file) first, then pass the returned file `id` instead of a `url`.
>
> #### Python
>
> ```python
> with open("bank_statement.pdf", "rb") as f:
>     uploaded = client.files.upload(file=f)
>
> response = client.parse(file={"id": uploaded.id})
> ```
>
> #### TypeScript
>
> ```typescript
> import { createReadStream } from "fs";
>
> const uploaded = await client.files.upload(createReadStream("bank_statement.pdf"), {});
>
> const response = await client.parse({ file: { id: uploaded.id } });
> ```
>
> #### Java
>
> ```java
> import ai.extend.requests.FilesUploadRequest;
> import ai.extend.types.File;
> import ai.extend.types.FileFromId;
> import ai.extend.types.ParseRequestFile;
>
> File uploaded = client.files().upload(
>     new java.io.File("bank_statement.pdf"),
>     FilesUploadRequest.builder().build());
>
> ParseRun response = client.parse(ParseRequest.builder()
>     .file(ParseRequestFile.of(FileFromId.builder().id(uploaded.getId()).build()))
>     .build());
> ```
>
> #### Go
>
> ```go
> f, err := os.Open("bank_statement.pdf")
> if err != nil {
> 	log.Fatal(err)
> }
> defer f.Close()
>
> uploaded, err := c.Files.Upload(context.TODO(), f, &extend.FilesUploadRequest{})
> if err != nil {
> 	log.Fatal(err)
> }
>
> response, err := c.Parse(context.TODO(), &extend.ParseRequest{
> 	File: &extend.ParseRequestFile{
> 		FileFromID: &extend.FileFromID{ID: uploaded.ID},
> 	},
> })
> ```
>
> #### cURL
>
> ```bash
> # Upload the file to get an id
> curl -X POST https://api.extend.ai/files/upload \
>   -H "Authorization: Bearer $EXTEND_API_KEY" \
>   -H "x-extend-api-version: 2026-02-09" \
>   -F "file=@bank_statement.pdf"
>
> # Then parse using the returned id
> curl -X POST https://api.extend.ai/parse \
>   -H "Authorization: Bearer $EXTEND_API_KEY" \
>   -H "x-extend-api-version: 2026-02-09" \
>   -H "Content-Type: application/json" \
>   -d '{ "file": { "id": "file_xK9mLPqRtN3vS8wF5hB2cQ" } }'
> ```

### Example response

After you run the code snippet above, you’ll see a response like this. This example response is truncated for brevity. The response is organized into output.chunks, which in this case are page-level units. Each chunk includes a formatted content string for the full page and a blocks array for block-level elements (like text, tables, and figures) with metadata and spatial data.

```json
{
  "object": "parse_run",
  "id": "pr_3f1j6I1gsw5k96xFiCnkM",
  "file": {
    "object": "file",
    "id": "file_GzKUy0VDhHscv7tweODYb",
    "name": "bank_statement.pdf"
  },
  "status": "PROCESSED",
  "output": {
    "chunks": [
      {
        "id": "chunk_qncr8Txe-wYvmFjipXgMD",
        "type": "page",
        "content": "CHASE JPMorgan Chase Bank, N.A. P O Box 659754...",
        "metadata": { "pageRange": { "start": 1, "end": 1 } },
        "blocks": [
          {
            "object": "block",
            "id": "block_WNoJ0WbMj4pRW9MpMpUox",
            "type": "text",
            "content": "CHASE JPMorgan Chase Bank, N.A. P O Box 659754 San Antonio, TX 78265 - 9754",
            "details": {},
            "metadata": { "page": { "number": 1, "width": 612, "height": 792 } },
            "polygon": [
              { "x": 56.873, "y": 35.374 },
              { "x": 162.173, "y": 35.215 },
              { "x": 162.245, "y": 81.158 },
              { "x": 56.938, "y": 81.317 }
            ],
            "boundingBox": { "left": 56.873, "top": 35.215, "right": 162.245, "bottom": 81.317 }
          }
        ]
      }
    ],
    "ocr": {
      "words": [
        {
          "content": "CHASE",
          "boundingBox": { "left": 56.873, "top": 35.374, "right": 90.201, "bottom": 45.128 },
          "confidence": 0.99,
          "pageNumber": 1,
          "blockId": "block_WNoJ0WbMj4pRW9MpMpUox"
        }
      ]
    },
    "metadata": {
      "originalMimeType": "application/pdf",
      "finalMimeType": "application/pdf",
      "pages": [
        { "number": 1, "rotationApplied": 0, "originalPageWidth": 612, "originalPageHeight": 792, "dpi": 72 }
      ]
    }
  },
  "metrics": { "pageCount": 7, "processingTimeMs": 8293 },
  "usage": { "credits": 14 }
}
```

### Key fields

| Field                     | What it contains                                                                                                                                                                                                                                                        |
| ------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `output.chunks`           | Parsed content units (page, section, or document-level based on config).                                                                                                                                                                                                |
| `output.chunks[].content` | Formatted content string for the chunk.                                                                                                                                                                                                                                 |
| `output.chunks[].blocks`  | Block array with structured elements and their layout data.                                                                                                                                                                                                             |
| `blocks[].type`           | What kind of element this is: `text`, `table`, `figure`, `key_value`, and more.                                                                                                                                                                                         |
| `blocks[].boundingBox`    | Coordinates showing where the element appears on the page.                                                                                                                                                                                                              |
| `output.ocr.words`        | Word-level OCR data with `blockId` linking each word to its block. Only present when [`advancedOptions.returnOcr.words`](/parsing/configuration#advancedoptionsreturnocrwords) is set.                                                                                  |
| `output.metadata`         | Per-page rotation, original-dimension, and file-type info. This is set when the file is a PDF or when it was converted to a PDF. See [Reconciling coordinates against your original file](/parsing/response-format#reconciling-coordinates-against-your-original-file). |

For full request/response details, see the [Create Parse Run API reference](/api-reference/endpoints/parse/create-parse-run).

### Use the output

You can pass each chunk's formatted `content` straight into an LLM, or walk individual `blocks` for more control over tables and layout.

#### Python

```python
# Access the formatted content of each chunk
for index, chunk in enumerate(response.output.chunks):
    print(f"Page {index + 1}:", chunk.content)

# Or work with individual blocks for more control
for chunk in response.output.chunks:
    for block in chunk.blocks:
        print(f"{block.type}:", block.content)
```

#### TypeScript

```typescript
// Access the formatted content of each chunk
response.output.chunks.forEach((chunk, index) => {
  console.log(`Page ${index + 1}:`, chunk.content);
});

// Or work with individual blocks for more control
response.output.chunks.forEach((chunk) => {
  chunk.blocks.forEach((block) => {
    console.log(`${block.type}:`, block.content);
  });
});
```

#### Java

```java
var chunks = response.getOutput().get().getChunks();

// Access the formatted content of each chunk
for (int i = 0; i < chunks.size(); i++) {
    System.out.println("Page " + (i + 1) + ": " + chunks.get(i).getContent());
}

// Or work with individual blocks for more control
for (var chunk : chunks) {
    for (var block : chunk.getBlocks()) {
        System.out.println(block.getType() + ": " + block.getContent());
    }
}
```

#### Go

```go
// Access the formatted content of each chunk
for i, chunk := range response.Output.Chunks {
	fmt.Printf("Page %d: %s\n", i+1, chunk.Content)
}

// Or work with individual blocks for more control
for _, chunk := range response.Output.Chunks {
	for _, block := range chunk.Blocks {
		fmt.Printf("%s: %s\n", block.Type, block.Content)
	}
}
```

For a deeper guide on how to use the output of this endpoint, see [Response Format](/parsing/response-format).

## Sync vs async

The example above calls the synchronous `/parse` endpoint. We also have an asynchronous `/parse_runs` endpoint that should be used for large files and high volume use cases.

See [Async Processing](/general/async-processing) for the full comparison, polling options, and webhook setup.

## Configuration

The quick start uses default settings. To control how a document is parsed, pass a `config` object alongside `file`. Here are the most commonly changed options; for the full reference, see [Configuration](/parsing/configuration).

### Engine

Choose the parsing engine based on your accuracy and latency needs.

```json
{ "config": { "engine": "parse_performance" } }
```

| Engine              | When to use                                                                                                                                                                                                  |
| ------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| `parse_performance` | Highest accuracy; best for strong checkbox support, complex tables, handwriting, and multilingual documents (default).                                                                                       |
| `parse_light`       | Faster, lower-cost parsing for high-volume ingestion. Handles layout well, but trades some accuracy on lower-quality scans, hard handwriting, large tables, non-Latin languages, and dense checkbox regions. |
| `parse_auto`        | Adaptive parsing that classifies difficulty and routes work per page: simple pages parse cheaply while complex pages get performance-level treatment. Best for mixed-complexity workloads.                   |

### Chunking

By default, Parse returns one chunk per page. For RAG, `section` chunking splits at semantic boundaries so each chunk is a complete unit you can embed and retrieve independently.

```json
{
  "config": {
    "chunkingStrategy": {
      "type": "section",
      "options": { "minCharacters": 500, "maxCharacters": 2000 }
    }
  }
}
```

| Type       | Behavior                                                                                                             |
| ---------- | -------------------------------------------------------------------------------------------------------------------- |
| `page`     | One chunk per page (default).                                                                                        |
| `section`  | Splits at logical sections (headings); keeps tables and figures intact. Best for RAG. Requires `target: "markdown"`. |
| `document` | The entire document as a single chunk.                                                                               |

[Full chunking options →](/parsing/configuration#chunking-strategy)

### Table format

Controls how tables appear in each block's `content`.

```json
{ "config": { "blockOptions": { "tables": { "targetFormat": "markdown" } } } }
```

| Format     | When to use                                                   |
| ---------- | ------------------------------------------------------------- |
| `html`     | Complex tables with merged cells or nested headers (default). |
| `markdown` | Simple tables and Markdown-based or LLM workflows.            |

### Figures, charts, diagrams, and equations

Figures are parsed by default: a vision model summarizes each image, chart, or diagram and classifies it (`figureType` of `chart`, `diagram`, `image`, `logo`, or `other`). Disable figures for the fastest parsing, or enable **advanced chart extraction** to convert charts into structured data tables. Enable **formulas** to return mathematical equations as `formula` blocks with a LaTeX representation.

```json
{
  "config": {
    "blockOptions": {
      "figures": { "enabled": true, "advancedChartExtractionEnabled": true },
      "formulas": { "enabled": true }
    }
  }
}
```

[Figure options →](/parsing/configuration#figures) · [Formula options →](/parsing/configuration#formulas)

### Agentic OCR and tables

Agentic processing uses a vision model to review and correct parsing output. It's off by default and adds latency, so enable it only where it helps:

* **`text.agentic`** — corrects low-confidence OCR. Enable for handwriting, faded or skewed scans, or when you see garbled characters in the output.
* **`tables.agentic`** — reviews and fixes table structure. Enable for tables with misaligned columns, merged cells, or values landing in the wrong column.

Don't enable either for clean digital PDFs; they parse correctly without it and you'll just add latency.

```json
{
  "config": {
    "blockOptions": {
      "text": { "agentic": { "enabled": true } },
      "tables": { "agentic": { "enabled": true } }
    }
  }
}
```

### Page range

Process only specific pages. Page numbers are 1-based and inclusive, and you're only billed for pages actually processed.

```json
{ "config": { "advancedOptions": { "pageRanges": [{ "start": 1, "end": 10 }] } } }
```

> **Note**
>
> For every option, including the full block options, Excel settings, and OCR output, see the [Configuration](/parsing/configuration) reference.

---

## Next steps

#### [Configuration](/parsing/configuration)

Customize chunking, output format, and block options

#### [Response Format](/parsing/response-format)

The full shape of chunks and blocks in the parse response.

#### [Best Practices](/parsing/best-practices)

Tune for speed or accuracy, plus ready-to-use recipes

#### [Parsing for RAG](/parsing/rag)

Markdown chunks, citations, and the end-to-end ingestion recipe for retrieval.

#### [Error Handling](/parsing/error-handling)

Handle parse errors with sync and async error-handling patterns