OCR Image to Text API: Private, with Translation avatar

OCR Image to Text API: Private, with Translation

Pricing

from $2.80 / 1,000 image returneds

Go to Apify Store
OCR Image to Text API: Private, with Translation

OCR Image to Text API: Private, with Translation

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.

Pricing

from $2.80 / 1,000 image returneds

Rating

0.0

(0)

Developer

Pradio Actors

Pradio Actors

Maintained by Community

Actor stats

0

Bookmarked

12

Total users

8

Monthly active users

15 hours ago

Last modified

Share

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:

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

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.

{
"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

BuyerWhat they run it for
Developers adding OCR to an appPost a list of image URLs through the API and get JSON rows back, one per image
Operations and back-office teamsTurn scanned documents, receipts and screenshots into text you can search and process
Data, research and AI-agent buildersPull 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:

{
"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:

FieldTypeWhat it is
image_urlstringThe URL this row was read from, echoed so every row names its source; null on base64 and store images.
image_source, image_namestringWhere 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_textstringThe whole text read out of the image; empty on a readable, text-free image.
word_countnumberWords read; Chinese, Japanese and Korean text counts one per character.
mean_confidencenumberThe words' average confidence, 0 to 100; null on a wordless read.
image_width, image_heightnumberSize in pixels from the file's own header, when the format carries it.
words, lines, paragraphsarrayThe words, text lines and paragraphs found, each entry with text, a confidence score and a pixel box.
ocr_languagestringThe model code the image was read in; detected_language is what the text turned out to be.
detected_languagestringThe 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_enginestringpaddleocr or tesseract: with the language empty, a Latin-alphabet or Cyrillic page is read by tesseract.
translation, translation_language, translation_notestringEnglish machine translation, its language (en), and the machine-translation label or why untranslated; null when Translate to is unset.
fetched_in_seconds, processed_in_secondsnumberSeconds to download (null on base64) and to read, accents included.
row_typestringROW on a data row, ITEM_STATUS on a miss, NO_TEXT_FOUND or STOPPED_EARLY closing the run.
statusstringok on a read; a miss names its kind: not_found, fetch_failed, bad_url, bad_input, blocked, timeout, unreadable or not_reached.
reasonstringOn a miss row: what went wrong, or why the run stopped or returned zero rows.
rowsFetched, rowsReturned, rowsRemainingintegerOn 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 sendBilled rows backImage cost
100 image URLsabout 93$0.37
1,000 image URLsabout 930$3.72
10,000 image URLsabout 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

InputTypeDefaultWhat it does
image_urlsarraysix test URLs: five images and one web page, so a first run shows a free missThe public http(s) image URLs to read; one data row per readable entry.
ocr_languagestringempty: automaticRead every image in a named language, or leave empty to work each out.
base64ImagesarrayemptyImages inside the input itself, each {"name": "receipt-01.png", "data": "<base64>"}; the platform caps input size, so send large files through your store.
keyValueStoreIdstringemptyYour key-value store holding images, by ID or name; picking it grants the run read access.
keyValueStoreRecordsarrayemptyThe keys of entries to read from that store, one per line.
datasetIdstringemptyYour dataset whose items hold image URLs, by ID or name; picking it grants the run read access.
datasetUrlFieldstringempty: usual fieldsThe 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.
outputDetailstringfullfull, lines or text: how much layout each row carries.
translateTostringempty: offen adds an English machine translation of the read text.
minConfidenceinteger0Leave out words, lines and paragraphs scoring under it, 0 to 100; 70 is a good first value.
preprocessstringnoneOptional 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.
pageSegmentationstringautoHow Tesseract segments the page: a single column, block or line, or sparse text. PaddleOCR ignores it.
maxItemsinteger100The most rows one run returns; the rest come back named and free.
maxMegabytesPerImageinteger40The most megabytes one image may be, 1 to 40.
dryRunbooleanoffProbe every entry without reading or billing it.
seenDatasetIdstringemptyA previous run's dataset; entries it read are skipped free.

Details worth knowing:

  • 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:

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

Or start a run over the Apify API:

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.
  • 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.