# OCR — Scanned PDF & Image to Text (Tesseract, 29 Languages) (`actor-forge/ocr-to-text`) Actor

Extract text from scanned PDFs and images (PNG, JPEG, TIFF, WebP, GIF, BMP) with Tesseract 5 OCR in 29 languages. PDF pages that already have text are read directly at a tenth of the price. Per-page text and confidence, optional word bounding boxes. $3 per 1,000 OCR pages.

- **URL**: https://apify.com/actor-forge/ocr-to-text.md
- **Developed by:** [ActorForge](https://apify.com/actor-forge) (community)
- **Categories:** AI, Developer tools, Integrations
- **Stats:** 1 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $3.00 / 1,000 page ocrs

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

## OCR — Scanned PDF & Image to Text (Tesseract, 29 Languages)

Extract text from scanned PDFs and images (PNG, JPEG, TIFF, WebP, GIF, BMP) with Tesseract 5 OCR in 29 languages. PDF pages that already have text are read directly at a tenth of the price. Per-page text and confidence, optional word bounding boxes. $3 per 1,000 OCR pages.

**Extract text from scanned PDFs and images with OCR.** Paste links to scanned documents, photos of pages, screenshots, faxes or receipts (**PDF, PNG, JPEG, TIFF, WebP, GIF, BMP, JPEG 2000**) and get the text back, page by page, with an **OCR confidence score** for every OCR'd page. Powered by **Tesseract 5** with its LSTM neural-network models in **29 languages** (English, German, French, Spanish, Italian, Portuguese, Dutch, Polish, Nordic languages, Czech, Slovak, Hungarian, Romanian, Turkish, Russian, Ukrainian, Arabic, Hebrew, Hindi, Chinese, Japanese, Korean, Vietnamese, Indonesian, Thai), up to 4 at once. **Smart PDF mode** reads pages that already contain text straight from the text layer (exact, and a tenth of the price) and only OCRs the scanned pages, so mixed PDFs cost what they should. Optional **word-level bounding boxes** with per-word confidence for redaction, highlighting and form extraction. Use it to make scanned archives searchable, feed **RAG pipelines and LLMs** with paper documents, digitise invoices, contracts and letters, or give **AI agents** a reliable OCR tool. **Simple pricing: $3 per 1,000 OCR pages** (scanned-PDF OCR elsewhere costs $15 per 1,000) and **$0.30 per 1,000 text-layer pages**, with no compute bill on top. Failed downloads, unreadable files and blank pages are never charged.

### What data does it return?

Every run outputs clean, schema-validated rows like these:

| url | fileType | pagesOcr | confidence | wordCount | text | pagesTextLayer |
| --- | --- | --- | --- | --- | --- | --- |
| https://raw.githubusercontent.com/ocrmypdf/OCRmyPDF/main/tests/resources/linn.pdf | pdf | 1 | 95.5 | 728 | The LinnSequencer\n32 Track MIDI Sequence Recorder\n\nThe LinnSequencer is a state-of-the-art composition and performance tool… |  |
| https://raw.githubusercontent.com/tesseract-ocr/test/main/testing/phototest.tif | tiff | 1 | 96.3 | 60 | This is a lot of 12 point text to test the\nocr code and see if it works on all types\nof file format. |  |
| https://arxiv.org/pdf/1706.03762 | pdf | 0 |  | 6457 | Provided proper attribution is provided, Google hereby grants permission to reproduce the tables and figures… | 15 |

### How much does it cost?

Transparent pay-per-event pricing — you only pay for what you get, and the
actor **always respects your run budget**: set a maximum total charge and it
stops cleanly at the cap instead of overrunning.

| Event | Price | Charged | Worked example |
| --- | --- | --- | --- |
| `page-ocr` | $0.003 | per image or scanned PDF page read by OCR | A 10-page scanned PDF = $0.03; 1,000 receipts = $3.00 |
| `page-text` | $0.0003 | per PDF page that already has a text layer (read directly, no OCR) | A 100-page digital PDF = $0.03 |
| `apify-actor-start` | $0.00005 | per run per GB of memory (platform start fee) | One run at 4 GB = $0.0002 |

### Input options

| Field | Type | Required | Default | Description |
| --- | --- | --- | --- | --- |
| `urls` | array | yes | — | Links to scanned PDFs or images (PNG, JPEG, TIFF, WebP, GIF, BMP, JPEG 2000). Each image is one page. |
| `languages` | array | no | `["eng"]` | Languages in the documents (up to 4). Picking only the languages you need is faster and more accurate. |
| `pdfMode` | string | no | `"auto"` | Auto: pages that already contain text are read directly (exact, and charged at the cheaper text-layer price); only scanned pages are OCR'd. OCR all: OCR every page, e.g. when a PDF's hidden text layer is poor. |
| `outputMode` | string | no | `"document"` | For PDFs: one row per PDF with all pages, or one row per page. Images are always one row each. |
| `includeWords` | boolean | no | `false` | Add every recognised word with its confidence and pixel box (left, top, width, height), e.g. for redaction, highlighting or form extraction. |
| `minWordConfidence` | integer | no | `0` | Drop words Tesseract is less sure of than this (0–100). 0 keeps everything; 40–60 removes most noise from stains and stamps. |
| `pageSegmentation` | string | no | `"auto"` | How Tesseract finds text. Auto suits most pages; Single column for uniform text; Single block for receipts and snippets; Sparse for scattered text like forms and screenshots. |
| `dpi` | integer | no | `300` | Resolution scanned PDF pages are rendered at before OCR. 300 is the accuracy sweet spot; 200 is faster for large print. |
| `maxPagesPerPdf` | integer | no | `200` | Process at most this many pages of each PDF (from the start). Longer PDFs are marked truncated. |
| `maxFiles` | integer | no | `1000` | Stop after this many files. |
| `password` | string | no | — | For password-protected PDFs you are entitled to open. Used for every PDF in the run. |

### Limits & honest notes

- Tesseract reads printed and typed text very well (95%+ confidence on clean scans); handwriting, low-resolution photos, heavy stamps and decorative fonts come out poorly. The confidence score tells you which pages to check.
- Output is plain text in reading order with line and paragraph breaks. Tables come out as lines of text, not structured tables. Images and charts have no text to extract.
- Pages rotated by 90° or 180° are not auto-rotated; slightly skewed scans are fine.
- Up to 4 languages per run; picking only the languages your documents use is faster and more accurate. Modern Greek is not available.
- HEIC/AVIF photos and SVG are not supported (convert photos to JPEG). Files up to 100 MB; PDFs up to 2,000 pages each (200 by default).
- Password-protected PDFs need the password input. Links that return a web page instead of a file are reported and not charged.
- Respects your run budget: set a maximum total charge and processing stops cleanly at the cap, with no page charged twice.

### Related ActorForge actors

- [PDF OCR](https://apify.com/actor-forge/pdf-ocr)
- [Image to Text OCR](https://apify.com/actor-forge/image-to-text-ocr)
- [PDF to Markdown](https://apify.com/actor-forge/pdf-to-markdown) — for digital PDFs with a text layer
- [Word, Excel & PowerPoint to Markdown](https://apify.com/actor-forge/office-to-markdown)

### Changelog

- **2026-10-19** — Initial release: Tesseract 5 OCR (fast LSTM models) for images and scanned PDFs in 29 languages, smart text-layer mode for PDFs, per-page confidence, optional word boxes.

***

*Built and maintained by **ActorForge**. Reliability first: every actor in the
portfolio is monitored by an automated nightly self-test, and breakages are
typically fixed the same day.*

# Actor input Schema

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

Links to scanned PDFs or images (PNG, JPEG, TIFF, WebP, GIF, BMP, JPEG 2000). Each image is one page.

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

Languages in the documents (up to 4). Picking only the languages you need is faster and more accurate.

## `pdfMode` (type: `string`):

Auto: pages that already contain text are read directly (exact, and charged at the cheaper text-layer price); only scanned pages are OCR'd. OCR all: OCR every page, e.g. when a PDF's hidden text layer is poor.

## `outputMode` (type: `string`):

For PDFs: one row per PDF with all pages, or one row per page. Images are always one row each.

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

Add every recognised word with its confidence and pixel box (left, top, width, height), e.g. for redaction, highlighting or form extraction.

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

Drop words Tesseract is less sure of than this (0–100). 0 keeps everything; 40–60 removes most noise from stains and stamps.

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

How Tesseract finds text. Auto suits most pages; Single column for uniform text; Single block for receipts and snippets; Sparse for scattered text like forms and screenshots.

## `dpi` (type: `integer`):

Resolution scanned PDF pages are rendered at before OCR. 300 is the accuracy sweet spot; 200 is faster for large print.

## `maxPagesPerPdf` (type: `integer`):

Process at most this many pages of each PDF (from the start). Longer PDFs are marked truncated.

## `maxFiles` (type: `integer`):

Stop after this many files.

## `password` (type: `string`):

For password-protected PDFs you are entitled to open. Used for every PDF in the run.

## Actor input object example

```json
{
  "urls": [
    "https://github.com/tesseract-ocr/tessdoc/raw/main/images/eurotext.png"
  ],
  "languages": [
    "eng"
  ],
  "pdfMode": "auto",
  "outputMode": "document",
  "includeWords": false,
  "minWordConfidence": 0,
  "pageSegmentation": "auto",
  "dpi": 300,
  "maxPagesPerPdf": 200,
  "maxFiles": 1000
}
```

# Actor output Schema

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

One row per file (or per page) with the extracted text, confidence and page counts.

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

Files processed, pages OCR'd vs read from the text layer, failures (not 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 = {
    "urls": [
        "https://github.com/tesseract-ocr/tessdoc/raw/main/images/eurotext.png"
    ]
};

// Run the Actor and wait for it to finish
const run = await client.actor("actor-forge/ocr-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://github.com/tesseract-ocr/tessdoc/raw/main/images/eurotext.png"] }

# Run the Actor and wait for it to finish
run = client.actor("actor-forge/ocr-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://github.com/tesseract-ocr/tessdoc/raw/main/images/eurotext.png"
  ]
}' |
apify call actor-forge/ocr-to-text --silent --output-dataset

```

## MCP server setup

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