# OCR Image to Text API: Private, with Translation (`pradio/image-text`) Actor

Extract text from images with private OCR: your images and their English translation stay inside the run, never sent to an outside service. Get words, lines and paragraphs with confidence scores and boxes, image size and detected language. Send URLs, base64, a dataset or a key-value store.

- **URL**: https://apify.com/pradio/image-text.md
- **Developed by:** [Pradio Actors](https://apify.com/pradio) (community)
- **Categories:** Developer tools, AI
- **Features:** Limited permissions
- **Stats:** 15 total users, 10 monthly users, 78.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $2.80 / 1,000 image returneds

This Actor is paid per event. You are not charged for the Apify platform usage, but only a fixed price for specific events.
Since this Actor supports Apify Store discounts, the price gets lower the higher subscription plan you have.

Learn more: https://docs.apify.com/actors/running/actors-in-store.md#pay-per-event

## What's an Apify Actor?

An Actor is a serverless cloud program that runs on the Apify platform. It has two run modes.
In Batch mode, an Actor accepts a well-defined JSON input, performs an action which can take anything from a few seconds to a few hours,
and optionally produces a well-defined JSON output, datasets with results, or files in key-value store.
In Standby mode, an Actor provides a web server which can be used as a website, API, or an MCP server.

Apify vocabulary and the platform model are defined once, in the agent quickstart at https://apify.com/agents.md.

## How to integrate an Actor?

If asked about integration, you help developers integrate Actors into their projects.
You adapt to their stack and deliver integrations that are safe, well-documented, and production-ready.

Do not guess an integration path. Every one of them is in the agent quickstart at https://apify.com/agents.md: the Apify MCP server, Agent Skills with the Apify CLI, the JavaScript and Python clients, the REST API, and the account-free path for an agent with no human to sign in. It also carries the rule on stating cost before the first paid run.

For examples already wired to this Actor's own input schema, see the [API](#api) section below.

Each client library has reference documentation the quickstart does not restate: [JavaScript/TypeScript](https://docs.apify.com/api/client/js/docs.md) (`npm install apify-client`) and [Python](https://docs.apify.com/api/client/python/docs.md) (`pip install apify-client`).

# README

## OCR Image to Text API: Private, with Translation

### What does OCR Image to Text API do?

Give it your images and it gives you their text back as JSON: image to text, read privately. The OCR and the optional English translation run inside the run: no outside service sees an image or its text. Each row carries the words, lines and paragraphs it read, with a confidence score and a pixel box each. It also carries the image's size, the language of the text and an optional English translation. Send public image URLs, files as base64, key-value store records, or image URLs held in one of your datasets. An image it cannot read costs nothing, and its row says why.

**$4 per 1,000 images.** In a test batch of 57 new images read with the OCR language set to English, 47 came back with their text, 6 were readable but empty of text, and 4 failed to read. You pay for the 53 it read.

Read a batch of public images, text alone:

```json
{
  "image_urls": ["https://app.koofr.net/content/links/18da9989-4d2e-4017-9319-b76a5309c62f/files/get/eng_bw.png?path=%2F"],
  "outputDetail": "text"
}
```

Read a German page and get an English translation beside it:

```json
{
  "image_urls": ["https://app.koofr.net/content/links/d7c0be09-6f03-4915-ab48-a6122de6a744/files/get/deu.png?path=%2F"],
  "ocr_language": "de",
  "translateTo": "en"
}
```

One image, one row. A real row reads like this, cut short for the page. The field table and a fuller row sit under Output.

```json
{
  "status": "ok",
  "image_url": "https://app.koofr.net/content/links/7994c136-634b-44cd-a91a-eb54091cefdc/files/get/cosmic.png?path=%2F",
  "full_text": "Hello World
from beyond
the Cosmic Void",
  "word_count": 7,
  "mean_confidence": 99.7,
  "detected_language": null,
  "ocr_engine": "paddleocr"
}
```

### Who uses OCR Image to Text API

| Buyer | What they run it for |
|---|---|
| Developers adding OCR to an app | Post a list of image URLs through the API and get JSON rows back, one per image |
| Operations and back-office teams | Turn scanned documents, receipts and screenshots into text you can search and process |
| Data, research and AI-agent builders | Pull text out of image collections for indexing, or give an agent a way to read it through the MCP line below |

### Features

- **Scored word by word.** Every word, line and paragraph carries its own confidence score, and the row carries the image's average.
- **Automatic language, accents kept.** Leave the OCR language empty. A Latin-alphabet page is then read in its own language, so Paraná comes back as Paraná.
- **Optional English translation.** Set Translate to for an English machine translation of the read text. Eight languages are covered at zero extra charge, and every translated row says it is machine-made.
- **Four ways to send images.** Public URLs, files inside the input as base64, records in your key-value store, or image URLs in a dataset you pick.
- **A confidence floor you set.** Minimum confidence leaves out every word, line and paragraph scoring under it. A smudge or a blur then stays out of your text.
- **A free check before paying.** Check only probes every entry the way a real read would. It names the ones that would reject, all free.
- **Resume without paying twice.** Point Skip images a previous run read at an earlier run's dataset. A re-run then reads and bills the images it left unread.

### Why this one

- **Measured on a real batch.** A 57-image run came back 93% answered: 47 with their text, 6 readable but empty, 4 failed. That is 53 billable rows at $0.004 each.
- **Rows carry the whole answer.** Words, lines and paragraphs each with a confidence score and a pixel box; in a side-by-side sample read against the shelf's leading seller, its rows were the more complete ones.

### How do I use OCR Image to Text API?

1. **Send the images.** Paste public image URLs, files as base64, keys in your key-value store, or a dataset holding URLs. The quick-start input above is a working first run.
2. **Set the reading.** Leave the OCR language empty for automatic, or name it for a known language. Set Translate to for English. Raise Minimum confidence to keep uncertain words out.
3. **Read the rows.** One row per image lands in the run's dataset with the text, scores and layout. Entries it cannot read come back as miss rows naming why.

### Output: what data does OCR Image to Text API return?

This is that row in full, every field it carried:

```json
{
  "status": "ok",
  "image_url": "https://app.koofr.net/content/links/7994c136-634b-44cd-a91a-eb54091cefdc/files/get/cosmic.png?path=%2F",
  "image_source": "url",
  "image_name": null,
  "full_text": "Hello World
from beyond
the Cosmic Void",
  "paragraphs": [
    {"text": "Hello World
from beyond
the Cosmic Void", "confidence": 99.6, "bbox": {"x0": 99, "y0": 16, "x1": 317, "y1": 124}}
  ],
  "word_count": 7,
  "mean_confidence": 99.7,
  "image_width": 400,
  "image_height": 400,
  "words": [
    {"text": "Hello", "confidence": 98.9, "bbox": {"x0": 101, "y0": 16, "x1": 186, "y1": 42}},
    {"text": "World", "confidence": 98.9, "bbox": {"x0": 203, "y0": 16, "x1": 288, "y1": 42}},
    {"text": "from", "confidence": 100, "bbox": {"x0": 100, "y0": 56, "x1": 157, "y1": 86}},
    {"text": "beyond", "confidence": 100, "bbox": {"x0": 171, "y0": 56, "x1": 256, "y1": 86}},
    {"text": "the", "confidence": 100, "bbox": {"x0": 99, "y0": 95, "x1": 143, "y1": 124}},
    {"text": "Cosmic", "confidence": 100, "bbox": {"x0": 157, "y0": 95, "x1": 244, "y1": 124}},
    {"text": "Void", "confidence": 100, "bbox": {"x0": 259, "y0": 95, "x1": 317, "y1": 124}}
  ],
  "ocr_language": "eng",
  "detected_language": null,
  "ocr_engine": "paddleocr",
  "lines": [
    {"text": "Hello World", "confidence": 98.9, "bbox": {"x0": 101, "y0": 16, "x1": 288, "y1": 42}},
    {"text": "from beyond", "confidence": 100, "bbox": {"x0": 100, "y0": 56, "x1": 256, "y1": 86}},
    {"text": "the Cosmic Void", "confidence": 100, "bbox": {"x0": 99, "y0": 95, "x1": 317, "y1": 124}}
  ],
  "translation": null,
  "translation_language": null,
  "translation_note": null,
  "fetched_in_seconds": 0.083,
  "processed_in_seconds": 0.247,
  "row_type": "ROW"
}
```

A miss lands in the same dataset as a row carrying the entry, its status and the reason instead.

One row per image. Every field a row can carry:

| Field | Type | What it is |
|---|---|---|
| `image_url` | string | The URL this row was read from, echoed so every row names its source; null on base64 and store images. |
| `image_source`, `image_name` | string | Where the image came from (url, dataset, base64, key_value_store; dry_run on a check's summary row), and its name when sent without a URL. |
| `full_text` | string | The whole text read out of the image; empty on a readable, text-free image. |
| `word_count` | number | Words read; Chinese, Japanese and Korean text counts one per character. |
| `mean_confidence` | number | The words' average confidence, 0 to 100; null on a wordless read. |
| `image_width`, `image_height` | number | Size in pixels from the file's own header, when the format carries it. |
| `words`, `lines`, `paragraphs` | array | The words, text lines and paragraphs found, each entry with text, a confidence score and a pixel box. |
| `ocr_language` | string | The model code the image was read in; detected_language is what the text turned out to be. |
| `detected_language` | string | The text's language as a three-letter ISO code; null when the text is too short, mostly fragments or split between scripts. Right on 87.4% of labelled scans. |
| `ocr_engine` | string | paddleocr or tesseract: with the language empty, a Latin-alphabet or Cyrillic page is read by tesseract. |
| `translation`, `translation_language`, `translation_note` | string | English machine translation, its language (en), and the machine-translation label or why untranslated; null when Translate to is unset. |
| `fetched_in_seconds`, `processed_in_seconds` | number | Seconds to download (null on base64) and to read, accents included. |
| `row_type` | string | ROW on a data row, ITEM_STATUS on a miss, NO_TEXT_FOUND or STOPPED_EARLY closing the run. |
| `status` | string | ok on a read; a miss names its kind: not_found, fetch_failed, bad_url, bad_input, blocked, timeout, unreadable or not_reached. |
| `reason` | string | On a miss row: what went wrong, or why the run stopped or returned zero rows. |
| `rowsFetched`, `rowsReturned`, `rowsRemaining` | integer | On the run's summary row: entries read before de-duplication, data rows kept, rows left out. |

The run's summary row lives beside your rows as an entry in the key-value store; the `rowsFetched`, `rowsReturned` and `rowsRemaining` fields appear on it alone.

### How much does it cost?

Two prices cover everything:

- **$0.004 per returned image**, the Image read event (`document-returned` in the Console). One charged unit is one image read and returned as a row. We bill it after the row lands in your dataset.
- **$0.00005 per start event** (`apify-actor-start`), the platform's per-run charge of one event per GB of memory. At the 2048 MB default that is $0.0001 a run.

On the Store's discount tiers the price per image falls to $0.0036, $0.0032 and $0.0028.

| You send | Billed rows back | Image cost |
|---|---|---|
| 100 image URLs | about 93 | $0.37 |
| 1,000 image URLs, in 4 runs | about 930 | $3.72 |
| 10,000 image URLs, in 40 runs | about 9,298 | $37.19 |

Billed rows are projected at the fill the 57-image test showed, and misses are free. The miss rows beside them in your dataset, dropped duplicates, entries past Maximum items and entries an earlier run already read all sit outside the count. Set a spending limit for a hard cap, or run Check only to probe your list first.

### Input

| Input | Type | Default | What it does |
|---|---|---|---|
| `image_urls` | array | six test URLs: five images and one web page, so a first run shows a free miss | The public http(s) image URLs to read; one data row per readable entry. |
| `ocr_language` | string | empty: automatic | Read every image in a named language, or leave empty to work each out. |
| `base64Images` | array | empty | Images inside the input itself, each `{"name": "receipt-01.png", "data": "<base64>"}`; the platform caps input size, so send large files through your store. |
| `keyValueStoreId` | string | empty | Your key-value store holding images, by ID or name; picking it grants the run read access. |
| `keyValueStoreRecords` | array | empty | The keys of entries to read from that store, one per line. |
| `datasetId` | string | empty | Your dataset whose items hold image URLs, by ID or name; picking it grants the run read access. |
| `datasetUrlField` | string | empty: usual fields | The item field holding the image URL or a list of them; empty tries image_url, imageUrl, image, url then src; a dotted path reads a nested field. |
| `outputDetail` | string | full | full, lines or text: how much layout each row carries. |
| `translateTo` | string | empty: off | en adds an English machine translation of the read text. |
| `minConfidence` | integer | 0 | Leave out words, lines and paragraphs scoring under it, 0 to 100; 70 is a good first value. |
| `preprocess` | string | none | Optional image work before OCR: enhance (grayscale, contrast and sharpen) for faint scans, binarize (grayscale then threshold) for dirty or colored backgrounds. Runs on the normalised image both engines read. |
| `pageSegmentation` | string | auto | How Tesseract segments the page: a single column, block or line, or sparse text. PaddleOCR ignores it. |
| `maxItems` | integer | 100 | The most rows one run returns; the rest come back named and free. |
| `maxMegabytesPerImage` | integer | 40 | The most megabytes one image may be, 1 to 40. |
| `dryRun` | boolean | off | Probe every entry without reading or billing it. |
| `timeBudgetSeconds` | integer | empty | The most seconds one run may spend reading, 120 or more. A minute before it ends no new image is started; the entries left come back on free rows that name the budget. |
| `zipArchiveUrl` | string | empty | The address of one ZIP archive of images, up to 100 MB. Each image is read and named archive address/member; each member counts against Maximum items. |
| `zipArchiveRecord` | string | empty | The key of a record in the key-value store that holds a ZIP archive file, up to 100 MB; its members are named archive key/member. |
| `seenDatasetId` | string | empty | A previous run's dataset; entries it read are skipped free. |

Details worth knowing:

- **Blank lines are skipped.** A blank or whitespace-only line in any list is not an entry: it is skipped and gets no row.
- **The prefilled list is example data.** Replace the six test URLs with your own before your first real run: reading them bills a few cents for rows you did not ask about.
- **Language codes.** Two-letter codes such as en or de are mapped for you. Codes joined with + read mixed-language images. With en set, accents in other Latin-alphabet languages come back plain, and another script comes back as a miss. Leave it empty for automatic.
- **Reading a dataset.** Leave **Image URL field in the dataset** empty and the usual names are tried in order. An item without a URL comes back as a miss row naming it. You need the right to read and use every image the dataset points to.
- **Translation.** Into English, over up to 5,000 characters of read text per image: set `ocr_language` to `de` and `translateTo` to `en` for German with English beside it. Text already in English, or in a language outside the eight models, stays untranslated, with the reason on the row.

### Use it with AI agents and integrations

Every run writes its rows to an Apify dataset. The platform's integrations, schedules and webhooks all work with it. Paste this line to give a compatible agent this Actor as a tool:

```bash
claude mcp add --transport http apify "https://mcp.apify.com?tools=Pradio/image-text"
```

Or start a run over the Apify API:

```bash
curl -X POST "https://api.apify.com/v2/acts/Pradio~image-text/runs?token=<YOUR_APIFY_TOKEN>" \
  -H "Content-Type: application/json" \
  -d '{"image_urls": ["https://app.koofr.net/content/links/18da9989-4d2e-4017-9319-b76a5309c62f/files/get/eng_bw.png?path=%2F"], "ocr_language": "eng"}'
```

### Personal data

Rows are the text found in the images you supply, possibly machine-translated. That text may hold personal data or protected works, and you are responsible for it: for having the right to read every image you give it, and for how you use the rows. The run returns that text to you alone; you are the controller of what you upload. The design treats it like this:

- **Your images only, no retention.** The run reads only what you send, follows zero links, and keeps everything inside your own run dataset; you must hold the rights or a lawful basis for every image. A base64 image is listed by name and size, its bytes left out.
- **Everything stays inside the run.** Translation is off unless you set Translate to, then runs offline on bundled models; every translated row says it is machine-made, and unset, the translation fields are null. Extraction is verbatim: no sentiment, named-entity, person or topic inference. A refused read ends that read; logins, captchas and access walls stay closed to it.

### Limits

- **Public image URLs, or the bytes themselves.** A URL that answers a web page, text or anything other than image bytes is a miss. Anything behind a login or a block stays outside this Actor; send such a file as base64 or through your store.
- **Plain, paced fetches.** Each URL is one GET with a declared user agent, one request at a time per host. A refused read or a challenge page is a miss and stays refused for the rest of the run; an over-size image or a slow fetch is a miss too.
- **Language has its bounds.** Text that cannot be placed in a language at low confidence comes back a miss; name the language and run again. The detected language is null on very short text, on text that is mostly fragments, on a page split between two scripts such as Chinese and English, and on two close languages scoring alike such as Dutch and Norwegian. Mostly Han text is cmn. Chinese, Japanese and Korean text counts one character per word.
- **Image files only, not PDFs.** For scanned PDFs use our [PDF Text Extractor](https://apify.com/pradio/pdf-text-verifier).
- **Translation is machine translation.** Into English, from the eight languages under Translate to. It is as good as the text read.
- **OCR is exactness-limited.** Handwriting, decorative fonts and low-contrast or blurred text can come back partial; the confidence scores are the signal to filter on. A readable image empty of text still bills: the empty read is its delivered answer.

### Troubleshooting

- **One row in the dataset looks different from the rest.** It is a miss row: the entry failed to read, and its status and reason say why. Extra rows past Maximum items are miss rows too, naming the entries the cap left out.
- **The run failed instead of returning rows.** A failure the run cannot pin on one entry fails the whole run with the error in the log. A broken source is kept from looking like a good run that found little.

If your run shows something else, open an issue on this Actor's Store page with the run ID.

### FAQ

**Can I use it through the Apify API or an MCP server?**

Yes to both. The API starts runs, polls their status and reads the dataset. The curl line above is the whole call. The MCP line above registers it as a tool an agent can hand image URLs to.

**How accurate is the text detection?**

Every word, line and paragraph carries a confidence score, and the row carries the image's average. Clean scans and printed pages read best; handwriting and blurred photographs read worst. Filter on Minimum confidence before you trust noisy text.

On 82 proofread Wikisource pages in English, French, German and Russian, the read text was wrong on a median of 1.7% of its characters, and 76.8% of the pages were within 5%. Plain Tesseract at its defaults scored the same on those pages.

The detected language was right on 87.4% of 119 labelled scans (104 right). Old, damaged or mixed-language print is where it is wrong or null.

**A host keeps refusing the download. What can I do?**

A refused read comes back as a miss row and stays refused for the rest of the run. Download the image yourself and send it as base64, or save it to your key-value store and name its key.

**What does a miss cost?**

Zero. Misses are free. An image that fails to read comes back as a row naming the entry and the reason.

**How many images can one run take?**

As many entries as you send, up to Maximum items (100 by default). The rest come back named on miss rows. One image may be up to the megabyte cap (40 by default), and a URL must be public.

### Release notes

- **2026-10-28**: with the language empty, Latin-alphabet pages are read by Tesseract, which cut the read text's median character error from 2.4% to 1.7%, and text that is mostly fragments gets no detected language.
- **2026-09-30**: a free check-only pass before a paid run, and a resume that skips already-read images.
- **2026-09-29**: entries past the row cap come back named on miss rows, free.
- **2026-09-22**: the first release: one row per image, misses unbilled, private OCR inside the run.

### Feedback

A problem or a missing field goes to the Issues tab on this Actor's page in the Apify Console. We answer there. If the Actor saved you time, a review on the Store helps other buyers find it.

### Not affiliated

OCR Image to Text API is an independent tool, not affiliated with or endorsed by any host it reads images from.

# Actor input Schema

## `image_urls` (type: `array`):

Public http(s) image URLs to OCR, one data row each, no login or proxy. No page is read for the image and no link followed. An unreadable entry is an uncharged status row naming it. Blank lines are skipped and get no row. You need the right to read every image you list. Leave empty when sending through Images as base64 or a key-value store.

## `base64Images` (type: `array`):

Images as base64 for files that are not online: objects {"name": "receipt-01.png", "data": "<base64 or data: URI>"}; the name is echoed as image_name. Invalid data is an uncharged bad_input row. Large files go through a key-value store (the input itself is size-limited).

## `keyValueStoreId` (type: `string`):

One of your key-value stores holding the images to read, by ID or name. Pick it so the run gets read access. Records are named in Key-value store records.

## `keyValueStoreRecords` (type: `array`):

The record keys to read, one per line. Each holds an image file (PNG, JPEG, GIF, BMP, WebP, TIFF) or base64 text; a missing key is an uncharged not_found row naming it.

## `datasetId` (type: `string`):

One of your datasets whose items hold image URLs, by ID or name. You need the right to read every image it points to. Pick it for read access. One image per item, or per URL in a list field; an item with no URL is an uncharged bad_input row. Example: a scraper's product photos.

## `datasetUrlField` (type: `string`):

The item field holding the image URL or URL list; a dotted path like media.images reads a nested field. Empty: the first of image_url, imageUrl, image, url, src the items carry.

## `ocr_language` (type: `string`):

Empty or auto: the language is detected per image (English and Chinese with PaddleOCR; another Latin-alphabet language gets a second Tesseract pass in it; a Cyrillic page is read again in Russian). Or force one: two-letter codes like en or de, joined with + for mixed-language images.

## `preprocess` (type: `string`):

Optional image work before OCR. It runs on the normalised PNG both engines read, so PaddleOCR and Tesseract benefit alike. enhance for faint or low-contrast scans; binarize for dirty or colored backgrounds.

## `pageSegmentation` (type: `string`):

How Tesseract segments the page, when the read goes to Tesseract (any language outside English and Chinese). PaddleOCR does its own detection and ignores this setting.

## `outputDetail` (type: `string`):

How much layout each row carries: full (default) returns words, lines and paragraphs with boxes; lines drops the per-word list; text returns full text and counts only.

## `translateTo` (type: `string`):

Empty: no translation. Set to en to add a machine English translation of each image's text (German, French, Spanish, Italian, Dutch, Polish, Russian, Chinese detected). Runs inside the Actor: no outside service, no extra charge; translation_note says it is machine-made.

## `minConfidence` (type: `integer`):

Drop words, lines and paragraphs scoring under this confidence (0-100, default 0 keeps everything). The row's own confidence, detected language and verdict still cover everything read. A good first value is 70.

## `maxItems` (type: `integer`):

The most rows one run returns (default 100). Entries past the cap come back as named, free not_reached rows.

## `maxMegabytesPerImage` (type: `integer`):

The most megabytes one image may declare before it is read (1-40, default 40); an image over the cap is an uncharged bad_input row naming it.

## `dryRun` (type: `boolean`):

Probe every entry without reading it: a HEAD request per URL, the same decode per record. Nothing OCR'd, nothing billed; each entry gets a free row with the status a real read would emit. Off by default.

## `timeBudgetSeconds` (type: `integer`):

Optional. The most seconds one run may spend reading. A minute before the budget ends the run starts no new image; every entry left is named on a free row saying so, not billed, and the run's summary names the budget as the cause. Run again with Skip images a previous run read set to this run's dataset to read the rest. Leave empty for no time budget. Minimum 120.

## `zipArchiveUrl` (type: `string`):

Optional. One ZIP archive of images, up to 100 MB, read in memory with no login. You need the right to read every image in it. Each image is named address/member on its row, and members count against Maximum items. A folder, nested archive or other non-image member gets a free row and no content.

## `zipArchiveRecord` (type: `string`):

Optional. The key of one record in Key-value store that holds a ZIP archive file itself, up to 100 MB. You need the right to read every image in it. It is read as a ZIP archive by URL is, and its members are named key/member. Leave empty when the archive is at a URL.

## `seenDatasetId` (type: `string`):

A previous run's dataset, by ID or URL. An entry already read there returns on a free row saying it was skipped, not read again and not billed; entries it missed or never reached are read as usual.

## Actor input object example

```json
{
  "image_urls": [
    "https://app.koofr.net/content/links/18da9989-4d2e-4017-9319-b76a5309c62f/files/get/eng_bw.png?path=%2F",
    "https://app.koofr.net/content/links/cc518dd1-9b5e-4546-9161-e10b74192d48/files/get/bill.png?path=%2F",
    "https://app.koofr.net/content/links/7994c136-634b-44cd-a91a-eb54091cefdc/files/get/cosmic.png?path=%2F",
    "https://app.koofr.net/content/links/4ecc22b0-83d5-43cc-a8e3-00420bdbdbc6/files/get/chi_sim.png?path=%2F",
    "https://app.koofr.net/content/links/d7c0be09-6f03-4915-ab48-a6122de6a744/files/get/deu.png?path=%2F",
    "https://example.com/"
  ],
  "base64Images": [],
  "keyValueStoreRecords": [],
  "preprocess": "none",
  "pageSegmentation": "auto",
  "outputDetail": "full",
  "minConfidence": 0,
  "maxItems": 100,
  "maxMegabytesPerImage": 40,
  "dryRun": false
}
```

# Actor output Schema

## `rows` (type: `string`):

The text rows for this run: one per readable image, plus any uncharged status rows.

## `summary` (type: `string`):

This run's counts: entries fetched, rows pushed, events charged, duplicates dropped, and whether the charge limit stopped the run early.

# API

You can run this Actor programmatically using our API. Below are code examples in JavaScript, Python, and CLI, as well as the OpenAPI specification and MCP server setup.

## JavaScript example

```javascript
import { ApifyClient } from 'apify-client';

// Initialize the ApifyClient with your Apify API token
// Replace the '<YOUR_API_TOKEN>' with your token
const client = new ApifyClient({
    token: '<YOUR_API_TOKEN>',
});

// Prepare Actor input
const input = {
    "image_urls": [
        "https://app.koofr.net/content/links/18da9989-4d2e-4017-9319-b76a5309c62f/files/get/eng_bw.png?path=%2F",
        "https://app.koofr.net/content/links/cc518dd1-9b5e-4546-9161-e10b74192d48/files/get/bill.png?path=%2F",
        "https://app.koofr.net/content/links/7994c136-634b-44cd-a91a-eb54091cefdc/files/get/cosmic.png?path=%2F",
        "https://app.koofr.net/content/links/4ecc22b0-83d5-43cc-a8e3-00420bdbdbc6/files/get/chi_sim.png?path=%2F",
        "https://app.koofr.net/content/links/d7c0be09-6f03-4915-ab48-a6122de6a744/files/get/deu.png?path=%2F",
        "https://example.com/"
    ]
};

// Run the Actor and wait for it to finish
const run = await client.actor("pradio/image-text").call(input);

// Fetch and print Actor results from the run's dataset (if any)
console.log('Results from dataset');
console.log(`💾 Check your data here: https://console.apify.com/storage/datasets/${run.defaultDatasetId}`);
const { items } = await client.dataset(run.defaultDatasetId).listItems();
items.forEach((item) => {
    console.dir(item);
});

// 📚 Want to learn more 📖? Go to → https://docs.apify.com/api/client/js/docs

```

## Python example

```python
from apify_client import ApifyClient

# Initialize the ApifyClient with your Apify API token
# Replace '<YOUR_API_TOKEN>' with your token.
client = ApifyClient("<YOUR_API_TOKEN>")

# Prepare the Actor input
run_input = { "image_urls": [
        "https://app.koofr.net/content/links/18da9989-4d2e-4017-9319-b76a5309c62f/files/get/eng_bw.png?path=%2F",
        "https://app.koofr.net/content/links/cc518dd1-9b5e-4546-9161-e10b74192d48/files/get/bill.png?path=%2F",
        "https://app.koofr.net/content/links/7994c136-634b-44cd-a91a-eb54091cefdc/files/get/cosmic.png?path=%2F",
        "https://app.koofr.net/content/links/4ecc22b0-83d5-43cc-a8e3-00420bdbdbc6/files/get/chi_sim.png?path=%2F",
        "https://app.koofr.net/content/links/d7c0be09-6f03-4915-ab48-a6122de6a744/files/get/deu.png?path=%2F",
        "https://example.com/",
    ] }

# Run the Actor and wait for it to finish
run = client.actor("pradio/image-text").call(run_input=run_input)

# Fetch and print Actor results from the run's dataset (if there are any)
print(f"💾 Check your data here: https://console.apify.com/storage/datasets/{run.default_dataset_id}")
for item in client.dataset(run.default_dataset_id).iterate_items():
    print(item)

# 📚 Want to learn more 📖? Go to → https://docs.apify.com/api/client/python/docs/quick-start

```

## CLI example

```bash
echo '{
  "image_urls": [
    "https://app.koofr.net/content/links/18da9989-4d2e-4017-9319-b76a5309c62f/files/get/eng_bw.png?path=%2F",
    "https://app.koofr.net/content/links/cc518dd1-9b5e-4546-9161-e10b74192d48/files/get/bill.png?path=%2F",
    "https://app.koofr.net/content/links/7994c136-634b-44cd-a91a-eb54091cefdc/files/get/cosmic.png?path=%2F",
    "https://app.koofr.net/content/links/4ecc22b0-83d5-43cc-a8e3-00420bdbdbc6/files/get/chi_sim.png?path=%2F",
    "https://app.koofr.net/content/links/d7c0be09-6f03-4915-ab48-a6122de6a744/files/get/deu.png?path=%2F",
    "https://example.com/"
  ]
}' |
apify call pradio/image-text --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,pradio/image-text"
        }
    }
}
```

The hosted server signs you in with OAuth on first connect, so no API token belongs in this config. Clients without OAuth support can send an `Authorization: Bearer <APIFY_API_TOKEN>` header instead, using a token from API & Integrations in Apify Console (https://console.apify.com/settings/integrations).

## OpenAPI specification

Download the OpenAPI definition: https://api.apify.com/v2/actors/89dBdHIn6CiI8sH0C/builds/UMfVCBaXEMMhBzini/openapi.json
