# Image to Text OCR: Read Text from Images & Screenshots (`private_image_hg9/image-to-text-ocr`) Actor

Extract text from images at public URLs with OCR: PNG, JPEG, WebP, GIF, BMP, multi-page TIFF, HEIC and AVIF. Full text with line breaks, confidence, and optional line or word boxes. 7 languages. Pay only for images where text was found; empty images and errors are free.

- **URL**: https://apify.com/private_image_hg9/image-to-text-ocr.md
- **Developed by:** [Michael Shanker](https://apify.com/private_image_hg9) (community)
- **Categories:** AI, Developer tools, Automation
- **Security:** Limited permissions
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

$1.50 / 1,000 image with texts

This Actor is paid per event. You are not charged for the Apify platform usage, but only a fixed price for specific events.

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

## Image to Text OCR: Read Text from Images & Screenshots

Give it the addresses of images and get back **the text in them**, with line breaks, a confidence score, and if you want, **every line or word with its position in the picture**. It reads PNG, JPEG, WebP, GIF, BMP, multi-page TIFF, HEIC (iPhone photos) and AVIF, in English, Spanish, French, German, Italian, Portuguese and Dutch.

**You pay only for images where text was found.** Images with no text, files that can't be downloaded or aren't pictures, and images that time out are saved with the reason and cost nothing.

### What it does

- **Full text with its layout.** Lines stay on their own lines and paragraphs are separated by a blank line, so receipts, forms, slides and screenshots read the way they look.
- **Confidence you can filter on.** Every image gets a `meanConfidence` from 0 to 100 (the average over its words). Clean scans and screenshots usually score above 90; blurry photos score much lower, so you can flag results to check by hand.
- **Lines and words with boxes.** Choose `lines` or `words` to get each line or word with its confidence and its box (`left`, `top`, `width`, `height`) in the original image's pixels, even when the image was enlarged or shrunk for reading. Good for highlighting text, redacting, or pulling out a field by position.
- **Image cleanup that helps OCR.** In `auto` mode, images are turned to grayscale, small images (screenshots, crops, thumbnails) are enlarged so letters are big enough, contrast is stretched, and light text on a dark background (dark-mode screenshots, signs) is inverted. Phone photos are turned upright from their rotation tag, and transparent PNGs are put on white.
- **Layouts for different pictures.** `auto` for documents, scans and screenshots; `auto_rotate` also turns sideways or upside-down scans upright; `single_block` for one paragraph or a cropped text box; `sparse` for photos, signs, labels and app screens where words are scattered.
- **Multi-page TIFFs** (faxes, scanned batches): every page is read (up to 50), with the text of each page in `pages` and a `--- page N ---` marker in the full text. You pay per page that had text.

Good for: turning screenshots and scanned pages into searchable text, reading receipts and invoices before parsing them, getting text out of social media images and memes, feeding image text to AI tools, checking product photos and labels, and indexing image archives.

### How it compares

Several small OCR tools in the Store charge per image, from about $1 to $2 per 1,000 images, some with a start fee. Here is the same work priced side by side:

| Job | This Actor | ~$1 / 1,000 images + start fee | ~$2 / 1,000 images |
|---|---|---|---|
| 1,000 images, all with text | $1.50 | about $1.00 + start fee | about $2.00 |
| 1,000 images, 400 with no text or broken links | $0.90 | check how it charges for empty and failed images | check how it charges for empty and failed images |
| Word and line boxes, confidence | included | check the tool | check the tool |

So if every image has text, the cheapest per-image tool costs less; if your batch mixes in photos without text, dead links or files that aren't pictures, you only pay here for what gave text. Try a few of your own images first: OCR quality depends most on the image.

### Input

| Field | What it does |
|---|---|
| **Image addresses** (`imageUrls`) | Public `http(s)` addresses of images, one per line. Request-list style objects (`{"url": "..."}`) work too. Redirects are followed, and an image sent with the wrong content type is still read. |
| **Languages** (`languages`) | Up to 4 of `eng`, `spa`, `fra`, `deu`, `ita`, `por`, `nld`. Default `["eng"]`. Pick only what you need: each extra language makes OCR slower. |
| **Detail** (`detail`) | `text` (default): text, counts and confidence. `lines`: also each line with its box. `words`: also each word with its box and line number. |
| **Layout** (`pageSegmentation`) | `auto` (default), `auto_rotate`, `single_block` or `sparse` (see above). |
| **Image cleanup** (`preprocessing`) | `auto` (default) or `off` to send the image as it is. |
| **Time limit per image** (`imageTimeoutSecs`) | Default 120 seconds. |

Example input:

```json
{
  "imageUrls": [
    "https://upload.wikimedia.org/wikipedia/commons/c/cd/Origin_of_Species_title_page.jpg",
    "https://www.example.org/screenshots/settings.png"
  ],
  "languages": ["eng"],
  "detail": "lines",
  "pageSegmentation": "auto"
}
```

### Output

One row per image (values shortened):

```json
{
  "url": "https://files.example.org/receipts/bakery.png",
  "inputUrl": "https://files.example.org/receipts/bakery.png",
  "status": "ok",
  "error": null,
  "note": null,
  "fileName": "bakery.png",
  "format": "PNG",
  "width": 900,
  "height": 520,
  "bytes": 23618,
  "pageCount": 1,
  "pagesRead": 1,
  "languages": ["eng"],
  "text": "CORNER BAKERY\n\n12 Market Street\nSourdough loaf 6.50\nTwo croissants 7.00\nTOTAL 13.50\n\nThank you for visiting",
  "charCount": 107,
  "wordCount": 17,
  "lineCount": 6,
  "meanConfidence": 96.3,
  "lines": [
    {"line": 1, "text": "CORNER BAKERY", "confidence": 96.5, "box": {"left": 41, "top": 46, "width": 236, "height": 20}},
    {"line": 5, "text": "TOTAL 13.50", "confidence": 96.5, "box": {"left": 40, "top": 222, "width": 176, "height": 20}}
  ],
  "preprocessing": ["grayscale", "enlarged 2x", "contrast stretched"],
  "ocrSeconds": 0.21,
  "ocrAt": "2026-11-04T17:07:46.906216+00:00"
}
```

- `width` and `height` are the image as it's shown (after its rotation tag); boxes use the same pixels.
- `words` (with `detail: words`) has `line`, `text`, `confidence` and `box` for each word. For multi-page TIFFs, lines and words also have `page`, and `pages` lists each page's text and confidence.
- `preprocessing` lists what was done to the image before reading, and `ocrSeconds` how long the reading took.
- `note` says when not everything was read and why (first frame of an animated GIF, TIFF page cap, spending cap, blank TIFF pages).

`status` is one of:

- `ok`: text was found (at least one word of two or more letters or digits read with confidence 50 or more). The only status that costs anything.
- `no_text`: the image was read but no letters or digits were found.
- `download_failed`: the server answered with an error, timed out, couldn't be reached, or the file is over 20 MB.
- `not_image`: the address returned a web page or an empty file.
- `unsupported_format`: an SVG drawing, a PDF, or a file type this tool doesn't read.
- `invalid_image`: the picture is damaged and can't be decoded.
- `image_too_large`: the picture is too big to decode in memory (see limits below).
- `ocr_failed`: reading took longer than the time limit, or the OCR engine failed on this image.
- `blocked_by_robots`: the website's robots.txt asks tools like this one not to download that address.
- `invalid_url`: not a usable public `http(s)` address.

Download results as JSON, CSV or Excel, or send them to Google Sheets, Zapier, Make or n8n. The run also saves a `SUMMARY` record in the key-value store with counts per status, images charged, the average OCR time, and whether the spending cap stopped the run.

### Pricing

Pay per event: **Image with text: $0.0015** ($1.50 per 1,000 images). For a multi-page TIFF, each page with text counts as one image.

No start fee. **Images where no text was found, failed downloads, files that aren't images, and timeouts are free.** Set a **maximum charge per run** in the run options: one charge is set aside for each image before it's downloaded, so the run never goes over the limit and stops cleanly when it's reached (the log and `SUMMARY` say so).

### Good to know

- **Speed.** A screenshot or small image takes well under a second of OCR time on one full CPU; a dense 300 DPI scanned page about 2 seconds; a 40-megapixel image about 7. With the default 1 GB of memory Apify gives the run a quarter of a CPU, so expect roughly four times that. More memory gives more CPU and reads more images at once.
- **Sizes.** Files up to 20 MB. Images over 40 megapixels are scaled down to 40 before reading (boxes are still in the original's pixels). Images that would take more than 256 MB to decode (about 64 megapixels in color) are refused, except JPEGs, which are decoded straight at a smaller size.
- **Formats.** GIFs and animated WebP/AVIF: the first frame only. HEIC/HEIF photos are supported. SVG and PDF are not (use a PDF tool for PDFs). Images must be at public addresses: uploads, base64 data and private links aren't supported.
- **OCR quality** depends on the image. Printed text in clean scans and screenshots reads very well; small, blurry, curved, decorative or low-contrast text reads poorly, and handwriting mostly doesn't read. Pick the right language: accented letters (é, ü, ñ, ß) are read properly only with that language selected. Sideways scans need the `auto_rotate` layout. Watch `meanConfidence`: a low score usually means the text needs checking.
- **What counts as text.** An image is charged only when OCR reads at least one real word: two or more letters or digits with a confidence of 50 or more. Busy photos without text can make OCR guess stray letters from textures; those guesses have low confidence, so such images come back as `no_text` and cost nothing. Any text found is still returned.
- OCR is done with the open-source Tesseract engine (version 5) on Apify's servers; images are deleted when they've been read.

### Responsible use

- It downloads only the addresses you give it, names itself in its User-Agent (`ImageToTextOcrBot`), makes one request at a time to each website with at least a second between requests, and **respects robots.txt** (an address the site's robots.txt disallows is not downloaded, and the row says so).
- Local and internal network addresses are refused, and so are links with a user name or password in them.
- You are responsible for having the right to download and use the images you process, and for any personal data in them. Follow copyright and the privacy laws that apply to you.

This Actor isn't affiliated with or endorsed by any of the websites it downloads from.

### More tools from the same developer

- [PDF Text Extractor: Markdown, Tables & OCR](https://apify.com/private_image_hg9/pdf-text-table-extractor)
- [Website Screenshot & PDF: Full Page, Mobile, Batch URLs](https://apify.com/private_image_hg9/website-screenshot-pdf)

# Actor input Schema

## `imageUrls` (type: `array`):

One public http(s) address of an image per line: PNG, JPEG, WebP, GIF (first frame), BMP, TIFF (every page), HEIC or AVIF. Each image gets one row. Repeats are read once. Redirects are followed, and an image sent with the wrong content type is still read.

## `languages` (type: `array`):

Languages of the text in the images, up to 4. Pick only the ones you need: each extra language makes OCR slower and can add mistakes. English, Spanish, French, German, Italian, Portuguese and Dutch.

## `detail` (type: `string`):

Text: the full text, word and line counts and mean confidence. Lines: also each line with its confidence and box (left, top, width, height in the image's pixels). Words: also each word with its confidence, box and line number.

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

How the text is laid out. Auto suits documents, scans, receipts and screenshots. Auto + turn upright also detects pages that are sideways or upside down (without a rotation tag) and reads them the right way up. Single block suits a cropped paragraph or one text box. Sparse text suits photos, signs, labels, memes and app screens where words are scattered.

## `preprocessing` (type: `string`):

Auto turns the image to grayscale, enlarges small images (under 2,000 pixels on the longest side) so letters are big enough to read, stretches the contrast, and inverts light text on a dark background. Off sends the image as it is (still turned upright, with transparency on white, and scaled down if over 40 megapixels).

## `imageTimeoutSecs` (type: `integer`):

OCR of one image (all pages of a TIFF) stops after this. The row then says so and costs nothing.

## Actor input object example

```json
{
  "imageUrls": [
    "https://upload.wikimedia.org/wikipedia/commons/c/cd/Origin_of_Species_title_page.jpg",
    "https://placehold.co/900x200/png?text=Hello+from+the+OCR+test"
  ],
  "languages": [
    "eng"
  ],
  "detail": "text",
  "pageSegmentation": "auto",
  "preprocessing": "auto",
  "imageTimeoutSecs": 120
}
```

# Actor output Schema

## `results` (type: `string`):

One row per image: the text, confidence, size and format, optional line and word boxes, or why no text was read.

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

Counts for the run: images by status, images charged, average OCR time, and whether the spending cap was reached.

# 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 = {
    "imageUrls": [
        "https://upload.wikimedia.org/wikipedia/commons/c/cd/Origin_of_Species_title_page.jpg",
        "https://placehold.co/900x200/png?text=Hello+from+the+OCR+test"
    ],
    "languages": [
        "eng"
    ]
};

// Run the Actor and wait for it to finish
const run = await client.actor("private_image_hg9/image-to-text-ocr").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 = {
    "imageUrls": [
        "https://upload.wikimedia.org/wikipedia/commons/c/cd/Origin_of_Species_title_page.jpg",
        "https://placehold.co/900x200/png?text=Hello+from+the+OCR+test",
    ],
    "languages": ["eng"],
}

# Run the Actor and wait for it to finish
run = client.actor("private_image_hg9/image-to-text-ocr").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 '{
  "imageUrls": [
    "https://upload.wikimedia.org/wikipedia/commons/c/cd/Origin_of_Species_title_page.jpg",
    "https://placehold.co/900x200/png?text=Hello+from+the+OCR+test"
  ],
  "languages": [
    "eng"
  ]
}' |
apify call private_image_hg9/image-to-text-ocr --silent --output-dataset

```

## MCP server setup

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

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/P8TJzjMBtdcpbpciY/builds/E0AShIKqQGplWA91N/openapi.json
