# Image to Text OCR – Extract Text from Photos & Scans (`pinkish_armada/image-ocr`) Actor

Extract text from images (JPG, PNG, WebP, HEIC, TIFF, GIF) with Tesseract OCR in 27 languages: auto-rotation, lines and words with confidence and bounding boxes. $3 per 1,000 images.

- **URL**: https://apify.com/pinkish_armada/image-ocr.md
- **Developed by:** [Phuc Tiet](https://apify.com/pinkish_armada) (community)
- **Categories:** AI, Developer tools
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $3.00 / 1,000 processed images

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 – Extract Text from Photos, Scans & Screenshots

Extract text from **images in bulk** with the open-source **Tesseract OCR** engine. Give it image URLs and get clean text back, with **confidence scores**, optional **line and word bounding boxes**, and automatic **rotation fixing**. OCR runs inside the Actor, so images are never sent to a third-party API.

- 🖼️ **Formats:** JPEG, PNG, WEBP, **multi-page TIFF**, BMP, GIF, **HEIC/HEIF (iPhone photos)**, AVIF.
- 🌍 **27 languages**, mixable (up to 4 at once): English, German, French, Spanish, Italian, Portuguese, Dutch, Polish, Czech, Swedish, Danish, Norwegian, Finnish, Turkish, Russian, Ukrainian, Greek, Vietnamese, Indonesian, **Japanese, Chinese (Simplified/Traditional), Korean, Arabic, Hindi, Thai, Hebrew**.
- 🔄 **Auto-rotation** of sideways or upside-down scans, EXIF orientation for phone photos, automatic upscaling of small screenshots.
- 📐 **Layout modes** for documents, single text blocks (receipts, labels) and sparse text (signs, posters, product photos).
- 🤖 **Built for automation and AI agents.** Structured JSON output, per-image error codes, and you only pay for images that were processed.
- 💸 **$0.003 per image** ($3 per 1,000).

### Use cases

- Digitise scanned letters, forms, archives and typewritten documents.
- Pull text out of screenshots, slides, memes and social-media images for search, moderation or RAG.
- Read product labels, packaging, shelf tags and street signs from photos.
- Pre-process receipts and invoices before parsing with an LLM.
- Make image libraries searchable (alt-text and indexing).

### Input

```json
{
  "imageUrls": [
    "https://upload.wikimedia.org/wikipedia/commons/e/e2/Typewritten_letter_from_Dr_Claude_H_Organ_Jr_MD_FACS_to_Dr_Leonidas_Berry_dated_October_5_1965.jpg",
    "https://upload.wikimedia.org/wikipedia/commons/a/a5/Street_sign%2C_Primrose_Street_-_geograph.org.uk_-_6556772.jpg"
  ],
  "languages": ["eng"],
  "pageMode": "auto"
}
```

| Field | Default | Description |
|---|---|---|
| `imageUrls` | – | Image URLs (required), up to 10,000 per run |
| `languages` | `["eng"]` | Up to 4 language codes (`eng`, `deu`, `jpn`, `chi_sim`... or `en`, `de`, `ja`) |
| `pageMode` | `auto` | `auto`, `single-block` (receipts/labels), `sparse` (signs/photos) |
| `autoRotate` | true | Fix sideways/upside-down text |
| `includeLines` | false | Lines with bounding boxes and confidence |
| `includeWords` | false | Words with bounding boxes and confidence |
| `maxPagesPerFile` | 20 | Pages read from multi-page TIFFs |
| `maxConcurrency` | 2 | Images processed in parallel |

### Output

```json
{
  "url": "https://upload.wikimedia.org/.../Street_sign%2C_Primrose_Street_-_geograph.org.uk_-_6556772.jpg",
  "status": "ok",
  "format": "jpeg",
  "width": 640,
  "height": 480,
  "pageCount": 1,
  "pagesProcessed": 1,
  "languages": "eng",
  "confidence": 92.7,
  "rotated": 0,
  "wordCount": 3,
  "text": "PRIMROSE\n\nSTREET EC2",
  "warnings": []
}
```

- Multi-page TIFFs also get a `pages` array.
- `includeLines`/`includeWords` add `lines`/`words` with `box: [x, y, width, height]`.
- Errors (`HTTP_404`, `NOT_AN_IMAGE`, `UNSUPPORTED_FORMAT`, `TOO_LARGE`, `CORRUPT_FILE`...) are reported per image and **not charged**.
- PDFs are rejected with a pointer to our [PDF to Markdown](https://apify.com/pinkish_armada/pdf-to-markdown) Actor.

### Pricing

Pay per event, plus a tiny Actor start fee ($0.00005 per GB of memory):

- **Image processed:** **$0.003** per image (each page of a multi-page TIFF counts as one image). That's **$3 per 1,000 images**, with compute included.
- Failed downloads, non-images, PDFs and oversized files are **free**.
- Images with no recognisable text are charged, because the OCR work was done (they return `text: ""` and a warning).

Popular OCR Actors on the Store charge around $5 per 1,000 images.

### Accuracy (honest)

- Tesseract is excellent on **printed text**: documents, screenshots, typewritten pages, signs with clear fonts (typically 85–95% confidence).
- It is **weak on handwriting**, very stylised fonts, heavy perspective, low-light photos and text over busy backgrounds. Check the `confidence` field: below ~60 usually means poor results.
- For best results use images at least ~1,000 px wide, choose the correct language(s), and use `sparse` mode for photos with scattered text.
- Tables come out as text lines (no table structure). For layout-heavy PDFs use a PDF converter instead.

### FAQ

**Are my images stored or sent elsewhere?** No. They are downloaded into the run container, OCR'd locally and discarded. Only the extracted text is saved to your dataset.

**Can I OCR images behind a login?** No. URLs must be publicly downloadable (or pre-signed links such as S3/GCS signed URLs).

**How fast is it?** About 1–3 seconds per typical image per CPU core. Raise memory (4 GB = 1 core) and `maxConcurrency` together for big batches.

# Actor input Schema

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

Direct links to images: JPEG, PNG, WEBP, TIFF (all pages), BMP, GIF (first frame), HEIC/HEIF, AVIF. Up to 10,000 per run.

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

Language(s) of the text, up to 4. Codes: eng, deu, fra, spa, ita, por, nld, pol, ces, swe, dan, nor, fin, tur, rus, ukr, ell, vie, ind, jpn, chi_sim, chi_tra, kor, ara, hin, tha, heb (ISO codes like en, de, ja also work).

## `pageMode` (type: `string`):

<b>auto</b>: documents, letters, screenshots. <b>single-block</b>: one uniform block of text (receipts, labels). <b>sparse</b>: scattered text such as signs, posters, product photos.

## `autoRotate` (type: `boolean`):

Detect sideways or upside-down text and rotate before OCR (EXIF orientation from phone photos is always applied).

## `includeLines` (type: `boolean`):

Add each text line with its bounding box \[x, y, width, height] and confidence.

## `includeWords` (type: `boolean`):

Add every word with its bounding box and confidence (large output).

## `maxPagesPerFile` (type: `integer`):

Each page is billed as one image.

## `maxConcurrency` (type: `integer`):

Images processed at once. Raise together with memory (each 4 GB adds one CPU core).

## `maxFileSizeMb` (type: `integer`):

Larger files are skipped with TOO_LARGE (not charged).

## `requestTimeoutSecs` (type: `integer`):

Network timeout for each download.

## Actor input object example

```json
{
  "imageUrls": [
    "https://upload.wikimedia.org/wikipedia/commons/e/e2/Typewritten_letter_from_Dr_Claude_H_Organ_Jr_MD_FACS_to_Dr_Leonidas_Berry_dated_October_5_1965.jpg"
  ],
  "languages": [
    "eng"
  ],
  "pageMode": "auto",
  "autoRotate": true,
  "includeLines": false,
  "includeWords": false,
  "maxPagesPerFile": 20,
  "maxConcurrency": 2,
  "maxFileSizeMb": 30,
  "requestTimeoutSecs": 60
}
```

# Actor output Schema

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

Recognised text and metadata per image.

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

Images processed, failed and pages charged.

# 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/e/e2/Typewritten_letter_from_Dr_Claude_H_Organ_Jr_MD_FACS_to_Dr_Leonidas_Berry_dated_October_5_1965.jpg"
    ]
};

// Run the Actor and wait for it to finish
const run = await client.actor("pinkish_armada/image-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/e/e2/Typewritten_letter_from_Dr_Claude_H_Organ_Jr_MD_FACS_to_Dr_Leonidas_Berry_dated_October_5_1965.jpg"] }

# Run the Actor and wait for it to finish
run = client.actor("pinkish_armada/image-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/e/e2/Typewritten_letter_from_Dr_Claude_H_Organ_Jr_MD_FACS_to_Dr_Leonidas_Berry_dated_October_5_1965.jpg"
  ]
}' |
apify call pinkish_armada/image-ocr --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,pinkish_armada/image-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/mDUEaiDmRwqhhNfhp/builds/OJRU2LbVQwP3A5STn/openapi.json
