# Image OCR Extractor 🖼️ (image to text extractor) (`tagadanar/image-ocr-extractor`) Actor

OCR for images: image to text with line and word boxes, confidence and orientation. PNG, JPG, WebP, GIF, BMP, TIFF. Clean-up for low-res photos, 7 languages. No API key.

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

## Pricing

from $4.20 / 1,000 image reads

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

## Image OCR Extractor: image to text with line and word boxes

Give it image links and get back the text in them, with a confidence score, the position of every line (and optionally every word), the image size and the orientation that was applied. It reads PNG, JPG, WebP, GIF, BMP and TIFF, cleans up low-resolution and low-contrast photos on its own, and turns sideways or upside-down images upright. OCR runs inside the actor: no API key, no external OCR or AI service.

$6 per 1,000 images, platform usage included. Images with no readable text and links that are not images cost nothing.

### What you get

One row per image:

| Field | Description |
| --- | --- |
| `url` | The image link |
| `text` | The recognized text, lines separated by new lines, blocks by a blank line |
| `confidence` | Average OCR confidence from 0 to 100 |
| `wordCount`, `lineCount` | Size of what was read |
| `lines` | With the "lines" or "words" output: every line with `text`, `confidence` and a `bbox` (`x0`, `y0`, `x1`, `y1`) |
| `words` | With the "words" output: every word with `text`, `confidence` and `bbox` |
| `width`, `height`, `format` | Size in pixels (of the upright image) and the file format |
| `orientationDegrees` | How far the image was turned to read it (0, 90, 180 or 270) |
| `preprocessing`, `languages` | What was used |
| `fileSizeBytes`, `capturedAt` | File size and run time |
| `status`, `errorCode`, `errorMessage` | `ok`, or an error row (see below) |

Box coordinates are in pixels of the upright original image, so you can draw them straight on the picture. EXIF rotation from phones is applied first.

#### Example row (real, from a run on 2026-10-16, shortened)

```json
{
  "url": "https://raw.githubusercontent.com/naptha/tesseract.js/master/tests/assets/images/testocr.png",
  "status": "ok",
  "text": "This is a lot of 12 point text to test the\nocr code and see if it works on all types\nof file format.\n\nThe quick brown do ...",
  "confidence": 95,
  "wordCount": 60,
  "lineCount": 8,
  "languages": ["eng"],
  "format": "png",
  "width": 640,
  "height": 480,
  "orientationDegrees": 0,
  "preprocessing": "auto",
  "lines": [
    { "text": "This is a lot of 12 point text to test the", "confidence": 95, "bbox": { "x0": 36, "y0": 92, "x1": 580, "y1": 122 } }
  ]
}
```

### Settings that change the result

- **Output detail.** Text only, text with line boxes (default), or text with line and word boxes.
- **Languages.** English, French, German, Spanish, Italian, Portuguese and Dutch. Pick up to two for mixed text.
- **What the image contains.** Page or screenshot (automatic layout), one block, one line, or scattered text such as signs, memes and app screenshots. Telling it saves a failed read on cropped labels and codes.
- **Image clean-up.** Auto (default) converts to grayscale, raises contrast, enlarges small images up to three times, and retries a weak read on a hard black-and-white copy. You can also force grayscale, a black and white threshold, or no changes at all.
- **Fix sideways and upside-down images.** On by default. When a read is weak or the text runs vertically, the orientation is detected and the image is read again upright.

### Errors are rows, not crashes

A link that cannot be read produces an error row (`status: "error"`) and costs nothing:

