# OCR API — Image & Scanned PDF to Text, 100+ Languages (`highbrow_fame/ocr-api`) Actor

OCR API: text, confidence, paragraphs and word boxes from images and scanned PDFs for $2 per 1,000 images. Tesseract OCR by URL, optional hOCR/TSV, many languages. Unofficial OCR API.

- **URL**: https://apify.com/highbrow_fame/ocr-api.md
- **Developed by:** [yestrue](https://apify.com/highbrow_fame) (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 $1.40 / 1,000 images

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

## OCR API — Image & Scanned PDF to Text, 100+ Languages

Turn **images and scanned PDF pages into text** by URL: the full text, a confidence score, paragraphs and words with bounding boxes, optional hOCR / TSV, many languages. One record per image or PDF page.

**Price:** $2.00 per 1,000 images (one PDF page = one image) on the Free plan, from $1.40 on higher Apify plans. Images with no recognisable text and failed downloads are free.

**[Run it now](https://console.apify.com/actors/pRoibtoZkJXUYVifN/input)** — the Input tab is prefilled, one click starts a run.

| Type | Size px | Words | Confidence | Text | ms |
|---|---|---|---|---|---|
| png | 1486×668 | 58 | 93.5 | Mild Splendour of the various-vested Ni… | 1032 |
| png | 1486×668 | 96 | 92.6 | O Tannenbaum © Tannenbaum, O Tannenbaum… | 1690 |
| pdf | 1190×1684 | 3 | 95.7 | Dummy PDF file | 216 |

*Sample rows from a live run on 2026-10-19; every record has more fields.*

Read the text out of images at public links — screenshots, photos of documents, scanned pages, labels — and out of the first pages of scanned PDFs, with the open-source Tesseract engine (tesseract.js). Every record carries the text, a mean confidence score, the paragraphs with their pixel bounding boxes, and optionally every word, the hOCR layout or tesseract's TSV. Pick the languages (English ships with the Actor; a hundred more download on demand) and the page segmentation mode that fits your images. No API key, no upload: give it links, get text.

**Try it in 1 minute:**

1. Press **Start** — the prefilled input reads tesseract's two demo images, an English poem and a German paragraph, with the languages set to `eng` and `deu` (German data is fetched once at the start of the run).
2. The **Output** tab shows one record per image: the text, confidence, word and line counts and the paragraphs with their boxes. In a test on 19 October 2026 the 1486 × 668 px English demo image gave 58 words at confidence 93.5 in 1,364 ms, after 476 ms to start the worker.
3. Download JSON, CSV or Excel, or call the Actor from the API, Make, Zapier, n8n or an AI agent through the Apify MCP server.

Price: **$2.00 per 1,000 images** on the Free plan, from **$1.40** on higher Apify plans (one PDF page = one image). Images with no recognisable text, missing files, web pages and unsupported files are free.

**Use it to:**

- Make screenshots, memes, receipts and photographed documents searchable or readable by an LLM.
- Read scanned PDFs page by page — the ones a PDF text extractor returns empty — up to 50 pages per file.
- Extract labels, serial numbers or captions from product photos with the bounding box of every word.
- Check which parts of an image were read with low confidence before trusting them, with `minConfidence`.
- Feed hOCR or TSV to your own layout analysis, highlighting or redaction tools.

### How it works

1. Each link is downloaded directly (the proxy only retries a download that failed on the network). The bytes decide what the file is: PNG, JPEG, WebP, BMP, GIF, TIFF or PDF. A web page, an SVG or anything else is a free `NOT_AN_IMAGE` record.
2. One Tesseract worker per concurrency slot (default 2) is started once with your languages and page segmentation mode, then reused for every image. English language data is built into the Actor image; other languages are downloaded once per run from tesseract.js's CDN (a few MB each).
3. A PDF is rendered page by page with pdf.js at about 144 dpi, and each page is read like an image — one record per page with `page` and `pageCount`.
4. Tesseract's result is flattened: the whole text, the mean word confidence, counts, the paragraphs as `blocks[]` with boxes, and — if you ask — `words[]`, `hocr` or `tsv`. An image in which nothing was read comes back as a free `NO_TEXT` record instead of an empty success.

### Input

| Field | What it does |
|---|---|
| `urls` | Public image or PDF links, one per line. Required. |
| `languages` | Tesseract codes, default `["eng"]`; several are combined (`eng`, `deu` → `eng+deu`). Only letters and underscores are valid (`chi_sim`, `chi_tra`, `jpn`, `ara`…). |
| `outputFormat` | `text` (default), `hocr` (adds the hOCR HTML) or `tsv` (adds tesseract's TSV). Text is always delivered. |
| `includeBlocks` | `blocks[]` paragraphs with text, confidence and bbox (default on). |
| `includeWords` | `words[]` every word with confidence and bbox (default off). |
| `minConfidence` | Count words under this confidence in `wordsBelowMinConfidence`; the text is never cut (default 0 = off). |
| `psm` | Page segmentation mode 0-13 (default 3, automatic; 6 for a uniform block such as a screenshot, 7 one line, 11 sparse text). |
| `maxPdfPages` | PDF pages to read from the start (default 5, max 50). |
| `maxConcurrency` | Tesseract workers (1-4, default 2). OCR is CPU-bound. |
| `proxyConfiguration` | Used only for network retries. |

### Output

One record per image or PDF page:

| Field | What it is |
|---|---|
| `url`, `contentType`, `bytes`, `type` | Final address, server content type, file size, type from the bytes (`png`, `jpeg`, `webp`, `bmp`, `gif`, `tiff`, `pdf`) |
| `page`, `pageCount` | PDF only |
| `width`, `height` | Pixels, from the file header (for a PDF page: of the rendered image) |
| `languages` | The codes used |
| `text`, `confidence`, `wordCount`, `lineCount`, `blockCount` | The text, mean word confidence 0-100, counts |
| `wordsBelowMinConfidence` | Words under `minConfidence` |
| `blocks[]` | `{ text, confidence, bbox: { x0, y0, x1, y1 } }` per paragraph |
| `words[]` | `{ text, confidence, bbox }` with `includeWords` |
| `hocr`, `tsv` | With `outputFormat` hocr / tsv |
| `durationMs` | Recognition time |
| `input`, `status`, `error`, `scrapedAt` | What you gave, and why a link gave no text |

Statuses: `OK` (charged), `NO_TEXT`, `NOT_FOUND`, `NOT_AN_IMAGE`, `NOT_SUPPORTED`, `TOO_BIG`, `INVALID_INPUT`, `FAILED` (all free).

#### Example

The real record for tesseract's demo image, 19 October 2026 (`blocks[0].text` shortened):

```json
{
  "input": "https://tesseract.projectnaptha.com/img/eng_bw.png",
  "url": "https://tesseract.projectnaptha.com/img/eng_bw.png",
  "contentType": "image/png",
  "bytes": 26854,
  "type": "png",
  "width": 1486,
  "height": 668,
  "languages": ["eng"],
  "text": "Mild Splendour of the various-vested Night!\nMother of wildly-working visions! hail\nI watch thy gliding, while with watery light\nThy weak eye glimmers through a fleecy veil;\nAnd when thou lovest thy pale orb to shroud\nBehind the gather’d blackness lost on high;\nAnd when thou dartest from the wind-rent cloud\nThy placid lightning o’er the awaken’d sky.",
  "confidence": 93.5,
  "wordCount": 58,
  "lineCount": 8,
  "blockCount": 1,
  "wordsBelowMinConfidence": 0,
  "blocks": [
    { "text": "Mild Splendour of the various-vested Night!\nMother of wildly-working visions! hail\n…", "confidence": 93.5, "bbox": { "x0": 28, "y0": 34, "x1": 1454, "y1": 640 } }
  ],
  "durationMs": 1364,
  "status": "OK",
  "scrapedAt": "2026-10-19T13:05:12.000Z"
}
```

### FAQ

**Is this an official API?** No, it's an unofficial API built on public files and the open-source Tesseract engine (tesseract.js) — there is no OCR vendor behind it, and no image leaves the Apify run.

**How accurate is it?** Tesseract reads clean, horizontal, reasonably large print very well (the demo above: 93.5 mean confidence) and struggles with handwriting, tiny text, strong skew or busy backgrounds. For such images a higher-resolution source, a crop, or the right `psm` helps more than anything else. Use `confidence`, `blocks[].confidence` and `minConfidence` to judge each result.

**Which languages?** Any Tesseract 4/5 language code: `eng`, `deu`, `fra`, `spa`, `por`, `ita`, `nld`, `pol`, `rus`, `ukr`, `tur`, `ell`, `jpn`, `kor`, `chi_sim`, `chi_tra`, `ara`, `hin`, `vie` and the rest of the 100+ list. English is built in; others are downloaded once per run. An unknown code makes the run stop with a clear message rather than guess.

**How long does it take and why is concurrency low?** Tesseract is CPU work: 1-3 seconds for a typical screenshot on one CPU, more for a full scanned page. Each worker needs about 150 MB; with 2 workers the Actor reads two images at a time. Give the run more memory (and so more CPU) to raise `maxConcurrency` up to 4.

**Why is a GIF or TIFF sometimes `FAILED`?** The engine reads PNG, JPEG, WebP and BMP reliably; GIF and TIFF are passed to it and work for common encodings, but an exotic compression may be rejected — the record then says so, and it is free.

**Like it?** A short review on the Store page helps other people find this Actor. Something missing or broken? Tell us on the Issues tab — we read every one.

### Related Actors

- [PDF Text Extractor](https://apify.com/highbrow_fame/pdf-text-extractor) — text, pages and metadata from any PDF link
- [PDF to Markdown API](https://apify.com/highbrow_fame/pdf-to-markdown-api) — headings, tables and text of a PDF
- [Office Document to Text API](https://apify.com/highbrow_fame/office-document-to-text-api) — Word, Excel, PowerPoint and EPUB as Markdown
- [Website Screenshot API](https://apify.com/highbrow_fame/website-screenshot-api) — full page and mobile screenshots
- [Article Extractor API](https://apify.com/highbrow_fame/article-extractor-api) — title, author, date and full text of any article

# Actor input Schema

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

Public links to images of text (PNG, JPEG, WebP, BMP; GIF and TIFF are passed to tesseract) or scanned PDFs (first pages rendered and read), one per line. Up to 20 MB per file.

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

Tesseract language codes, e.g. eng, deu, fra, spa, por, ita, nld, pol, rus, tur, jpn, kor, chi_sim, chi_tra, ara, hin — one per line; several are combined (eng + deu). English ships with the Actor; other languages are downloaded once per run (a few MB each).

## `outputFormat` (type: `string`):

The plain text is always delivered. hOCR adds the full layout as HTML (hocr field); TSV adds tesseract's tab-separated table of every word with its box and confidence (tsv field).

## `includeBlocks` (type: `boolean`):

Deliver blocks\[]: each paragraph tesseract found, with its text, confidence and bounding box.

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

Deliver words\[]: every word with its confidence and bounding box. Makes records much larger.

## `minConfidence` (type: `integer`):

Count the words whose confidence (0-100) is below this value in wordsBelowMinConfidence. The text itself is never cut. 0 = off.

## `psm` (type: `integer`):

Tesseract PSM: 3 = fully automatic (default), 4 = single column of variable sizes, 6 = one uniform block of text, 7 = a single line, 8 = a single word, 11 = sparse text, 13 = raw line. Try 6 for screenshots and 11 for scattered labels.

## `maxPdfPages` (type: `integer`):

For PDF links: how many pages from the start to render and read (one record per page).

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

How many images to read at the same time: one tesseract worker per slot. OCR is CPU-bound, so more slots help only with more CPU (raise the run's memory).

## `proxyConfiguration` (type: `object`):

Images are downloaded directly first. The proxy is used only to retry a download that failed on the network.

## Actor input object example

```json
{
  "urls": [
    "https://tesseract.projectnaptha.com/img/eng_bw.png",
    "https://tesseract.projectnaptha.com/img/deu.png"
  ],
  "languages": [
    "eng",
    "deu"
  ],
  "outputFormat": "text",
  "includeBlocks": true,
  "includeWords": false,
  "minConfidence": 0,
  "psm": 3,
  "maxPdfPages": 5,
  "maxConcurrency": 2,
  "proxyConfiguration": {
    "useApifyProxy": true
  }
}
```

# Actor output Schema

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

Every result as a JSON record, with a status for each input.

## `resultsCsv` (type: `string`):

The same records as CSV, for a spreadsheet.

# 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.projectnaptha.com/img/eng_bw.png",
        "https://tesseract.projectnaptha.com/img/deu.png"
    ],
    "languages": [
        "eng",
        "deu"
    ],
    "proxyConfiguration": {
        "useApifyProxy": true
    }
};

// Run the Actor and wait for it to finish
const run = await client.actor("highbrow_fame/ocr-api").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.projectnaptha.com/img/eng_bw.png",
        "https://tesseract.projectnaptha.com/img/deu.png",
    ],
    "languages": [
        "eng",
        "deu",
    ],
    "proxyConfiguration": { "useApifyProxy": True },
}

# Run the Actor and wait for it to finish
run = client.actor("highbrow_fame/ocr-api").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.projectnaptha.com/img/eng_bw.png",
    "https://tesseract.projectnaptha.com/img/deu.png"
  ],
  "languages": [
    "eng",
    "deu"
  ],
  "proxyConfiguration": {
    "useApifyProxy": true
  }
}' |
apify call highbrow_fame/ocr-api --silent --output-dataset

```

## MCP server setup

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

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/pRoibtoZkJXUYVifN/builds/zYvviwSk7Mv103haU/openapi.json
