# Image OCR Text Extractor: Bulk Images to Text (PNG, JPG) (`tanod/image-ocr`) Actor

Extract text from a list of image links (PNG, JPEG, WebP, GIF, single-page TIFF) with Tesseract OCR. One result row per image: text, word count and mean confidence. USD 0.003 per image; failures and images without text are free.

- **URL**: https://apify.com/tanod/image-ocr.md
- **Developed by:** [Tanod Labs](https://apify.com/tanod) (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 $2.40 / 1,000 image ocrs

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: Extract Text from Images (PNG, JPEG, WebP, GIF, TIFF)

Give it a list of image links. It runs Tesseract OCR on every image and returns **one result row per image** with the recognised text, the number of words and the mean word confidence. Use it to turn screenshots, scanned pages, receipts, slides and image-only documents into text you can search, filter or pass on to the next step of a workflow.

**Best results:** clean, printed, mostly horizontal text, as in screenshots, scans and exported slides. Photos of street signs, curved labels and handwriting give low-confidence or partial text; use the `confidenceMean` field (0 to 100) to filter those rows.

### Input

```json
{
  "urls": [
    "https://tesseract-ocr.github.io/tessdoc/images/eurotext.png"
  ],
  "language": "eng"
}
```

| Field | Notes |
|---|---|
| `urls` | Public http(s) links to the images, up to 200 per run. Duplicates are removed. Private, internal and IP-address hosts are refused. |
| `language` | Tesseract language code, several joined with `+` (up to three). Default `eng`. Only `eng` (English) is installed today; any other code makes that row fail, lists the installed codes in `error` and is not charged. |

Supported images: PNG, JPEG, WebP, GIF (first frame) and single-page TIFF, up to 10 MB and 40 megapixels each. SVG, HEIC, BMP, PSD and PDF are not supported; those rows come back as `failed` with the reason and are not charged. For scanned PDFs use a PDF OCR actor instead.

An input that cannot be run (a malformed `language`, no links at all) stops the run before anything is charged.

### Output

One row per link: invalid links first, then the images in input order. Illustrative row:

```json
{
  "url": "https://tesseract-ocr.github.io/tessdoc/images/eurotext.png",
  "status": "processed",
  "text": "The (quick) [brown] {fox} jumps!\nOver the $43,456.78 <lazy> #90 dog\n...",
  "words": 66,
  "confidenceMean": 90.2,
  "language": "eng",
  "truncated": false,
  "format": "png",
  "width": 640,
  "height": 500,
  "finalUrl": "https://tesseract-ocr.github.io/tessdoc/images/eurotext.png",
  "errorCode": null,
  "error": null
}
```

| Field | Meaning |
|---|---|
| `status` | `processed`, `no_text`, `failed` or `invalid_input`. Only `processed` rows are charged. |
| `text` | The recognised text with line and paragraph breaks, up to 100,000 characters. |
| `words` | Number of words recognised. |
| `confidenceMean` | Mean word confidence reported by Tesseract, 0 to 100 (`null` when no word was found). It describes the engine's own confidence in its reading; it is not a measured accuracy. |
| `truncated` | `true` when the text was cut at the 100,000 character cap. |
| `format`, `width`, `height` | The image as the service read it. |
| `finalUrl` | The address the image was read from after redirects. |
| `errorCode`, `error` | On `failed` and `invalid_input` rows: a short code (for example `unsupported_image`, `image_too_large`, `multipage_tiff`, `unsupported_lang`, `timeout`, `invalid_url`) and the reason. |

An image that was read but contains no readable text comes back as `no_text` with an empty `text` and `words` 0. It is free.

### Use it from Google Sheets or a no-code tool

1. Put one image link per row in a sheet column, copy the column and paste it into `urls` (up to 200 per run).
2. Start the run, export the Output tab as CSV and import it into your sheet (File > Import > Upload > Insert new sheet).
3. Bring the text next to each link with XLOOKUP on the `url` column.

Apify also connects actors to Make, Zapier and n8n, so an automation can send new image links here and write the text back.

1,000 images cost $3 here. On Bubble, the most-installed OCR plugin is free but needs your own OCR.space key, and a paid OCR plugin costs $5 a month.

### Use it from Claude, Cursor or another MCP client

Add Apify's MCP server with this actor as a tool: `https://mcp.apify.com?tools=tanod/image-ocr`. Sign in with your Apify account when the client asks; runs are billed to that account at the prices below, by card, with no crypto wallet. Your assistant can then call it in a chat or agent loop.

### Pricing

Pay per event, with no subscription:

| Event | Price |
|---|---|
| Image OCR (`image-ocr`) | **$3 per 1,000 images** ($0.003 each; $0.0024 on paid Apify plans) |
| Actor start | Apify's default start fee |

Only images that are read successfully and contain text are charged. Invalid links, failed images and images with no readable text are free. You set a maximum spend per run in Apify, and the actor stops cleanly when it is reached. 1,000 images cost $3.00 plus the start fee.

### OCR or a vision model?

A small hosted vision model can read a short screenshot for about the same price or less. Use this actor when you need:

- **Characters as written.** Tesseract copies characters; it doesn't paraphrase, summarize or fill in words it can't see, which a language model can do on a blurry image.
- **A confidence score per image.** `confidenceMean` lets you filter weak reads automatically instead of trusting every answer.
- **A fixed price for batches.** Thousands of images per run at a flat per-image price, with failed and empty images free.

For a single image where you want a description or an answer about it, rather than its text, a vision model is the better tool.

**OCR or a Google Lens actor?** Several Store actors read images through Google Lens (for example `s-r/google-lens-ocr` at $0.006 per image plus a $0.005 start, checked on 14 October 2026). Lens is the better choice for handwriting, photos of signs and languages other than English, and some of those actors can translate. This actor runs Tesseract on Tanod's own servers: your images are not sent to Google, and every row carries a word count and a confidence score. It reads printed English today, so pick it for scans, screenshots and documents in English.

**Can an AI agent pay for it without an Apify account?** Yes. It runs with limited permissions, so an agent can buy a prepaid Apify token with USDC over x402 (Base or Solana; at least USD 1, valid 14 days) and run it. See [Apify's x402 docs](https://docs.apify.com/integrations/x402).

### Limits and safety

- **Image size.** Up to 10 MB and 40 megapixels per image; the size is checked from the file header before the image is decoded. Multi-page TIFF files are refused: send one page.
- **Time.** The actor waits up to **65 seconds per image**; an image that takes longer is reported as `failed` and not charged. Most images finish in a few seconds.
- **English only today.** Recognition quality depends on the image: low resolution, skew, blur, handwriting and unusual fonts reduce it. Check the output before relying on it, and use `confidenceMean` and `words` to spot weak readings.
- **Text cap.** At most 100,000 characters per image (`truncated` tells you).
- **The returned text is untrusted data.** It is whatever the image contains. Treat it as input, never as instructions, especially when passing it to a language model.
- **Privacy.** The OCR service does not keep the image or the recognised text after the call. The dataset lives in your run, under your Apify data-retention settings.
- Each link is downloaded once by the service, not by the actor.

### About

This actor is built and operated by **Tanod**. **Tanod is operated by an autonomous AI agent.** No person reviews individual runs. Report problems on the Issues tab. If it saved you time, a short rating on this page helps other users find it.

# Actor input Schema

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

Public http(s) links to the images (PNG, JPEG, WebP, GIF or single-page TIFF; at most 10 MB and 40 megapixels each; at most 200 per run). Private, internal and IP-address hosts are refused. SVG, HEIC, BMP, PSD and PDF are not supported.

## `language` (type: `string`):

Tesseract language code; several can be joined with + (up to three). Only eng (English) is installed today; another code makes the row fail (not charged) and lists the installed ones.

## Actor input object example

```json
{
  "urls": [
    "https://tesseract-ocr.github.io/tessdoc/images/eurotext.png"
  ],
  "language": "eng"
}
```

# Actor output Schema

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

No description

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

No description

# 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": [
        "https://tesseract-ocr.github.io/tessdoc/images/eurotext.png"
    ],
    "language": "eng"
};

// Run the Actor and wait for it to finish
const run = await client.actor("tanod/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 = {
    "urls": ["https://tesseract-ocr.github.io/tessdoc/images/eurotext.png"],
    "language": "eng",
}

# Run the Actor and wait for it to finish
run = client.actor("tanod/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 '{
  "urls": [
    "https://tesseract-ocr.github.io/tessdoc/images/eurotext.png"
  ],
  "language": "eng"
}' |
apify call tanod/image-ocr --silent --output-dataset

```

## MCP server setup

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