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

# OCR, document intelligence, and DAM search

> Extract embedded PDF text or OCR PDF and image pages asynchronously, inspect normalized word geometry, cache by content identity, and search extracted text in the DAM.

<Tip>
  **Live.** This area is documented as current, user-reliable behavior.
</Tip>

## Goal

Make PDFs and images searchable while keeping extraction state and failures independent from asset availability.

## Prerequisites

* A PDF or image asset
* An `assets:process` token to start or retry extraction and `assets:read` to read results or search
* The English language pack for the shipped `eng` runtime; additional Tesseract language data must exist before requesting another code

## Workflow

<Steps>
  <Step>
    Start extraction for one asset, or enable `auto_extract_text` on a bucket for future PDF and image uploads.
  </Step>

  <Step>
    Poll the extraction until it is `ready` or `failed`. Continue serving the original asset regardless of OCR state.
  </Step>

  <Step>
    Store or render `plain_text`, then use ordered page blocks and normalized boxes for highlights or overlays.
  </Step>

  <Step>
    Search the existing Assets list with `query`; key and original-name matching continue to work and ready extracted text participates in the same result set.
  </Step>

  <Step>
    Fix a visible failure cause and retry the extraction ID when necessary.
  </Step>
</Steps>

## Provider behavior and supported input

* The production provider is `poppler_tesseract`; its cache identity includes the installed Poppler and Tesseract engine versions.
* For a PDF, `pdftotext -bbox-layout` first extracts embedded text and word boxes. If the document has no usable embedded text, `pdftoppm` renders every page and Tesseract OCRs the PNG pages.
* For an image MIME type, Tesseract processes one page directly.
* The default language is `eng`. The only current option is `dpi` for rasterized PDFs; it defaults to 200 and is clamped to 72–400.

## Start, read, and retry

```ts theme={null}
const extraction = await stackshift.assets.text.start(asset.id, {
  language: 'eng',
  options: { dpi: 240 },
})

let current = await stackshift.assets.text.get(asset.id)
while (current.status === 'pending' || current.status === 'processing') {
  await new Promise((resolve) => setTimeout(resolve, 2000))
  current = await stackshift.assets.text.get(asset.id)
}
if (current.status === 'failed') {
  console.error(current.error_code, current.error_message)
  await stackshift.assets.text.retry(current.id)
}
```

```bash theme={null}
stackshift asset ocr-start ASSET_UUID --wait --data '{"language":"eng","options":{"dpi":240}}' --output json
stackshift asset ocr-get ASSET_UUID --output json
stackshift asset ocr-retry EXTRACTION_UUID --output json
```

## Result schema and geometry

Extraction states are `pending`, `processing`, `ready`, and `failed`. A ready result includes `plain_text`, `page_count`, and ordered `pages`. Each page has a one-based `number`, source `width` and `height`, and ordered word blocks.

* `box` is `[left, top, right, bottom]`, normalized to 0–1 relative to the page.
* Tesseract confidence is normalized from 0–100 to 0–1. Embedded PDF words have confidence `1` because no OCR probability is involved.
* Page dimensions remain useful for projecting normalized boxes into pixels, canvas coordinates, or PDF viewer coordinates.

```json theme={null}
{
  "status": "ready",
  "plain_text": "Invoice total 42.00",
  "page_count": 1,
  "pages": [{
    "number": 1,
    "width": 1275,
    "height": 1650,
    "blocks": [{
      "text": "Invoice",
      "type": "word",
      "confidence": 0.97,
      "box": [0.10, 0.22, 0.24, 0.27]
    }]
  }]
}
```

## Automatic extraction, cache identity, and versions

* Bucket automation defaults off. Set `auto_extract_text: true` through the revision-checked storage configuration endpoint; it applies to future supported uploads and replacements.
* The cache key is tenant-scoped and includes asset SHA-256, provider, engine version, language, and canonical options hash. Identical content in one Assets space can reuse a result without cross-tenant disclosure.
* The extraction is linked to the current asset version. Replacing bytes changes the checksum/version and therefore creates or links the correct cache entry naturally.
* A failed extraction records `error_code` and `error_message`, emits an OCR failure event, and remains retryable. It never changes asset readiness, scan state, visibility, or delivery.

## Search extracted text

Use the existing Assets list `query` filter. StackShift keeps the existing case-insensitive key and original-name search, then also matches ready current extraction text through PostgreSQL web-search syntax. The list and count queries use the same predicate, so pagination totals remain consistent.

```ts theme={null}
const results = await stackshift.assets.list({
  query: '"invoice total" 42.00',
  status: 'ready',
  limit: 50,
})
```

## Expected result

<Check>
  The asset exposes searchable plain text and page/word geometry without changing its bytes, current version, or delivery URL.
</Check>

## Common failures

<Warning>
  * The asset MIME type is neither `application/pdf` nor `image/*`.
  * A requested Tesseract language pack is not installed; the production image ships the English `eng` pack.
  * A PDF is encrypted, malformed, or cannot be rendered by Poppler.
  * The asset backend cannot be read or the worker runs out of bounded scratch capacity.
</Warning>

## Related guides

<CardGroup cols={2}>
  <Card title="Upload UX and DAM" href="/assets/upload-ux-and-dam">
    Build a durable upload and digital-asset-management workflow with resumable sessions, revision-safe mutations, search, collections, webhooks, and usage summaries.
  </Card>

  <Card title="Assets platform API, SDK, CLI, and operations" href="/assets/platform-api-cli-and-operations">
    A complete interface and recovery reference for storage connections, S2, imports, relocation, OCR, browser capabilities, reports, scopes, events, billing, and durable worker behavior.
  </Card>

  <Card title="AI DAM and versioning" href="/assets/ai-dam-and-versioning">
    Use configured asset AI jobs, moderation, transcripts, derived images, collections, saved searches, and branching versions with explicit readiness and spend controls.
  </Card>
</CardGroup>
