# Image to Text OCR: images & scanned PDFs, per page (`glistening_film/image-ocr-extractor`) Actor

Turn images and scanned PDFs into text by URL, up to 50 files per run, with per-page confidence scores. Tesseract OCR, 6 languages. $0.005 per OCR'd page, no start fee. Weak on handwriting. Failed, unsupported or empty results are reported but never charged.

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

## Pricing

$5.00 / 1,000 page ocr'ds

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

## Image to Text OCR: images & scanned PDFs, pay per page

Turn **images and scanned PDFs** into clean text by URL, up to 50 files per run. **$0.005 per
OCR'd page, no start fee. Weak on handwriting.** Built for automation pipelines (digitizing paper
documents, RAG ingestion of scans, form and receipt data entry, search indexing).

### Use cases

- Digitizing paper documents and scanned PDFs into searchable text
- RAG ingestion of scanned documents
- Form, label and receipt data entry
- Extracting text from images in a pipeline (png, jpg, tiff, webp, bmp, gif)

### What you get

For each file, one dataset item:

- `status`: `ok`, `download_failed`, `unsupported_format`, `invalid_file`, or `no_text_found`
- `fileType`: detected from the file's content (magic bytes), never the URL extension:
  `pdf`, `png`, `jpg`, `tiff`, `webp`, `bmp`, or `gif`
- `pages[]`: per-page `text`, `meanConfidence` (mean word confidence, 0-100) and `wordCount`
- `fullText`, `totalChars`, `pageCount`, `pagesProcessed`, `truncated`
- `processingMs`, and `error` with a plain-language reason when something fails

PDF pages are rendered with pypdfium2 at your chosen DPI (default 200) and OCR'd with
Tesseract. Images (png, jpg, tiff, webp, bmp, and the first frame of gif) are OCR'd directly.

### Pricing: you only pay for pages that worked

**One `page-ocred` event per processed page of a file that came back `ok` ($0.005).** Failed
downloads, unsupported or invalid files, and OCR runs that found zero words (`no_text_found`)
are **reported in the output but never charged**. There is no start fee. Files with more pages
than your limit are truncated and charged only for the pages actually processed. The run checks
your spending limit before each file, processes at most the pages your remaining limit covers,
and stops cleanly when it is reached.

### Accuracy: Tesseract OCR, open source

The engine is [Tesseract](https://github.com/tesseract-ocr/tesseract), the standard open-source
OCR. It is **good at printed text**: documents, scans, screenshots, forms, labels and photos of
text taken straight-on at reasonable resolution, typically at 200-300 DPI. It is **weak on
handwriting, stylized or tiny fonts, and low-resolution or blurry photos** — expect lower
confidence and occasional misreads there. The per-page `meanConfidence` field tells you how sure
the engine was, so you can route low-confidence pages to review. Six languages are available
out of the box: English, Spanish, French, German, Portuguese and Italian.

### Limits (by design)

- Max 50 URLs per run, max 25 MB per file, max 200 pages per file (default 20).
- Supported inputs: png, jpg, tiff, webp, bmp, gif (first frame), and PDF. Anything else is
  reported as `unsupported_format` and not charged.
- Only public `http(s)` links; local and private-network addresses are refused.
- No table structure or layout detection: output is plain text in reading order.

### FAQ

**Does it work on scanned PDFs?** Yes — PDF pages are rendered at your chosen DPI (default 200)
and OCR'd with Tesseract.

**Is it good on handwriting?** It is weak on handwriting, stylized or tiny fonts, and
low-resolution or blurry photos — expect lower confidence and occasional misreads there. The
per-page `meanConfidence` field tells you how sure the engine was.

**Which languages are supported?** Six out of the box: English, Spanish, French, German,
Portuguese and Italian.

**Do I pay for pages that find no text?** No. Failed downloads, unsupported or invalid files,
and `no_text_found` results are reported but never charged; you pay $0.005 only for pages
actually processed in a file that came back `ok`, with no start fee.

**How are multi-page files charged?** Per processed page, up to your limit; truncated files are
charged only for the pages actually processed.

**What are the limits?** Up to 50 public `http(s)` URLs per run, 25 MB per file, 200 pages per
file (default 20).

### Input example

```json
{
  "urls": ["https://example.com/scan.png"],
  "language": "eng",
  "maxPagesPerFile": 20,
  "dpi": 200
}
```

# Actor input Schema

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

Public http(s) links to images (png, jpg, tiff, webp, bmp, gif first frame) or PDFs (max 50 per run). The file type is detected from its content, not the URL extension. Only files with status ok are charged.

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

Language of the text to recognize (Tesseract language code).

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

Pages beyond this are not OCR'd; the result is marked truncated. Hard cap 200.

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

Resolution at which PDF pages are rendered before OCR. Higher is more accurate and slower (150-400).

## Actor input object example

```json
{
  "urls": [
    "https://raw.githubusercontent.com/tesseract-ocr/test/main/testing/phototest.tif"
  ],
  "language": "eng",
  "maxPagesPerFile": 20,
  "dpi": 200
}
```

# Actor output Schema

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

One dataset item per input URL: status (ok, download\_failed, unsupported\_format, invalid\_file or no\_text\_found), per-page text with mean word confidence, full text, page counts and error reason. Only items with status ok are charged, one page-ocred event per processed page.

# 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/tesseract-ocr/test/main/testing/phototest.tif"
    ]
};

// Run the Actor and wait for it to finish
const run = await client.actor("glistening_film/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": ["https://raw.githubusercontent.com/tesseract-ocr/test/main/testing/phototest.tif"] }

# Run the Actor and wait for it to finish
run = client.actor("glistening_film/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": [
    "https://raw.githubusercontent.com/tesseract-ocr/test/main/testing/phototest.tif"
  ]
}' |
apify call glistening_film/image-ocr-extractor --silent --output-dataset

```

## MCP server setup

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