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

# Examples

> Common implementation patterns for Parse.

Copy and adapt these examples for your own parsing tasks. All examples use the REST API with the `requests` library and read credentials from environment variables.

```python theme={null}
import os

HEADERS = {
    "x-ti-app-id": os.environ["TEXTIN_APP_ID"],
    "x-ti-secret-code": os.environ["TEXTIN_SECRET_CODE"],
}

PARSE_SYNC_URL = "https://api.textin.ai/api/v1/xparse/parse/sync"
```

<Info>
  See [Configuration](/xparse/parse/configuration) for all available options and [Response Format](/xparse/parse/response-format) for the full response structure.
</Info>

## Parse a PDF

Convert a PDF document to Markdown and structured elements.

```python theme={null}
import os
import requests

with open("document.pdf", "rb") as file:
    response = requests.post(
        "https://api.textin.ai/api/v1/xparse/parse/sync",
        headers=HEADERS,
        files={"file": ("document.pdf", file)},
    )

response.raise_for_status()
result = response.json()["data"]

with open("output.md", "w", encoding="utf-8") as out:
    out.write(result["markdown"])
```

## Parse from a URL

Parse a document directly from a hosted URL without uploading the file.

```python theme={null}
import requests

response = requests.post(
    "https://api.textin.ai/api/v1/xparse/parse/sync",
    headers=HEADERS,
    data={"file_url": "https://example.com/document.pdf"},
)

result = response.json()["data"]
print(result["markdown"])
```

## Parse specific pages

Use `page_range` to parse only selected pages.

```python theme={null}
import json
import requests

config = {"scope": {"page_range": "1-5,10,15-20"}}

with open("large_document.pdf", "rb") as file:
    response = requests.post(
        "https://api.textin.ai/api/v1/xparse/parse/sync",
        headers=HEADERS,
        files={"file": ("large_document.pdf", file)},
        data={"config": json.dumps(config)},
    )

result = response.json()["data"]
```

## Extract tables

Enable `include_table_structure` to return structured row, column, and cell data.

```python theme={null}
import json
import requests

config = {
    "capabilities": {
        "include_table_structure": True,
        "table_view": "html",
    }
}

with open("financial_report.pdf", "rb") as file:
    response = requests.post(
        "https://api.textin.ai/api/v1/xparse/parse/sync",
        headers=HEADERS,
        files={"file": ("financial_report.pdf", file)},
        data={"config": json.dumps(config)},
    )

result = response.json()["data"]

tables = [el for el in result["elements"] if el["type"] == "Table"]

for table in tables:
    structure = table.get("table_structure")
    if structure:
        print(f"Table: {structure['rows']}x{structure['cols']}")
        for cell in structure["cells"]:
            if cell["row"] == 1 and cell["col"] == 1:
                print("Cell [1,1]:", cell["text"])
```

## Extract formulas

Enable `include_inline_objects` to detect inline formulas, and read standalone `Formula` elements directly.

```python theme={null}
import json
import requests

config = {"capabilities": {"include_inline_objects": True}}

with open("paper.pdf", "rb") as file:
    response = requests.post(
        "https://api.textin.ai/api/v1/xparse/parse/sync",
        headers=HEADERS,
        files={"file": ("paper.pdf", file)},
        data={"config": json.dumps(config)},
    )

result = response.json()["data"]

# Standalone formulas
formulas = [el for el in result["elements"] if el["type"] == "Formula"]
for formula in formulas:
    print("Formula:", formula["text"])

# Inline formulas within text
for element in result["elements"]:
    for obj in element.get("objects", []):
        if obj["type"] == "formula":
            print("Inline formula:", obj["text"])
```

## Parse scanned documents

Use preprocessing options only when the document needs them.

```python theme={null}
import json
import requests

config = {
    "capabilities": {
        "crop_dewarp": True,
        "remove_watermark": True,
    }
}

with open("scan.jpg", "rb") as file:
    response = requests.post(
        "https://api.textin.ai/api/v1/xparse/parse/sync",
        headers=HEADERS,
        files={"file": ("scan.jpg", file)},
        data={"config": json.dumps(config)},
    )

result = response.json()["data"]
print(result["markdown"])
```

## Extract images

Enable `include_image_data` to return image URLs for `Image` elements.

```python theme={null}
import json
import requests

config = {"capabilities": {"include_image_data": True}}

with open("report.pdf", "rb") as file:
    response = requests.post(
        "https://api.textin.ai/api/v1/xparse/parse/sync",
        headers=HEADERS,
        files={"file": ("report.pdf", file)},
        data={"config": json.dumps(config)},
    )

result = response.json()["data"]

images = [el for el in result["elements"] if el["type"] == "Image"]

for index, image in enumerate(images):
    image_data = image.get("image_data")
    if image_data and image_data.get("image_url"):
        content = requests.get(image_data["image_url"]).content
        ext = image_data.get("mime_type", "image/png").split("/")[-1]
        with open(f"image_{index}.{ext}", "wb") as out:
            out.write(content)
```

