> For a complete page index of the Captain API documentation, fetch https://docs.captain.dev/llms.txt?excludeSpec=true

# Images

> How Captain indexes PNG, JPEG, GIF, BMP, TIFF and WebP files. One native image embedding plus a full written description, so a query matches what the image shows and what it says.

## Agent Quick Reference - Images

* Extensions: `.png`, `.jpg`, `.jpeg`, `.gif`, `.bmp`, `.tiff`, `.webp`. Sniffed by magic bytes; EXIF orientation applied. Animated GIF and multi-page TIFF use the first frame.
* Per image: one native image embedding from the pixels, plus a written description stored as searchable text: every visible word transcribed verbatim (labels, numbers, codes, handwriting), tables as markdown, charts with axis labels and values, and the scene itself. A dense table (5+ rows) gets a second, grid-accurate pass.
* Stored content: `[Image: name]` then the description. Text-heavy images over about 1,500 tokens split into several chunks at section headings.
* Query hit: `modality: "image"`, content is the description text, `document.source` names the file. Search matches the pixels (vector) or the words (keyword).
* Limits: 200 megapixels decoded, checked from the header before decoding. A corrupt file fails as a per-file error naming the file.
* `mask_pii`: OCR finds PII words, black boxes are painted over them in the indexed copy (upscaled up to 4x toward a 3,000 px short side, long side capped at 4,000 px), and the description is masked too. Fails closed.
* Billing: 0.5 credits per image.

Captain indexes an image as one record with two signals: a native image embedding computed
from the pixels, and a written description stored as searchable text. This page covers what
the description contains, when an image is split, what a result contains, masking, and the
limits.

## This is useful for

* Screenshots of dashboards and tools, found by the text on the screen
* Photos from the field, found by a serial number on a plate or by what the photo shows
* Whiteboards, labels and single-page scans that should be transcribed word for word
* Scanned forms that need PII painted out before they are indexed

## What one image becomes

* **A native image embedding**, computed from the pixels. This lets a query such as "a red
  forklift in a warehouse" match a photo that contains no text.
* **A written description**, stored as text on the same record. A vision model transcribes
  every visible word verbatim (labels, titles, numbers, part codes, watermarks, handwriting),
  renders tables as markdown, reads charts (axis labels, values, series, trend) and describes
  the scene.

Formats other than PNG and JPEG are converted before the vision pass. EXIF orientation is
applied, so a sideways phone photo is read the right way up. Animated GIFs and multi-page
TIFFs use their first frame.

## How an image is chunked

#### One record, two signals

The pixels are embedded once, and the description is stored as text beside the embedding.
A query matches the image by vector similarity to the pixels, by the words in the
description, or both. `match_sources` on a result says which.

#### Verbatim transcription

The description is written to be searched. Every visible word is transcribed as it
appears, so a serial number on a plate or a metric label on a dashboard matches as text.
The stored content starts with `[Image: file name]` followed by the description.

#### Dense tables

When the description contains a table of five rows or more, a layout model re-reads the
image into a fixed grid. The table is written out in row sections with the header
repeated, and the row count is cross-checked against the first transcription.

#### When an image is split

A photo or a logo is one chunk. A text-heavy image (a full-page scan, a long screenshot)
is split into several chunks at its section headings so each passage stays small enough
to match precisely.

## Query results

An image result has `modality: "image"`, `text` set to the description, and
`document.source` naming the file. Collections that contain media rerank by default because
vector scores from images and text are not on the same scale; see
[Multimodal Search](/guides/multimodal-search).

## Limits, masking and billing

Images are accepted up to 200 megapixels decoded (about 20,000 x 10,000). The check reads
the header first, so a small file that would decode to an enormous raster is refused
without being decoded. A corrupt or truncated file fails with an error that names it, and
only that file fails. Route size limits are on [File Size Limits](/guides/file-size-limits).

With `mask_pii` on, OCR finds words that carry PII (and, on ID documents, the field values
next to the labels), and solid boxes are painted over them in the copy Captain indexes.
Small images are upscaled up to 4x toward a 3,000 px short side before OCR, because small
print is missed at native resolution; the long side is capped at 4,000 px. The description
is masked as well. If masking fails, the image is not indexed. The original file is not
modified.

Billing is 0.5 credits per image.

## Examples

#### Screenshots of dashboards

Goal: find a screenshot by the numbers on the screen, from a folder of files named
`Screenshot 2026-03-04.png`.

**`request`**

```json title="request"
{
  "query": "conversion rate by channel, March",
  "limit": 5
}
```

**`result (one item)`**

```json title="result (one item)"
{
  "modality": "image",
  "match_sources": [
    "keyword",
    "content_embedding"
  ],
  "text": "[Image: Screenshot 2026-03-04.png]\nDashboard titled 'Acquisition, March 2026'. Table: Channel | Sessions | Conversion rate. Paid search | 41,200 | 3.8% ...",
  "document": {
    "id": "…",
    "name": "Screenshot 2026-03-04.png"
  }
}
```

The on-screen text is transcribed verbatim into the description, so the file name does
not matter.

#### Equipment photos from the field

Goal: find a photo by the serial number on its plate, limited to one site.

**`request`**

```json title="request"
{
  "query": "pump serial PX-4471-B",
  "limit": 3,
  "filter": {
    "site": {
      "$eq": "plant-2"
    }
  }
}
```

The serial number is in the description as text. Photos without text still match on
the image embedding.

#### A scanned form with PII masked

Goal: index a one-page scan as one record with a full transcription and a redacted copy.
For a multi-page scan that needs page ranges and block-level citations, send it as a PDF
instead; see [Documents](/guides/file-types/documents).

**`index request (form fields)`**

```json title="index request (form fields)"
{
  "mask_pii": true,
  "custom_metadata": {
    "form": "KYC-2"
  }
}
```

OCR runs on an upscaled copy, boxes are painted into the indexed copy, and the
description is masked.

See [Supported File Types](/guides/supported-file-types#images) for the extension table.