Skip to content
Back to skills

Unstructured Io

ASecurity

Unstructured.io library for partitioning documents by filetype (PDF, DOCX, HTML, EPUB, PPT, email). Covers partition strategies (fast, hi_res, ocr_only, auto), chunking by title, metadata extraction, and serverless API usage. USE WHEN: user mentions "unstructured.io", "unstructured library", "partition documents", "multi-format ingestion", "DOCX to chunks", "HTML to RAG", "EPUB parser", "PPT extraction" DO NOT USE FOR: PDF-specific layout - use `pdf-extraction`; pure OCR work - use `ocr`; t...

  • 31 stars
  • 0 votes
  • 0 copies
  • 2 views
  • Added September 8, 2026
ai-agentspythongobashgitapi

Works with

  • cli
  • api

Security analysis

A96/100
  • mediumInstalls packages at runtime which could introduce malicious dependencies

Pro shows the line behind each finding and how to fix it

Scanned September 8, 2026

npx -y skills add claude-dev-suite/claude-dev-suite --skill unstructured-io --agent claude-code

Installs into .claude/skills of the current project.

Are you the author of Unstructured Io?

Add the live security badge to your README. It updates with every re-scan.

Security grade badge for Unstructured Io
[![Security: A — Skills Directory](https://www.skillsdirectory.com/api/skills/claude-dev-suite-unstructured-io/badge)](https://www.skillsdirectory.com/skills/claude-dev-suite-unstructured-io)

More formats (shields.io, HTML) on the badges page. Keep it an A: scan every change in CI with Pro.

Download with Pro
SKILL.md
---
name: unstructured-io
description: |
  Unstructured.io library for partitioning documents by filetype (PDF, DOCX, HTML,
  EPUB, PPT, email). Covers partition strategies (fast, hi_res, ocr_only, auto),
  chunking by title, metadata extraction, and serverless API usage.

  USE WHEN: user mentions "unstructured.io", "unstructured library", "partition
  documents", "multi-format ingestion", "DOCX to chunks", "HTML to RAG",
  "EPUB parser", "PPT extraction"

  DO NOT USE FOR: PDF-specific layout - use `pdf-extraction`;
  pure OCR work - use `ocr`;
  table-specific extraction - use `table-extraction`
allowed-tools: Read, Grep, Glob, Write, Edit
---
# Unstructured.io

## Installation

```bash
# Minimal
pip install "unstructured[all-docs]"

# System deps (Linux)
apt-get install -y poppler-utils tesseract-ocr libmagic1

# hi_res with layout model (Linux recommended)
pip install "unstructured[all-docs]" "unstructured-inference" "detectron2@git+https://github.com/facebookresearch/detectron2.git"
```

## Auto Partition by Filetype

```python
from unstructured.partition.auto import partition

# Routes to the right partitioner based on filetype
elements = partition(filename="contract.pdf")
# Also works: .docx, .html, .eml, .epub, .pptx, .xlsx, .md, .csv, .txt, .rst

for el in elements:
    print(el.category, "|", el.text[:80])
    # Title, NarrativeText, ListItem, Table, Image, Header, Footer, ...
```

## Filetype-Specific Partitioners

```python
from unstructured.partition.pdf import partition_pdf
from unstructured.partition.docx import partition_docx
from unstructured.partition.html import partition_html
from unstructured.partition.pptx import partition_pptx
from unstructured.partition.epub import partition_epub
from unstructured.partition.email import partition_email

pdf_elements = partition_pdf(
    filename="report.pdf",
    strategy="hi_res",                 # fast | hi_res | ocr_only | auto
    extract_images_in_pdf=True,
    extract_image_block_types=["Image", "Table"],
    extract_image_block_to_payload=False,
    extract_image_block_output_dir="./images",
    infer_table_structure=True,
    languages=["eng"],
    hi_res_model_name="yolox",         # yolox | detectron2_onnx
)

docx_elements = partition_docx(filename="brief.docx", include_page_breaks=True)
html_elements = partition_html(url="https://example.com/article")
pptx_elements = partition_pptx(filename="deck.pptx")
epub_elements = partition_epub(filename="book.epub")
eml_elements = partition_email(filename="msg.eml", process_attachments=True)
```

## Strategies Compared

| Strategy | Speed | Quality | Use Case |
|----------|-------|---------|----------|
| `fast` | Very fast | Text-only, no layout | Born-digital PDFs, bulk ingestion |
| `hi_res` | Slow (GPU helps) | Layout-aware (tables, figures) | RAG, complex docs |
| `ocr_only` | Medium | OCR every page | Scanned PDFs |
| `auto` | Variable | Picks per-document | Mixed corpora |

## Chunking by Title

```python
from unstructured.chunking.title import chunk_by_title

elements = partition_pdf(filename="report.pdf", strategy="hi_res")

chunks = chunk_by_title(
    elements,
    max_characters=1500,
    new_after_n_chars=1200,
    combine_text_under_n_chars=500,
    overlap=200,
    multipage_sections=True,
)

for chunk in chunks:
    print(chunk.metadata.page_number, chunk.text[:120])
```

## Basic (Character) Chunking

```python
from unstructured.chunking.basic import chunk_elements

chunks = chunk_elements(
    elements,
    max_characters=1200,
    new_after_n_chars=1000,
    overlap=150,
)
```

## Metadata Extraction

```python
for el in elements:
    m = el.metadata
    print({
        "filename": m.filename,
        "filetype": m.filetype,
        "page": m.page_number,
        "coordinates": m.coordinates.to_dict() if m.coordinates else None,
        "parent_id": m.parent_id,
        "languages": m.languages,
        "emphasized_texts": m.emphasized_text_contents,
        "link_urls": m.link_urls,
    })
```

## Convert to LangChain / LlamaIndex Documents

```python
from langchain_core.documents import Document as LCDocument

lc_docs = [
    LCDocument(
        page_content=chunk.text,
        metadata={
            "source": chunk.metadata.filename,
            "page": chunk.metadata.page_number,
            "category": chunk.category,
        },
    )
    for chunk in chunks
]

# LlamaIndex
from llama_index.core import Document as LIDocument

li_docs = [
    LIDocument(text=chunk.text, metadata={
        "page": chunk.metadata.page_number,
        "source": chunk.metadata.filename,
    })
    for chunk in chunks
]
```

## Serverless API (Unstructured Platform)

```python
import os
from unstructured_client import UnstructuredClient
from unstructured_client.models import operations, shared

client = UnstructuredClient(
    api_key_auth=os.environ["UNSTRUCTURED_API_KEY"],
    server_url=os.environ["UNSTRUCTURED_API_URL"],  # e.g., https://api.unstructuredapp.io
)

with open("contract.pdf", "rb") as f:
    files = shared.Files(content=f.read(), file_name="contract.pdf")

req = operations.PartitionRequest(
    partition_parameters=shared.PartitionParameters(
        files=files,
        strategy=shared.Strategy.HI_RES,
        chunking_strategy="by_title",
        max_characters=1500,
        overlap=200,
        split_pdf_page=True,
        split_pdf_concurrency_level=8,
    )
)

response = client.general.partition(request=req)
for element in response.elements:
    print(element["type"], element["text"][:100])
```

## Async Batch Ingestion

```python
import asyncio
from pathlib import Path
from unstructured.partition.auto import partition

async def process(path: Path):
    return await asyncio.to_thread(partition, filename=str(path), strategy="fast")

async def ingest_dir(root: str):
    paths = list(Path(root).rglob("*"))
    paths = [p for p in paths if p.suffix.lower() in {".pdf", ".docx", ".html", ".epub"}]
    results = await asyncio.gather(*(process(p) for p in paths))
    return dict(zip(paths, results))

asyncio.run(ingest_dir("./corpus"))
```

## Element Categories

Common `el.category` values: `Title`, `NarrativeText`, `ListItem`, `Table`, `Image`, `FigureCaption`, `Header`, `Footer`, `Address`, `EmailAddress`, `PageBreak`, `CodeSnippet`, `Formula`, `UncategorizedText`.

Filter out boilerplate before chunking:

```python
drop = {"Header", "Footer", "PageBreak", "UncategorizedText"}
cleaned = [el for el in elements if el.category not in drop]
```

## Anti-Patterns

| Anti-Pattern | Fix |
|---|---|
| Using `hi_res` on 10k simple PDFs | Start with `fast`, upgrade only when needed |
| Ignoring `parent_id` hierarchy | Preserve it so chunks know their section |
| Running `detectron2` without GPU | Use `yolox` model or run in serverless API |
| Treating Tables as NarrativeText | Convert Table elements to markdown separately |
| Skipping `combine_text_under_n_chars` | Tiny chunks hurt retrieval - combine them |
| Re-partitioning on every query | Persist elements as JSON and reload |

## Production Checklist

- [ ] Strategy chosen per document type (fast vs hi_res vs ocr_only)
- [ ] System deps installed (poppler, tesseract, libmagic)
- [ ] Chunked with `chunk_by_title` for structured docs
- [ ] Metadata preserved end-to-end (page, coordinates, parent_id)
- [ ] Boilerplate categories filtered before indexing
- [ ] Serverless API used for heavy `hi_res` workloads if no GPU
- [ ] `split_pdf_page=True` for large PDFs on the API
- [ ] Elements cached as JSON keyed by file hash

Attribution

Is this your skill, or is something wrong with this listing? Request removal or report an issue. Author removals are honored within 72 hours.

Comments

Loading comments…