## Parse a password-protected PDF

Pass the PDF password in the `document` section of the config.

```python theme={null}
import json
import requests

config = {"document": {"password": "your-pdf-password"}}

with open("protected.pdf", "rb") as file:
    response = requests.post(
        "https://api.textin.ai/api/v1/xparse/parse/sync",
        headers=HEADERS,
        files={"file": ("protected.pdf", file)},
        data={"config": json.dumps(config)},
    )

result = response.json()["data"]
```

## Convert coordinates to pixels

Element coordinates are normalized to the page width and height.

```python theme={null}
result = response.json()["data"]

page_width, page_height = 1576, 1683

for element in result["elements"]:
    if element["type"] == "Table":
        coords = element["coordinates"]
        x1 = int(coords[0] * page_width)
        y1 = int(coords[1] * page_height)
        x3 = int(coords[4] * page_width)
        y3 = int(coords[5] * page_height)
        print(f"Table on page {element['page_number']}: ({x1}, {y1}) to ({x3}, {y3})")
```

## Build a RAG pipeline

Parse a document into Markdown, split it into chunks, and prepare it for embedding.

```python theme={null}
import json
import requests

config = {
    "capabilities": {
        "include_hierarchy": True,
        "title_tree": True,
    }
}

with open("knowledge_base.pdf", "rb") as file:
    response = requests.post(
        "https://api.textin.ai/api/v1/xparse/parse/sync",
        headers=HEADERS,
        files={"file": ("knowledge_base.pdf", file)},
        data={"config": json.dumps(config)},
    )

result = response.json()["data"]

# Simple heading-based chunking
chunks = result["markdown"].split("\n## ")

# Or chunk by element while tracking the current heading as context
def chunk_by_elements(elements, chunk_size=500):
    chunks = []
    current, size, context = [], 0, ""
    for el in elements:
        if el["type"] == "Title":
            context = el["text"]
        text = el["text"]
        if size + len(text) > chunk_size and current:
            chunks.append({"text": "\n".join(current), "context": context})
            current, size = [], 0
        current.append(text)
        size += len(text)
    if current:
        chunks.append({"text": "\n".join(current), "context": context})
    return chunks

chunks = chunk_by_elements(result["elements"])
```

## Process large files asynchronously

For large or complex documents, use the asynchronous API. See [Async Processing](/xparse/parse/async-processing) for the complete guide.

```python theme={null}
import os
import time
import requests

# 1. Create the job
with open("large_report.pdf", "rb") as file:
    response = requests.post(
        "https://api.textin.ai/api/v1/xparse/parse/async",
        headers=HEADERS,
        files={"file": ("large_report.pdf", file)},
    )
job_id = response.json()["data"]["job_id"]

# 2. Poll until the job completes
while True:
    response = requests.get(
        f"https://api.textin.ai/api/v1/xparse/parse/async/{job_id}",
        headers=HEADERS,
    )
    data = response.json()["data"]
    if data["status"] == "completed":
        result_url = data["result_url"]
        break
    if data["status"] == "failed":
        raise RuntimeError(response.json()["message"])
    time.sleep(15)

# 3. Download the result
result = requests.get(result_url, headers=HEADERS).json()
print(result["markdown"])
```

## Handle errors

Check the response `code` and handle common failures.

```python theme={null}
import requests

response = requests.post(
    "https://api.textin.ai/api/v1/xparse/parse/sync",
    headers=HEADERS,
    files={"file": ("document.pdf", open("document.pdf", "rb"))},
)

body = response.json()
code = body.get("code")

if code != 200:
    if code == 40302:
        print("File too large. Use the async API or split the file.")
    elif code == 40423:
        print("Incorrect PDF password. Provide the correct password.")
    elif code == 40424:
        print("Page range out of bounds. Adjust the page_range parameter.")
    else:
        print(f"Error {code}: {body.get('message')}")
```

<Info>
  See [Errors](/xparse/errors) for the complete error code reference.
</Info>

## Related resources

<CardGroup cols={3}>
  <Card title="Configuration" icon="sliders" href="/xparse/parse/configuration">
    Customize parsing behavior.
  </Card>

  <Card title="Response Format" icon="code" href="/xparse/parse/response-format">
    Understand the response structure.
  </Card>

  <Card title="Async Processing" icon="clock" href="/xparse/parse/async-processing">
    Process large documents asynchronously.
  </Card>
</CardGroup>