| `errorCode` | Meaning |
| --- | --- |
| `not-an-image` | The link returned a web page or an unsupported file (the content type is named) |
| `looks-like-pdf` | The link is a PDF. Use [PDF Text Extractor](https://apify.com/tagadanar/pdf-text-extractor) for those |
| `no-text` | A readable image where OCR found no text |
| `not-found` | HTTP 404 or 410 |
| `too-large` | Over the 25 MB file limit |
| `corrupt` | The image is damaged or larger than 80 megapixels |
| `fetch-failed` | The server refused or timed out on every attempt |

The run status message summarizes the same, and a run where every link failed ends as failed instead of pretending to succeed. A low-confidence read (under 50) is delivered with a note in the status.

### Limits

- 25 MB per image, 1,000 images per run. Images over 6,000 pixels on the long side are shrunk for reading, boxes still come back in original pixels.
- Animated GIFs and multi-page TIFFs use their first frame. For multi-page documents use PDFs.
- Printed text only. Handwriting and very stylized fonts read poorly.
- Each image is downloaded directly first. If the server refuses, a datacenter proxy is tried. Files behind a login are not supported.
- Speed at the default memory: about a second for a small image, 5 to 10 seconds for a full dense page, more for photos that need turning or a second read.

### Input examples

Text and line boxes for two screenshots:

```json
{
  "urls": [
    { "url": "https://raw.githubusercontent.com/naptha/tesseract.js/master/tests/assets/images/testocr.png" },
    { "url": "https://raw.githubusercontent.com/tesseract-ocr/test/main/testing/phototest.tif" }
  ],
  "output": "lines"
}
```

Word boxes for a French and English scan, no clean-up:

```json
{
  "urls": [{ "url": "https://example.com/menu.jpg" }],
  "output": "words",
  "languages": ["fra", "eng"],
  "preprocessing": "none"
}
```

A cropped single line, such as a label or a license plate photo:

```json
{
  "urls": [{ "url": "https://example.com/label-crop.png" }],
  "imageType": "line",
  "output": "text"
}
```

### Who uses this

- **Automation and data teams.** Turn screenshots, receipts and photographed forms into text for parsers and spreadsheets.
- **AI and agent builders.** Give a text-only model the words in an image, with positions when layout matters.
- **QA and support teams.** Read error screenshots and UI captures at scale.
- **Archivists and researchers.** Digitize scanned pages and photos of printed text.

### FAQ

**Can I get the position of each word?** Yes. Pick the "words" output and every word has a bounding box and a confidence.

**Does it work on photos taken sideways?** Yes. EXIF rotation is applied and a sideways or upside-down photo is detected and read upright. The turn is reported in `orientationDegrees`.

**What about low-resolution or blurry images?** Auto clean-up enlarges small images and retries weak reads on a high-contrast copy. Very blurry text still reads poorly.

**Which image formats work?** PNG, JPG, WebP, GIF, BMP and TIFF.

**Does it need an API key?** No. OCR runs inside the actor.

**What about PDFs?** Use [PDF Text Extractor](https://apify.com/tagadanar/pdf-text-extractor), which also OCRs scanned pages.

### Keywords

image ocr, image to text, ocr extractor, text extractor, extract text from image, screenshot to text, jpg to text, png to text, ocr bounding boxes, scanned image to text.

# Changelog

This Actor's version history is a separate document: https://apify.com/tagadanar/image-ocr-extractor/changelog.md

# Actor input Schema

## `urls` (type: `array`):

Links to images, one per line (or upload a list). PNG, JPG, WebP, GIF, BMP and TIFF work. Any public https link works, including files stored in an Apify key-value store. Animated GIFs and multi-page TIFFs use their first frame.

## `output` (type: `string`):

Text: the recognized text and its confidence. Lines: also every line with its box and confidence. Words: also every word with its box and confidence. Boxes are in pixels of the upright original image.

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

Languages printed in the images. Pick up to 2 for mixed text; each extra language slows OCR.

## `imageType` (type: `string`):

Helps the reader pick the right layout. Document suits scans, screenshots and photos of pages with columns or paragraphs. Use a single block for one paragraph, a single line for a cropped line (captcha-free codes, labels, plates), or scattered text for signs, memes and UI screenshots.

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

Auto converts to grayscale, boosts contrast, enlarges small images and retries a weak read with a hard black-and-white copy. Pick another option to force one treatment or none.

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

When a read is weak or the text runs vertically, detect the orientation and read the image again turned upright. The turn applied is reported as orientationDegrees.

## Actor input object example

```json
{
  "urls": [
    {
      "url": "https://raw.githubusercontent.com/naptha/tesseract.js/master/tests/assets/images/testocr.png"
    },
    {
      "url": "https://raw.githubusercontent.com/tesseract-ocr/test/main/testing/phototest.tif"
    }
  ],
  "output": "lines",
  "languages": [
    "eng"
  ],
  "imageType": "document",
  "preprocessing": "auto",
  "autoRotate": true
}
```

# Actor output Schema

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

One item per image in the default dataset.

# 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 = {
    "urls": [
        {
            "url": "https://raw.githubusercontent.com/naptha/tesseract.js/master/tests/assets/images/testocr.png"
        },
        {
            "url": "https://raw.githubusercontent.com/tesseract-ocr/test/main/testing/phototest.tif"
        }
    ]
};

// Run the Actor and wait for it to finish
const run = await client.actor("tagadanar/image-ocr-extractor").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 = { "urls": [
        { "url": "https://raw.githubusercontent.com/naptha/tesseract.js/master/tests/assets/images/testocr.png" },
        { "url": "https://raw.githubusercontent.com/tesseract-ocr/test/main/testing/phototest.tif" },
    ] }

# Run the Actor and wait for it to finish
run = client.actor("tagadanar/image-ocr-extractor").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 '{
  "urls": [
    {
      "url": "https://raw.githubusercontent.com/naptha/tesseract.js/master/tests/assets/images/testocr.png"
    },
    {
      "url": "https://raw.githubusercontent.com/tesseract-ocr/test/main/testing/phototest.tif"
    }
  ]
}' |
apify call tagadanar/image-ocr-extractor --silent --output-dataset

```

## MCP server setup

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

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/Th9V5Ite6DIGausAM/builds/tjBkr4lXSrvCyypA3/openapi.json
