Image to Text OCR: Extract Text from Images, Bulk OCR API avatar

Image to Text OCR: Extract Text from Images, Bulk OCR API

Pricing

from $3.50 / 1,000 images

Go to Apify Store
Image to Text OCR: Extract Text from Images, Bulk OCR API

Image to Text OCR: Extract Text from Images, Bulk OCR API

Extract text from images in bulk with Tesseract OCR: image URLs (PNG, JPEG, WebP, TIFF, GIF, BMP or one-page scanned PDFs) in, text out, with a confidence score, image size and optional line and word boxes. 32 languages incl. Chinese, Japanese and Arabic. Pay per image.

Pricing

from $3.50 / 1,000 images

Rating

0.0

(0)

Developer

Michael Costa

Michael Costa

Maintained by Community

Actor stats

0

Bookmarked

2

Total users

2

Monthly active users

4 hours ago

Last modified

Share

What does Image to Text OCR do?

Image to Text OCR extracts text from images in bulk. Give it links to PNG, JPEG, WebP, TIFF, GIF or BMP files, or one-page scanned PDFs; you get the text, a confidence score and, optionally, every line and word with its position in pixels.

It runs Tesseract, the open-source OCR engine, inside the actor, in 32 languages: nothing is sent to a third-party OCR service. It reads only the images you list.

Input fields · API · Use it from Claude, ChatGPT or Cursor (MCP)

Jump to: Fields · Price · How to use · Input · Output · Chain after another actor · AI agents (MCP) · Limits · FAQ

Try it in one click: the input comes pre-filled with two small public-domain scans from Wikimedia Commons (a newspaper clipping and a book page). That's 2 images, about $0.008 (2 × $0.004, plus $0.00005 for the run start). Then replace them with your own images.

What data does Image to Text OCR return?

FieldExampleNotes
text-—A favorite copy set by writing teachers\n...Lines end with a newline; blocks are separated by a blank line.
confidence82.1Mean word confidence, 0-100. Under ~60 usually means a poor image or the wrong language.
wordCount, lineCount29, 4
lines[{"text": ..., "confidence": ..., "left": ..., "top": ..., "width": ..., "height": ...}]With Include lines with positions; else null.
words[{"text": "favorite", "confidence": 96.4, "left": 103, "top": 13, "width": 119, "height": 24}]With Include words with positions; else null.
width, height690, 150The image as read (upright; PDFs rendered at 300 DPI).
format, fileSizeBytes, fileNamepng, 28520, The_Quick_Brown_Fox_Newspaper_Reference.pngRead from the file itself.
languages, pageSegmentation["eng"], autoWhat you asked for.
truncated, truncatedReasonsfalse, []E.g. an animated GIF (only the first frame is read).
sourceTitle, sourceIndex"Receipt printer paper", 12From the dataset item the link came from (see Chain it after another actor); null for URLs you type in.

One result per image. The full list is under Output.

How much does it cost to extract text from images?

You pay per image that gives you text: $4.00 per 1,000 images, plus $0.00005 each time a run starts.

It's cheaper on paid Apify plans: $3.80 per 1,000 images on Starter, $3.60 on Scale and $3.50 on Business. The prices on this page are the Free-plan price, so on a paid plan you pay less than the examples show.

  • The example below: 2 images × $0.004 = $0.008, plus the start fee.
  • A month, for example: 2,000 scans × $0.004 = $8.00.
  • Caps: Max images per run in the input, and Maximum cost per run in the run options. The run stops cleanly at whichever comes first; it stops downloading as soon as the limit is covered, so a capped run is also a fast one.

Never charged: images with no text, and images that fail (not found, blocked, not an image, too large, a multi-page file, an SVG or HEIC photo).

