# Image to Text — OCR for Screenshots, Scans and Photos (`lergassy/image-to-text`) Actor

\[$0.004/image] Convert images to text with OCR: PNG, JPG, WEBP, TIFF, HEIC, screenshots, scans and scanned PDFs in 19 languages. Full text, confidence score and optional word boxes. No API key, no fee per run.

- **URL**: https://apify.com/lergassy/image-to-text.md
- **Developed by:** [Matvey](https://apify.com/lergassy) (community)
- **Categories:** AI, Developer tools, Agents
- **Stats:** 2 total users, 0 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $2.10 / 1,000 image or page read with 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

Convert **image to text** with OCR: screenshots, scanned documents, receipts, PNG, JPG, WEBP, TIFF, HEIC and scanned PDFs, in 19 languages. Every image comes back as plain text with an **engine confidence score**, and every word can come back with its position on the image. **$0.004 per image**, no fee per run, no API key, no external OCR service.

It is the [OCR Text Extractor](https://apify.com/lergassy/ocr-text-extractor) engine with the form set up for images; anything that works there works here.

### What it is for

| What you give it | What you get back |
| --- | --- |
| A screenshot of a web page, app or chat | The text on it, line by line |
| A scanned letter, form or invoice | Recognised text with a confidence score |
| A batch of hundreds of image links | One row per image, same fields for all of them |
| A scanned PDF | Text page by page, pages that already contain text copied for free |
| Base64 data from your code or an AI agent | The same row, nothing to host |

An empty call (`{}`) reads a sample invoice image, so you can see the output shape before you send your own files.

### What data does it return?

| Field | Type | Example |
| --- | --- | --- |
| `source` | string | `https://example.com/receipt.jpg` |
| `fileName` | string | `receipt.jpg` |
| `format` | string | `image` or `pdf` |
| `language` | string | `eng` |
| `text` | string | `INVOICE 2026-114\nMalina Data…` |
| `wordCount` / `charCount` | integer | `26` / `177` |
| `confidence` | number | `93.7` (average, 0–100) |
| `pages` | array | `[{"number": 1, "text": "…", "confidence": 93.7, "source": "ocr"}]` |
| `words` | array | `[{"text": "INVOICE", "confidence": 95, "left": 124, "top": 168, "width": 174, "height": 32}]` (when switched on) |
| `status` / `errorCode` / `errorMessage` | string | `ok`, or why a file failed |
| `extractedAt` | string | `2026-10-06T02:25:40+00:00` |

### How much does it cost?

| Event | Price | When it is charged |
| --- | --- | --- |
| Image or page read with OCR | $0.003 | Per image, or per scanned PDF page, that returned text |
| File processed | $0.001 | Once per file that returned text |

So **one image is $0.004** and 1,000 images are $4. There is no fee per run. Files that fail, or in which no text was found, come back as `error` rows and are **never charged**. PDF pages that already have a text layer are copied, not OCR-ed, and are not charged as OCR pages.

| Job | Cost |
| --- | --- |
| 1 screenshot | $0.004 |
| 1,000 product photos or receipts | $4.00 |
| 100 scanned PDFs, 10 pages each | $3.10 |

The Apify Free plan includes $5 of monthly usage — about **1,250 images**.

### How to turn an image into text

1. Click **Try for free** and sign in to Apify.
2. Paste image links into **Image URLs**, or use **Upload a file**.
3. Pick the **OCR language** — the right language matters more than any other setting.
4. Press **Start**, then read the **Output** tab or export JSON, CSV or Excel.

### ⬇️ Input

```json
{
  "urls": [
    "https://raw.githubusercontent.com/lergassy/apify-actor-assets/main/document-text-extractor/sample-scan.png"
  ],
  "language": "eng",
  "includeWordBoxes": false
}
```

| Field | What it does |
| --- | --- |
| `urls` | Direct links to images or PDFs. The link must open the file itself, not a gallery page |
| `file` | Upload one file from your computer |
| `base64Files` | Base64 strings or `{"fileName", "data"}` objects, for API and agent calls |
| `language` | One of 19 languages: English, German, French, Spanish, Portuguese, Italian, Dutch, Polish, Russian, Ukrainian, Turkish, Indonesian, Vietnamese, Arabic, Hindi, Chinese (simplified and traditional), Japanese, Korean |
| `autoDetectLanguage` | Inspect the image first and switch language when the script is clearly Cyrillic, Arabic, CJK or Devanagari. Works on documents; on street photos it can guess wrong, so set the language yourself when you know it |
| `includePages` | Per-page text and confidence (on by default) |
| `includeWordBoxes` | Every word with its confidence and pixel box |
| `minWordConfidence` | Drop words the engine is less sure about than this (0–100). 60 removes most noise from phone photos |
| `useExistingTextLayer` | For PDFs: copy text that is already there instead of OCR-ing it (on by default) |
| `pageRange`, `maxPagesPerFile` | Which PDF pages to read, and a safety cap |
| `maxConcurrency`, `maxFileSizeMb`, `timeoutPerFileSecs` | Advanced limits |

If a host refuses the download (rate limit, block), the Actor retries with a pause and then through a residential proxy before giving up on the file. You are not charged for that.

### ⬆️ Output

```json
{
  "source": "https://…/sample-scan.png",
  "format": "image",
  "language": "eng",
  "text": "INVOICE 2026-114\nMalina Data\nJalan Raya Uluwatu 88, Jimbaran, Bali\nConsulting services 1,250.00 USD\nDocument processing 340.00 USD\nTotal due: 1,590.00 USD\nPayment terms: 30 days",
  "wordCount": 26,
  "confidence": 93.7,
  "pages": [{ "number": 1, "text": "INVOICE 2026-114…", "confidence": 93.7, "wordCount": 26, "source": "ocr" }],
  "status": "ok"
}
```

#### Error rows

| `errorCode` | Meaning |
| --- | --- |
| `http-error` / `network-error` / `timeout` | The file could not be downloaded, even after retries |
| `too-large` | Above the size limit (50 MB by default, up to 200 MB) |
| `unsupported-format` | Not an image or a PDF — for example a link to a web page |
| `corrupt-file` | The file is damaged |
| `no-text-found` | Nothing readable — usually the wrong language, a photo with very little text, or a very small image |

### Limitations, stated plainly

- **Best on printed text**: screenshots, scans, typed letters, invoices. Screenshots and clean scans typically read at 85–95% confidence.
- **Phone photos of receipts, signs and labels** read noticeably worse (40–70% confidence in our tests), and a photo where the text is a small part of the scene may return nothing. Google Lens–based Actors handle such photos better; this one is cheaper and tells you how sure it is.
- **Handwriting** is not read reliably.
- One very dense page (an old newspaper page with ~2,000 words) can take over a minute.
- Recognition runs inside the Actor (Tesseract), so there is no external quota — and no cloud AI either.

### Use cases

- **Screenshots to text** — pull text out of app screens, chats, dashboards or error messages.
- **Digitising paperwork** — invoices, permits, letters and records that only exist as scans, with a confidence score that tells you which need a human.
- **Feeding images to an LLM or a search index** — pass text instead of pictures, with noisy words filtered out.
- **Document parsers** — word boxes let you read a field by where it sits on the page.

### 🤖 For AI agents and LLM apps

```json
{ "urls": ["https://example.com/screenshot.png"], "language": "eng" }
```

- One row per file; `status` is `ok` or `error`, no log parsing needed.
- `confidence` gives the agent a reason to ask for a better image instead of acting on noise.
- Files can be passed as base64.
- An empty call returns a sample result instead of an error.

### Use via API

```bash
curl -X POST "https://api.apify.com/v2/acts/lergassy~image-to-text/run-sync-get-dataset-items?token=YOUR_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"urls": ["https://example.com/scan.png"], "language": "eng"}'
```

```python
from apify_client import ApifyClient
items = ApifyClient("YOUR_TOKEN").actor("lergassy/image-to-text").call(
    run_input={"urls": ["https://example.com/scan.png"]}
).iterate_items()
```

Works the same from JavaScript, n8n, Make, Zapier and the Apify MCP server.

### ❓ FAQ

#### Do I need an API key?

No. The OCR engine runs inside the Actor.

#### Which image formats work?

PNG, JPG, WEBP, TIFF, BMP, GIF and HEIC (iPhone photos), plus PDF.

#### What is the difference from OCR Text Extractor?

None in the engine. [OCR Text Extractor](https://apify.com/lergassy/ocr-text-extractor) is the main Actor, framed around scanned PDFs; this one is set up for images.

#### Can it read a PDF that already has text?

Yes, but [Document Text Extractor](https://apify.com/lergassy/document-text-extractor) is the better tool for that: it returns Markdown, tables and RAG chunks.

### You might also like

| Actor | What it does |
| --- | --- |
| [OCR Text Extractor](https://apify.com/lergassy/ocr-text-extractor) | The main Actor: the same engine, framed around scanned PDFs |
| [PDF Text Extractor](https://apify.com/lergassy/pdf-text-extractor) | Text, Markdown and tables from PDF files |
| [Document Text Extractor](https://apify.com/lergassy/document-text-extractor) | PDF, Word, Excel and PowerPoint to Markdown and RAG chunks |
| [Speech to Text](https://apify.com/lergassy/speech-to-text) | Audio and video to a timed transcript |

### Also known as

Image to text converter, OCR API, picture to text, photo to text, screenshot to text, extract text from image, JPG to text, PNG to text.

# Actor input Schema

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

Direct links to the images you want to turn into text: PNG, JPG, WEBP, TIFF, BMP or GIF. Scanned PDFs work too — every page is read with OCR. The link must open the file itself, not a gallery or viewer page.

## `file` (type: `string`):

Upload one image or PDF from your computer instead of giving a URL.

## `base64Files` (type: `array`):

Base64-encoded images or PDFs for API and agent calls. Each entry is a plain base64 string (a data-URI prefix is allowed) or an object <code>{"fileName": "scan.png", "data": "…"}</code>.

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

Language of the text in the scan. Picking the right one is the single biggest factor in accuracy.

## `autoDetectLanguage` (type: `boolean`):

Look at the page first and switch language when the script is clearly Cyrillic, Arabic, Chinese, Japanese, Korean or Devanagari. Adds a moment per file.

## `includePages` (type: `boolean`):

Return each page separately with its own text and confidence score, alongside the full text.

## `includeWordBoxes` (type: `boolean`):

Return every recognised word with its confidence and its box on the page. Use it to highlight text or to build a document parser.

## `minWordConfidence` (type: `integer`):

Drop words the engine is less sure about than this, from 0 to 100. Raise it to cut noise out of poor scans.

## `useExistingTextLayer` (type: `boolean`):

When a PDF page already contains text, copy it instead of running OCR. Faster, cheaper and more accurate. Switch off to force OCR everywhere.

## `pageRange` (type: `string`):

Read only these PDF pages, for example <code>1-5</code>, <code>8</code> or <code>12-</code> (page 12 to the end).

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

Safety cap so a long scan cannot run up an unexpected bill.

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

How many files to read at the same time.

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

Files larger than this are skipped with an error row instead of being downloaded.

## `timeoutPerFileSecs` (type: `integer`):

How long to wait for one file to download before giving up on it.

## Actor input object example

```json
{
  "urls": [
    "https://raw.githubusercontent.com/lergassy/apify-actor-assets/main/document-text-extractor/sample-scan.png"
  ],
  "language": "eng",
  "autoDetectLanguage": false,
  "includePages": true,
  "includeWordBoxes": false,
  "minWordConfidence": 0,
  "useExistingTextLayer": true,
  "maxPagesPerFile": 50,
  "maxConcurrency": 3,
  "maxFileSizeMb": 50,
  "timeoutPerFileSecs": 120
}
```

# Actor output Schema

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

Dataset with one row per image or PDF.

## `resultsInConsole` (type: `string`):

Browse the OCR results in the Apify Console.

# 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://raw.githubusercontent.com/lergassy/apify-actor-assets/main/document-text-extractor/sample-scan.png"
    ]
};

// Run the Actor and wait for it to finish
const run = await client.actor("lergassy/image-to-text").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://raw.githubusercontent.com/lergassy/apify-actor-assets/main/document-text-extractor/sample-scan.png"] }

# Run the Actor and wait for it to finish
run = client.actor("lergassy/image-to-text").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://raw.githubusercontent.com/lergassy/apify-actor-assets/main/document-text-extractor/sample-scan.png"
  ]
}' |
apify call lergassy/image-to-text --silent --output-dataset

```

## MCP server setup

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

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/DtLHLoRIy0N2dyXOL/builds/yxtNduF9BCyQr1i5b/openapi.json
