Image to Text OCR — Bulk, 30 Languages, Lines
Pricing
from $1.50 / 1,000 image with texts
Image to Text OCR — Bulk, 30 Languages, Lines
Extract text from images by URL with OCR: screenshots, scans, photos, receipts. 30 languages, text plus lines with confidence and position. One flat row per URL, never null; only images with text are billed. PNG, JPEG, WebP, TIFF, GIF, BMP.
Pricing
from $1.50 / 1,000 image with texts
Rating
0.0
(0)
Developer
Sumitr Mardy
Maintained by CommunityActor stats
0
Bookmarked
2
Total users
1
Monthly active users
4 hours ago
Last modified
Categories
Share
Give it image links, get back the text in each image. Screenshots, scanned pages, photos of documents, receipts, signs. 30 languages, plus every text line with its confidence and position when you want it. One flat row per URL, every field always present, never null, built to be called from pipelines, n8n/Make/Zapier flows and AI agents.
$2 per 1,000 images with text, down to $1.50 on Gold. Images with no text, failed downloads and broken files are free.
Why this one
- One row for every URL you send. A 404, an HTML page, a PDF sent by mistake or a corrupt file still comes back as a row with
status: "failed"and a machine-readablesubStatus. You never have to diff your input against the output. - You pay for text, not for attempts. An image is billed only when OCR found text in it.
- Confidence you can filter on. Every row has
meanConfidence(0–100). Turn onincludeLinesto get each line with its own confidence and pixel box, in the original image's coordinates. - Images are prepared for OCR. EXIF rotation is applied, transparent PNGs are flattened onto white, small screenshots are upscaled and huge photos scaled down to the size Tesseract reads best.
- Fast. On Apify at the default 2 GB: a 640×500 screenshot in 0.5–1 s, an 11-megapixel scan in 2.7 s, download included.
Input
| Field | Default | What it does |
|---|---|---|
urls | — | Image links, one per item: PNG, JPEG, WebP, TIFF, GIF (first frame), BMP, AVIF. Google Drive and Dropbox share links work. Required. |
ocrLanguage | eng | Tesseract language code; join up to 3 with + (eng+vie). 30 built in, including vie, chi_sim, chi_tra, jpn, kor, ara, hin, rus, tha. |
layout | auto | auto for documents and screenshots, sparse for text scattered over a photo (memes, signs, UI), block for one cropped paragraph. |
includeLines | false | Adds lines[]: each line's text, confidence and box. |
maxFileSizeMb | 20 | Larger files fail as too_large, uncharged (max 50). |
downloadTimeoutSecs | 30 | Total time for one download. Slower URLs fail as download_timeout, uncharged. |
maxConcurrency | 8 | Parallel downloads. OCR runs one image per CPU core (1 core per 4 GB). |
proxyConfiguration | off | Optional. Hosts answering 401/403/429 are retried once through Apify's datacenter proxy anyway. |
{"urls": ["https://raw.githubusercontent.com/tesseract-ocr/tessdoc/main/images/eurotext.png"],"ocrLanguage": "eng","includeLines": true}
Output
One row per input URL, in completion order; inputIndex lines rows up with your input. A real row (shortened):
{"inputIndex": 0,"url": "https://raw.githubusercontent.com/tesseract-ocr/tessdoc/main/images/eurotext.png","resolvedUrl": "https://raw.githubusercontent.com/tesseract-ocr/tessdoc/main/images/eurotext.png","status": "ok","subStatus": "text_found","error": "","text": "The (quick) [brown] {fox} jumps!\nOver the $43,456.78 <lazy> #90 dog\n…","charCount": 414, "wordCount": 66, "lineCount": 12,"meanConfidence": 91.4,"lines": [{ "text": "The (quick) [brown] {fox} jumps!", "confidence": 96.1, "left": 65, "top": 41, "width": 450, "height": 30 }],"language": "eng","imageFormat": "png", "width": 640, "height": 500, "fileSizeBytes": 31481,"notes": [],"processingMs": 1027}
Strings are "" when absent, numbers 0, arrays []. No field is ever null or missing. text keeps reading order: lines are separated by \n, paragraphs by a blank line.
Status
status | subStatus | Charged |
|---|---|---|
ok | text_found | yes |
no_text | no_text_found: the image was read and has no text | free |
failed | http_404 (any http_<code>), not_an_image, unsupported_format (HEIC), too_large, download_timeout, download_error, corrupt_image, ocr_timeout, ocr_error, invalid_url, cost_limit_reached, free_work_limit | free |
A PDF sent by mistake fails as not_an_image with a pointer to PDF Text Extractor, which reads text layers and OCRs scanned pages.
Pricing
| Event | Price | When |
|---|---|---|
image-ocr | $2.00 per 1,000 (free plan), $1.80 Bronze, $1.60 Silver, $1.50 Gold | An image with text (status: "ok") |
The only other charge is a start fee of $0.0005 per GB of memory per run ($0.001 at the default 2 GB). No platform usage is added on top. A run stops starting new images when your maximum cost per run is reached, and marks the rest cost_limit_reached, uncharged.
Fair use
Failed and no-text rows are free, so a run that spends its compute on URLs that fail stops starting new ones. The rest come back as failed / free_work_limit, uncharged, and can be resubmitted. Ordinary lists with a share of dead links never get near this. Also: at most 3 OCR languages per run, a 50 MB file cap, 80 megapixels per image, datacenter proxy only.
What it does not do (yet)
- Tesseract, not a vision model. Very good on screenshots, scans and photos of printed text (confidence 85–96 in our tests). Weaker on handwriting, heavy blur, curved or stylised text and very low resolution. Check
meanConfidence: under ~60 the text is likely noisy. - No table structure. Table rows come out as lines; use
includeLinesboxes to rebuild columns. - One frame only for animated GIFs and multi-page TIFFs;
notessays so. For multi-page documents use PDF Text Extractor. - No HEIC. Convert iPhone photos to JPEG first.
Use it from AI agents (MCP)
This Actor is a tool on the Apify MCP server, so Claude, Cursor, VS Code or any MCP client can call it to read text in an image. Load only this tool: a short tool list keeps the agent from picking the wrong one.
Recommended: hosted server, OAuth sign-in (nothing secret on disk). Add to your MCP client config (claude_desktop_config.json, .cursor/mcp.json, …):
{"mcpServers": {"image-ocr": {"url": "https://mcp.apify.com?tools=sumitr_mardy/image-to-text-ocr"}}}
With an API token instead (clients without OAuth, or unattended setups):
{"mcpServers": {"image-ocr": {"url": "https://mcp.apify.com?tools=sumitr_mardy/image-to-text-ocr","headers": { "Authorization": "Bearer YOUR_APIFY_TOKEN" }}}}
Local server (stdio):
{"mcpServers": {"image-ocr": {"command": "npx","args": ["-y", "@apify/actors-mcp-server@latest", "--tools", "sumitr_mardy/image-to-text-ocr"],"env": { "APIFY_TOKEN": "YOUR_APIFY_TOKEN" }}}}
The hosted server also gives the agent this Actor's output schema, so it knows every field before the first call. apify mcp install <client> writes the config for you if you use the Apify CLI. Get a token at Apify Console → API & Integrations, and never commit it.
Tips for agents:
- "What does this screenshot say?": pass the link in
urls, readtext. Checkstatusfirst;no_textandfailedrows carry the reason insubStatusanderror. - Non-English text: set
ocrLanguage(vie,jpn,chi_sim…). The wrong language shows up as a lowmeanConfidence. - Text on a photo (a sign, a product label, a meme):
layout: "sparse". - Need positions (to highlight, crop or rebuild a table)?
includeLines: true. - The MCP
call-actortool waits up to 45 seconds; a few images finish well inside that.
Use it from code
from apify_client import ApifyClientclient = ApifyClient("<APIFY_TOKEN>")run = client.actor("sumitr_mardy/image-to-text-ocr").call(run_input={"urls": ["https://raw.githubusercontent.com/tesseract-ocr/test/main/testing/phototest.tif"],})for row in client.dataset(run["defaultDatasetId"]).iterate_items():print(row["status"], row["meanConfidence"], row["text"][:80])
curl -X POST "https://api.apify.com/v2/acts/sumitr_mardy~image-to-text-ocr/run-sync-get-dataset-items?token=<APIFY_TOKEN>" \-H "Content-Type: application/json" \-d '{"urls": ["https://raw.githubusercontent.com/tesseract-ocr/tessdoc/main/images/eurotext.png"]}'