How to extract text from an image

  1. Open Image to Text OCR and click Try for free (or Start if you're signed in).
  2. Put direct links to your images in Image URLs, one per line.
  3. Optional: pick the Languages, the Layout (e.g. scattered text for screenshots and signs), and turn on Include lines with positions or Include words with positions for bounding boxes.
  4. Click Start, then open the Output tab and export as JSON, CSV or Excel.

Example: two public-domain scans

The pre-filled input:

{"urls": ["https://upload.wikimedia.org/wikipedia/commons/d/d7/The_Quick_Brown_Fox_Newspaper_Reference.png",
"https://upload.wikimedia.org/wikipedia/commons/2/24/Scan_of_%22Proceedings_of_the_Cambridge_Philosophical_Society_19_%281917-1920%29%22_%28English%2C_page_36%29.png"],
"languages": ["eng"], "pageSegmentation": "auto"}

The first image's result (real output from a local run on 2026-09-25, OCR mistakes included):

{
"id": "c317d5a4b899024d1b737ef0",
"fileName": "The_Quick_Brown_Fox_Newspaper_Reference.png",
"format": "png",
"width": 690,
"height": 150,
"text": "-—A favorite copy set by writing teachers\nfor their pupils is the following, bevause.:it\ncontains: every letter in the alphabet: “A\nquick brown fox: jumps ‘over the lazy dog.”",
"confidence": 82.1,
"wordCount": 29,
"lineCount": 4
}

The book page gave 383 words at a confidence of 85.6. Exact characters can vary slightly between Tesseract versions on noisy scans like these.

Ready-to-run examples

Each example opens with the input already filled in. Run it as it is, or change the input first.

Input

FieldWhat it does
Image URLsDirect links to the images, one per line. The format is read from the file, so links without an extension work.
Or: image links from a dataset (datasetId)One of your Apify datasets, e.g. another actor's results: each item's image link is read and Image URLs is ignored. See Chain it after another actor.
Field with the image link (datasetUrlField)Only with a dataset. Empty (default): found automatically among imageUrl, image, displayUrl, images, src and url, then one level down.
LanguagesThe language(s) of the text (up to 4). Default: English.
LayoutAutomatic (pages, documents), automatic with rotated-text detection, one block, one line, or scattered text (screenshots, signs, diagrams).
Include lines with positionsAdds lines: each line's text, confidence and box.
Include words with positionsAdds words: each word's text, confidence and box.
Max images per runCap the number of images read.
{
"urls": [
"https://upload.wikimedia.org/wikipedia/commons/d/d7/The_Quick_Brown_Fox_Newspaper_Reference.png"
],
"languages": ["eng"],
"pageSegmentation": "auto",
"includeWords": true,
"maxResults": 100
}

Languages: English, German, French, Spanish, Italian, Portuguese, Dutch, Polish, Czech, Slovak, Swedish, Danish, Norwegian, Finnish, Hungarian, Romanian, Turkish, Greek, Russian, Ukrainian, Bulgarian, Arabic, Hebrew, Hindi, Bengali, Thai, Vietnamese, Indonesian, Japanese, Chinese (Simplified), Chinese (Traditional) and Korean. Pick every language that appears in your images; each extra one makes reading slower.

Output

One result per image. Fields that don't apply are null.

{
"id": "5b1c0f6e2d9a4c7e8f3a1b2c",
"url": "https://upload.wikimedia.org/wikipedia/commons/d/d7/The_Quick_Brown_Fox_Newspaper_Reference.png",
"finalUrl": "https://upload.wikimedia.org/wikipedia/commons/d/d7/The_Quick_Brown_Fox_Newspaper_Reference.png",
"fileName": "The_Quick_Brown_Fox_Newspaper_Reference.png",
"format": "png",
"fileSizeBytes": 28520,
"width": 690,
"height": 150,
"frameCount": 1,
"renderDpi": null,
"languages": ["eng"],
"pageSegmentation": "auto",
"text": ":—A favorite copy set by writing teachers\nfor their pupils is the following, bevause.it\ncontains: every letter in the alphabet: “A\nquick brown fox: jumps‘over the lazy dog.”",
"confidence": 86.2,
"wordCount": 28,
"lineCount": 4,
"lines": null,
"words": [
{"text": "favorite", "confidence": 96.4, "left": 103, "top": 13, "width": 119, "height": 24}
],
"truncated": false,
"truncatedReasons": [],
"scrapedAt": "2026-09-24T18:00:00Z",
"sourceTitle": null,
"sourceIndex": null
}
  • text: lines end with a newline; paragraphs and blocks are separated by a blank line.
  • confidence: the mean confidence of the words, 0 to 100 (per line and per word in lines and words). Under ~60 usually means a blurry, tiny or stylised image, or the wrong language.
  • width and height are the image as read: upright, and for PDFs the page rendered at renderDpi (300 DPI). Boxes are in those pixels.
  • id is stable for the same URL across runs, so you can use it to deduplicate.
  • truncated is true when not everything was read, e.g. an animated GIF (only the first frame is read).
  • sourceTitle / sourceIndex: for links read from a dataset, the item's title (or name) and its position in the dataset (0 = the first); null for URLs you type in.

Run it on a schedule, or from your own code

  1. Save your input as a task (Save as a new task, top right of the actor page) and add it to a schedule (Console → Schedules → Create new): for example nightly over the day's new scans, if they're published at links you can list. Every run reads, and charges for, every image that gives text.
  2. Collect results: download the dataset as JSON, CSV or Excel; fetch the latest run's results from the API (GET https://api.apify.com/v2/actor-tasks/<task id>/runs/last/dataset/items?status=SUCCEEDED&format=csv, with your API token); let a webhook tell your system when a run succeeds; or connect it to Make, Zapier or n8n through Apify's integrations.

Chain it after another actor

To read the text in the images another actor found, right after it finishes, chain it with an integration (any actor, ours or not: an image downloader, a shop or Instagram scraper):

  1. Open the other actor or its saved task, go to the Integrations tab and add Apify actor → Image to Text OCR, triggered when a run succeeds.
  2. Set "datasetId": "{{resource.defaultDatasetId}}" in the input (Apify fills in the finished run's dataset). Leave datasetUrlField empty to find the link automatically (imageUrl, image, displayUrl, images, src, then url), or name the field, e.g. "datasetUrlField": "product.mainImage". Add maxResults to cap each run.

Every successful scrape then comes back as text, with no code. Image URLs is ignored when a dataset is given, so its example scans are never read or charged. For example, after Bulk Image Downloader each image it found (imageUrl) is read, once even when several pages show it. Each link is read and charged like one you type in; items without a link are skipped and counted in RUN_STATS (dataset.withoutWebsite, dataset.notAWebsite). At most the first 20,000 items and 10,000 distinct links of a dataset are read per run, with your own account's access, read-only. From the API it's the same input: pass the finished run's defaultDatasetId as datasetId.

Can I use Image to Text OCR from an AI agent (MCP)?

Yes, through Apify's MCP server, from Claude, ChatGPT, Cursor or any other MCP client. Add this to your client's MCP configuration (or let the agent find it with the server's actor search); your client signs you in to Apify:

{
"mcpServers": {
"apify": {
"url": "https://mcp.apify.com?tools=humble-echidna/image-ocr"
}
}
}

To use an Apify API token instead of signing in, add "headers": {"Authorization": "Bearer <APIFY_TOKEN>"} next to url.

The agent passes image links, e.g. {"urls": ["https://example.com/receipt.png"], "languages": ["eng"]}, and reads text and confidence back.

Who it's for

Anyone with images of printed text at public links who needs the text as data: scanned pages and clippings for archives and research, screenshots and signs, one-page scanned forms. With word positions on, it also suits redaction and pulling fields from forms.

Why this one?

  • One flat price, no usage bill. You pay per result at the price above and nothing else: no compute, proxy or storage charges on top, apart from the $0.00005 run-start fee, so you know what a run costs before it starts. Results you don't get aren't charged.
  • Text, lines and words that agree. One recognition pass gives the plain text, the lines and the words, so a word's box always matches the text you got. Turn on Include lines or Include words for bounding boxes (left, top, width, height in pixels) and a confidence per line and word: good for highlighting, redaction, pulling fields from forms, or throwing away low-confidence words.
  • Photos come out right. Phone photos are turned upright from their orientation tag before reading, transparent images are put on white (dark text on a transparent background reads as text, not as a black square), and 16-bit and CMYK images are handled.
  • Honest about what it couldn't read. An image with no text, a multi-page file, a damaged file, an SVG or an iPhone HEIC photo is reported in the log and in the RUN_STATS record with the reason, and never charged. You only pay for images that gave you text.
  • Safe with untrusted files. Each image is decoded and read in its own process with a time and memory limit, and anything over 50 megapixels (including "decompression bombs": small files that unpack to gigapixels) is refused before it's unpacked. One bad file never stops the others.
  • Polite. It identifies itself honestly (User-Agent HumbleEchidnaApify), follows each site's robots.txt (read once per site per run), including opt-outs for AI crawlers (GPTBot, CCBot, ClaudeBot, Google-Extended and the like), and only requests public web addresses on the standard ports (80 and 443).

Limits

  • Formats: PNG, JPEG, WebP, TIFF, GIF, BMP, and PDFs with one page. Animated GIF and WebP: the first frame. Multi-page TIFFs and PDFs are refused (not charged): split them into one image per page. SVG and HEIC/HEIF (iPhone photos) aren't read: export them as PNG or JPEG.
  • Size: at most 40 MB and 50 megapixels per image, 2 GB of downloads per run (start another run for more).
  • Time: at most 3 minutes per image.
  • Handwriting and heavily stylised text are read poorly: Tesseract is built for printed text.

FAQ

Why does the text have mistakes or miss parts of the image?

OCR is only as good as the image. Text should be at least ~20 pixels high: upscale small screenshots before sending them. Pick the right language(s). For screenshots, signs and diagrams, try the Scattered text layout; for a single label, One line; for sideways scans, Automatic, and detect rotated text. Use confidence (or the per-word confidences) to spot what to check.

My PDF already has text in it. Do I need OCR?

No: a PDF-to-text converter (such as our PDF to Text Converter) reads the text layer exactly and faster. This actor is for scans and photos.

Something that used to work now fails. Why?

The run log names the image and what went wrong, and every other image in the run is unaffected. Please open an issue with the input you used.

The actor downloads only the images you list, as a logged-out visitor, and honours each site's robots.txt, including its opt-outs for AI crawlers. Make sure you have the right to process the images you send: the actor reads whatever text is in them, which can include personal data if your images contain it. It keeps nothing: images are deleted as soon as they're read, and the text goes only to your own dataset. The OCR engine is Tesseract (Apache-2.0) with its language models (Apache-2.0); images are decoded with Pillow (MIT-CMU) and PDFs rendered with PDFium via pypdfium2 (BSD-3/Apache-2.0).

ActorUse it when
PDF to Text ConverterYou have multi-page PDFs (scanned or not), Word or Excel. It uses the same OCR for scanned pages, and reads PDFs that already have text directly, without OCR.
Bulk Image DownloaderYou want to collect the images from web pages first.

Feedback and support

Found a bug, or an image that reads badly? Open an issue on the Issues tab with the link you used.

Versions

Current version: 1.1. See the Changelog tab for what changed in each version.